diff --git a/examples/scripts/functions_called.py b/examples/scripts/functions_called.py index 5f25477d0..4324ac902 100644 --- a/examples/scripts/functions_called.py +++ b/examples/scripts/functions_called.py @@ -16,7 +16,7 @@ entry_point = contract.get_function_from_signature('entry_point()') all_calls = entry_point.all_internal_calls() -all_calls_formated = [f.contract.name + '.' + f.name for f in all_calls] +all_calls_formated = [f.canonical_name for f in all_calls] # Print the result print('From entry_point the functions reached are {}'.format(all_calls_formated)) diff --git a/examples/scripts/possible_paths.py b/examples/scripts/possible_paths.py index e65ddb1c8..87806520f 100644 --- a/examples/scripts/possible_paths.py +++ b/examples/scripts/possible_paths.py @@ -69,7 +69,7 @@ def all_function_definitions(function): :return: Returns a list composed of the provided function definition and any base definitions. """ return [function] + [f for c in function.contract.inheritance - for f in c.functions_and_modifiers_not_inherited + for f in c.functions_and_modifiers_declared if f.full_name == function.full_name] @@ -86,7 +86,7 @@ def __find_target_paths(target_function, current_path=[]): # Look through all functions for contract in slither.contracts: - for function in contract.functions_and_modifiers_not_inherited: + for function in contract.functions_and_modifiers_declared: # If the function is already in our path, skip it. if function in current_path: @@ -179,12 +179,12 @@ reaching_functions = set([y for x in reaching_paths for y in x if y not in targe # Print out all function names which can reach the targets. print(f"The following functions reach the specified targets:") -for function_desc in sorted([f"{f.contract.name}.{f.full_name}" for f in reaching_functions]): +for function_desc in sorted([f"{f.canonical_name}" for f in reaching_functions]): print(f"-{function_desc}") print("\n") # Format all function paths. -reaching_paths_str = [' -> '.join([f"{f.contract.name}.{f.full_name}" for f in reaching_path]) for reaching_path in reaching_paths] +reaching_paths_str = [' -> '.join([f"{f.canonical_name}" for f in reaching_path]) for reaching_path in reaching_paths] # Print a sorted list of all function paths which can reach the targets. print(f"The following paths reach the specified targets:") diff --git a/examples/scripts/slithIR.py b/examples/scripts/slithIR.py index 04fe255c8..2b65e3122 100644 --- a/examples/scripts/slithIR.py +++ b/examples/scripts/slithIR.py @@ -15,7 +15,7 @@ for contract in slither.contracts: for function in contract.functions: # Dont explore inherited functions - if function.contract == contract: + if function.contract_declarer == contract: print('Function: {}'.format(function.name)) diff --git a/scripts/tests_generate_expected_json_4.sh b/scripts/tests_generate_expected_json_4.sh index 4e1def80c..74050acd1 100755 --- a/scripts/tests_generate_expected_json_4.sh +++ b/scripts/tests_generate_expected_json_4.sh @@ -21,38 +21,38 @@ generate_expected_json(){ } -#generate_expected_json tests/deprecated_calls.sol "deprecated-standards" -#generate_expected_json tests/erc20_indexed.sol "erc20-indexed" -#generate_expected_json tests/incorrect_erc20_interface.sol "erc20-interface" -#generate_expected_json tests/incorrect_erc721_interface.sol "erc721-interface" -#generate_expected_json tests/uninitialized.sol "uninitialized-state" -#generate_expected_json tests/backdoor.sol "backdoor" -#generate_expected_json tests/backdoor.sol "suicidal" -#generate_expected_json tests/pragma.0.4.24.sol "pragma" -#generate_expected_json tests/old_solc.sol.json "solc-version" -#generate_expected_json tests/reentrancy.sol "reentrancy-eth" -#generate_expected_json tests/uninitialized_storage_pointer.sol "uninitialized-storage" -#generate_expected_json tests/tx_origin.sol "tx-origin" -#generate_expected_json tests/unused_state.sol "unused-state" -#generate_expected_json tests/locked_ether.sol "locked-ether" -#generate_expected_json tests/arbitrary_send.sol "arbitrary-send" -#generate_expected_json tests/inline_assembly_contract.sol "assembly" -#generate_expected_json tests/inline_assembly_library.sol "assembly" -#generate_expected_json tests/low_level_calls.sol "low-level-calls" -#generate_expected_json tests/const_state_variables.sol "constable-states" -#generate_expected_json tests/external_function.sol "external-function" -#generate_expected_json tests/external_function_2.sol "external-function" -#generate_expected_json tests/naming_convention.sol "naming-convention" -#generate_expected_json tests/uninitialized_local_variable.sol "uninitialized-local" -#generate_expected_json tests/controlled_delegatecall.sol "controlled-delegatecall" -#generate_expected_json tests/constant.sol "constant-function" -#generate_expected_json tests/unused_return.sol "unused-return" -#generate_expected_json tests/shadowing_state_variable.sol "shadowing-state" -#generate_expected_json tests/shadowing_abstract.sol "shadowing-abstract" -#generate_expected_json tests/timestamp.sol "timestamp" -#generate_expected_json tests/multiple_calls_in_loop.sol "calls-loop" -#generate_expected_json tests/shadowing_builtin_symbols.sol "shadowing-builtin" -#generate_expected_json tests/shadowing_local_variable.sol "shadowing-local" -#generate_expected_json tests/solc_version_incorrect.sol "solc-version" -#generate_expected_json tests/right_to_left_override.sol "rtlo" -#generate_expected_json tests/unchecked_lowlevel.sol "unchecked-lowlevel" +generate_expected_json tests/deprecated_calls.sol "deprecated-standards" +generate_expected_json tests/erc20_indexed.sol "erc20-indexed" +generate_expected_json tests/incorrect_erc20_interface.sol "erc20-interface" +generate_expected_json tests/incorrect_erc721_interface.sol "erc721-interface" +generate_expected_json tests/uninitialized.sol "uninitialized-state" +generate_expected_json tests/backdoor.sol "backdoor" +generate_expected_json tests/backdoor.sol "suicidal" +generate_expected_json tests/pragma.0.4.24.sol "pragma" +generate_expected_json tests/old_solc.sol.json "solc-version" +generate_expected_json tests/reentrancy.sol "reentrancy-eth" +generate_expected_json tests/uninitialized_storage_pointer.sol "uninitialized-storage" +generate_expected_json tests/tx_origin.sol "tx-origin" +generate_expected_json tests/unused_state.sol "unused-state" +generate_expected_json tests/locked_ether.sol "locked-ether" +generate_expected_json tests/arbitrary_send.sol "arbitrary-send" +generate_expected_json tests/inline_assembly_contract.sol "assembly" +generate_expected_json tests/inline_assembly_library.sol "assembly" +generate_expected_json tests/low_level_calls.sol "low-level-calls" +generate_expected_json tests/const_state_variables.sol "constable-states" +generate_expected_json tests/external_function.sol "external-function" +generate_expected_json tests/external_function_2.sol "external-function" +generate_expected_json tests/naming_convention.sol "naming-convention" +generate_expected_json tests/uninitialized_local_variable.sol "uninitialized-local" +generate_expected_json tests/controlled_delegatecall.sol "controlled-delegatecall" +generate_expected_json tests/constant.sol "constant-function" +generate_expected_json tests/unused_return.sol "unused-return" +generate_expected_json tests/shadowing_state_variable.sol "shadowing-state" +generate_expected_json tests/shadowing_abstract.sol "shadowing-abstract" +generate_expected_json tests/timestamp.sol "timestamp" +generate_expected_json tests/multiple_calls_in_loop.sol "calls-loop" +generate_expected_json tests/shadowing_builtin_symbols.sol "shadowing-builtin" +generate_expected_json tests/shadowing_local_variable.sol "shadowing-local" +generate_expected_json tests/solc_version_incorrect.sol "solc-version" +generate_expected_json tests/right_to_left_override.sol "rtlo" +generate_expected_json tests/unchecked_lowlevel.sol "unchecked-lowlevel" diff --git a/scripts/tests_generate_expected_json_5.sh b/scripts/tests_generate_expected_json_5.sh index fb9552437..4a43fade4 100755 --- a/scripts/tests_generate_expected_json_5.sh +++ b/scripts/tests_generate_expected_json_5.sh @@ -20,20 +20,20 @@ generate_expected_json(){ sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i } -#generate_expected_json tests/solc_version_incorrect_05.ast.json "solc-version" -#generate_expected_json tests/uninitialized-0.5.1.sol "uninitialized-state" -#generate_expected_json tests/backdoor.sol "backdoor" -#generate_expected_json tests/backdoor.sol "suicidal" -#generate_expected_json tests/old_solc.sol.json "solc-version" -#generate_expected_json tests/reentrancy-0.5.1.sol "reentrancy-eth" -#generate_expected_json tests/tx_origin-0.5.1.sol "tx-origin" -#generate_expected_json tests/locked_ether-0.5.1.sol "locked-ether" -#generate_expected_json tests/arbitrary_send-0.5.1.sol "arbitrary-send" -#generate_expected_json tests/inline_assembly_contract-0.5.1.sol "assembly" -#generate_expected_json tests/inline_assembly_library-0.5.1.sol "assembly" -#generate_expected_json tests/constant-0.5.1.sol "constant-function" -#generate_expected_json tests/incorrect_equality.sol "incorrect-equality" -#generate_expected_json tests/too_many_digits.sol "too-many-digits" -#generate_expected_json tests/unchecked_lowlevel-0.5.1.sol "unchecked-lowlevel" -#generate_expected_json tests/unchecked_send-0.5.1.sol "unchecked-send" +generate_expected_json tests/solc_version_incorrect_05.ast.json "solc-version" +generate_expected_json tests/uninitialized-0.5.1.sol "uninitialized-state" +generate_expected_json tests/backdoor.sol "backdoor" +generate_expected_json tests/backdoor.sol "suicidal" +generate_expected_json tests/old_solc.sol.json "solc-version" +generate_expected_json tests/reentrancy-0.5.1.sol "reentrancy-eth" +generate_expected_json tests/tx_origin-0.5.1.sol "tx-origin" +generate_expected_json tests/locked_ether-0.5.1.sol "locked-ether" +generate_expected_json tests/arbitrary_send-0.5.1.sol "arbitrary-send" +generate_expected_json tests/inline_assembly_contract-0.5.1.sol "assembly" +generate_expected_json tests/inline_assembly_library-0.5.1.sol "assembly" +generate_expected_json tests/constant-0.5.1.sol "constant-function" +generate_expected_json tests/incorrect_equality.sol "incorrect-equality" +generate_expected_json tests/too_many_digits.sol "too-many-digits" +generate_expected_json tests/unchecked_lowlevel-0.5.1.sol "unchecked-lowlevel" +generate_expected_json tests/unchecked_send-0.5.1.sol "unchecked-send" diff --git a/scripts/travis_install.sh b/scripts/travis_install.sh index 77d84e296..e043c9c16 100755 --- a/scripts/travis_install.sh +++ b/scripts/travis_install.sh @@ -24,5 +24,3 @@ function install_solc { install_solc - - diff --git a/scripts/travis_test_4.sh b/scripts/travis_test_4.sh index 1b43f2a5d..01e5088df 100755 --- a/scripts/travis_test_4.sh +++ b/scripts/travis_test_4.sh @@ -94,6 +94,7 @@ test_slither tests/external_function_2.sol "external-function" test_slither tests/naming_convention.sol "naming-convention" #test_slither tests/complex_func.sol "complex-function" test_slither tests/controlled_delegatecall.sol "controlled-delegatecall" +test_slither tests/uninitialized_local_variable.sol "uninitialized-local" test_slither tests/constant.sol "constant-function" test_slither tests/unused_return.sol "unused-return" test_slither tests/shadowing_abstract.sol "shadowing-abstract" diff --git a/scripts/travis_test_5.sh b/scripts/travis_test_5.sh index 1c9276eac..7224638d7 100755 --- a/scripts/travis_test_5.sh +++ b/scripts/travis_test_5.sh @@ -88,7 +88,7 @@ test_slither tests/const_state_variables.sol "constable-states" test_slither tests/external_function.sol "external-function" test_slither tests/external_function_2.sol "external-function" test_slither tests/naming_convention.sol "naming-convention" -##test_slither tests/complex_func.sol "complex-function" +#test_slither tests/complex_func.sol "complex-function" test_slither tests/controlled_delegatecall.sol "controlled-delegatecall" test_slither tests/constant-0.5.1.sol "constant-function" test_slither tests/unused_return.sol "unused-return" diff --git a/scripts/travis_test_upgradability.sh b/scripts/travis_test_upgradability.sh index adce735c2..d840a2fb3 100755 --- a/scripts/travis_test_upgradability.sh +++ b/scripts/travis_test_upgradability.sh @@ -8,8 +8,9 @@ slither-check-upgradeability "$DIR_TESTS/proxy.sol" Proxy "$DIR_TESTS/contractV1 DIFF=$(diff test_1.txt "$DIR_TESTS/test_1.txt") if [ "$DIFF" != "" ] then - echo "slither-check-upgradeability failed" + echo "slither-check-upgradeability 1 failed" cat test_1.txt + echo "" cat "$DIR_TESTS/test_1.txt" exit -1 fi @@ -18,8 +19,9 @@ slither-check-upgradeability "$DIR_TESTS/proxy.sol" Proxy "$DIR_TESTS/contractV1 DIFF=$(diff test_2.txt "$DIR_TESTS/test_2.txt") if [ "$DIFF" != "" ] then - echo "slither-check-upgradeability failed" + echo "slither-check-upgradeability 2 failed" cat test_2.txt + echo "" cat "$DIR_TESTS/test_2.txt" exit -1 fi @@ -28,8 +30,9 @@ slither-check-upgradeability "$DIR_TESTS/proxy.sol" Proxy "$DIR_TESTS/contractV1 DIFF=$(diff test_3.txt "$DIR_TESTS/test_3.txt") if [ "$DIFF" != "" ] then - echo "slither-check-upgradeability failed" + echo "slither-check-upgradeability 3 failed" cat test_3.txt + echo "" cat "$DIR_TESTS/test_3.txt" exit -1 fi @@ -38,8 +41,9 @@ slither-check-upgradeability "$DIR_TESTS/proxy.sol" Proxy "$DIR_TESTS/contractV1 DIFF=$(diff test_4.txt "$DIR_TESTS/test_4.txt") if [ "$DIFF" != "" ] then - echo "slither-check-upgradeability failed" + echo "slither-check-upgradeability 4 failed" cat test_4.txt + echo "" cat "$DIR_TESTS/test_4.txt" exit -1 fi @@ -48,9 +52,12 @@ slither-check-upgradeability "$DIR_TESTS/proxy.sol" Proxy "$DIR_TESTS/contract_i DIFF=$(diff test_5.txt "$DIR_TESTS/test_5.txt") if [ "$DIFF" != "" ] then - echo "slither-check-upgradeability failed" + echo "slither-check-upgradeability 5 failed" cat test_5.txt + echo "" cat "$DIR_TESTS/test_5.txt" + echo "" + echo "$DIFF" exit -1 fi diff --git a/slither/core/children/child_contract.py b/slither/core/children/child_contract.py index d5a613bc9..9ca39af8e 100644 --- a/slither/core/children/child_contract.py +++ b/slither/core/children/child_contract.py @@ -11,3 +11,4 @@ class ChildContract: @property def contract(self): return self._contract + diff --git a/slither/core/children/child_inheritance.py b/slither/core/children/child_inheritance.py new file mode 100644 index 000000000..cc9c4065f --- /dev/null +++ b/slither/core/children/child_inheritance.py @@ -0,0 +1,13 @@ + +class ChildInheritance: + + def __init__(self): + super(ChildInheritance, self).__init__() + self._contract_declarer = None + + def set_contract_declarer(self, contract): + self._contract_declarer = contract + + @property + def contract_declarer(self): + return self._contract_declarer diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 667a0134f..73aeb61ee 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -35,6 +35,7 @@ class Contract(ChildSlither, SourceMapping): self._variables = {} self._modifiers = {} self._functions = {} + self._using_for = {} self._kind = None @@ -77,6 +78,20 @@ class Contract(ChildSlither, SourceMapping): ''' return list(self._structures.values()) + @property + def structures_inherited(self): + ''' + list(Structure): List of the inherited structures + ''' + return [s for s in self.structures if s.contract != self] + + @property + def structures_declared(self): + ''' + list(Structues): List of the structures declared within the contract (not inherited) + ''' + return [s for s in self.structures if s.contract == self] + def structures_as_dict(self): return self._structures @@ -91,6 +106,20 @@ class Contract(ChildSlither, SourceMapping): def enums(self): return list(self._enums.values()) + @property + def enums_inherited(self): + ''' + list(Enum): List of the inherited enums + ''' + return [e for e in self.enums if e.contract != self] + + @property + def enums_declared(self): + ''' + list(Enum): List of the enums declared within the contract (not inherited) + ''' + return [e for e in self.enums if e.contract == self] + def enums_as_dict(self): return self._enums @@ -108,6 +137,20 @@ class Contract(ChildSlither, SourceMapping): ''' return list(self._events.values()) + @property + def events_inherited(self): + ''' + list(Event): List of the inherited events + ''' + return [e for e in self.events if e.contract != self] + + @property + def events_declared(self): + ''' + list(Event): List of the events declared within the contract (not inherited) + ''' + return [e for e in self.events if e.contract == self] + def events_as_dict(self): return self._events @@ -153,6 +196,20 @@ class Contract(ChildSlither, SourceMapping): ''' return list(self._variables.values()) + @property + def state_variables_inherited(self): + ''' + list(StateVariable): List of the inherited state variables + ''' + return [s for s in self.state_variables if s.contract != self] + + @property + def state_variables_declared(self): + ''' + list(StateVariable): List of the state variables declared within the contract (not inherited) + ''' + return [s for s in self.state_variables if s.contract == self] + @property def slithir_variables(self): ''' @@ -177,18 +234,18 @@ class Contract(ChildSlither, SourceMapping): executed, following the c3 linearization Return None if there is no constructor. ''' - cst = self.constructor_not_inherited + cst = self.constructors_declared if cst: return cst for inherited_contract in self.inheritance: - cst = inherited_contract.constructor_not_inherited + cst = inherited_contract.constructors_declared if cst: return cst return None @property - def constructor_not_inherited(self): - return next((func for func in self.functions if func.is_constructor and func.contract == self), None) + def constructors_declared(self): + return next((func for func in self.functions if func.is_constructor and func.contract_declarer == self), None) @property def constructors(self): @@ -238,29 +295,29 @@ class Contract(ChildSlither, SourceMapping): ''' return list(self._functions.values()) - def functions_as_dict(self): - return self._functions + def available_functions_as_dict(self): + return {f.full_name: f for f in self._functions.values() if not f.is_shadowed} @property def functions_inherited(self): ''' list(Function): List of the inherited functions ''' - return [f for f in self.functions if f.contract != self] + return [f for f in self.functions if f.contract_declarer != self] @property - def functions_not_inherited(self): + def functions_declared(self): ''' list(Function): List of the functions defined within the contract (not inherited) ''' - return [f for f in self.functions if f.contract == self] + return [f for f in self.functions if f.contract_declarer == self] @property def functions_entry_points(self): ''' list(Functions): List of public and external functions ''' - return [f for f in self.functions if f.visibility in ['public', 'external']] + return [f for f in self.functions if f.visibility in ['public', 'external'] and not f.is_shadowed] @property def modifiers(self): @@ -269,22 +326,22 @@ class Contract(ChildSlither, SourceMapping): ''' return list(self._modifiers.values()) - def modifiers_as_dict(self): - return self._modifiers + def available_modifiers_as_dict(self): + return {m.full_name: m for m in self._modifiers.values() if not m.is_shadowed} @property def modifiers_inherited(self): ''' list(Modifier): List of the inherited modifiers ''' - return [m for m in self.modifiers if m.contract != self] + return [m for m in self.modifiers if m.contract_declarer != self] @property - def modifiers_not_inherited(self): + def modifiers_declared(self): ''' list(Modifier): List of the modifiers defined within the contract (not inherited) ''' - return [m for m in self.modifiers if m.contract == self] + return [m for m in self.modifiers if m.contract_declarer == self] @property def functions_and_modifiers(self): @@ -301,11 +358,36 @@ class Contract(ChildSlither, SourceMapping): return self.functions_inherited + self.modifiers_inherited @property - def functions_and_modifiers_not_inherited(self): + def functions_and_modifiers_declared(self): ''' list(Function|Modifier): List of the functions and modifiers defined within the contract (not inherited) ''' - return self.functions_not_inherited + self.modifiers_not_inherited + return self.functions_declared + self.modifiers_declared + + def available_elements_from_inheritances(self, elements, getter_available): + """ + + :param elements: dict(canonical_name -> elements) + :param getter_available: fun x + :return: + """ + # keep track of the contracts visited + # to prevent an ovveride due to multiple inheritance of the same contract + # A is B, C, D is C, --> the second C was already seen + inherited_elements = {} + accessible_elements = {} + contracts_visited = [] + for father in self.inheritance_reverse: + functions = {v.full_name: v for (_, v) in getter_available(father) + if not v.contract in contracts_visited} + contracts_visited.append(father) + inherited_elements.update(functions) + + for element in inherited_elements.values(): + accessible_elements[element.full_name] = elements[element.canonical_name] + + return accessible_elements + # endregion ################################################################################### @@ -375,7 +457,7 @@ class Contract(ChildSlither, SourceMapping): Returns: Function """ - return next((f for f in self.functions if f.full_name == function_signature), None) + return next((f for f in self.functions if f.full_name == function_signature and not f.is_shadowed), None) def get_modifier_from_signature(self, modifier_signature): """ @@ -385,7 +467,28 @@ class Contract(ChildSlither, SourceMapping): Returns: Modifier """ - return next((m for m in self.modifiers if m.full_name == modifier_signature), None) + return next((m for m in self.modifiers if m.full_name == modifier_signature and not m.is_shadowed), None) + + def get_function_from_canonical_name(self, canonical_name): + """ + Return a function from a a canonical name (contract.signature()) + Args: + canonical_name (str): canonical name of the function (without return statement) + Returns: + Function + """ + return next((f for f in self.functions if f.canonical_name == canonical_name), None) + + def get_modifier_from_canonical_name(self, canonical_name): + """ + Return a modifier from a canonical name (contract.signature()) + Args: + canonical_name (str): canonical name of the modifier + Returns: + Modifier + """ + return next((m for m in self.modifiers if m.canonical_name == canonical_name), None) + def get_state_variable_from_name(self, variable_name): """ @@ -456,7 +559,7 @@ class Contract(ChildSlither, SourceMapping): list(core.Function) ''' - candidates = [c.functions_not_inherited for c in self.inheritance] + candidates = [c.functions_declared for c in self.inheritance] candidates = [candidate for sublist in candidates for candidate in sublist] return [f for f in candidates if f.full_name == function.full_name] @@ -470,10 +573,12 @@ class Contract(ChildSlither, SourceMapping): @property def all_functions_called(self): ''' - list(Function): List of functions reachable from the contract (include super) + list(Function): List of functions reachable from the contract + Includes super, and private/internal functions not shadowed ''' - all_calls = [f.all_internal_calls() for f in self.functions + self.modifiers] + [self.functions + self.modifiers] - all_calls = [item for sublist in all_calls for item in sublist] + self.functions + all_calls = [f for f in self.functions + self.modifiers if not f.is_shadowed] + all_calls = [f.all_internal_calls() for f in all_calls] + [all_calls] + all_calls = [item for sublist in all_calls for item in sublist] all_calls = list(set(all_calls)) all_constructors = [c.constructor for c in self.inheritance] diff --git a/slither/core/declarations/enum.py b/slither/core/declarations/enum.py index d04d0f6eb..ace9b2095 100644 --- a/slither/core/declarations/enum.py +++ b/slither/core/declarations/enum.py @@ -19,5 +19,13 @@ class Enum(ChildContract, SourceMapping): def values(self): return self._values + def is_declared_by(self, contract): + """ + Check if the element is declared by the contract + :param contract: + :return: + """ + return self.contract == contract + def __str__(self): return self.name diff --git a/slither/core/declarations/event.py b/slither/core/declarations/event.py index 0974c4773..7d4eeeaf7 100644 --- a/slither/core/declarations/event.py +++ b/slither/core/declarations/event.py @@ -29,9 +29,25 @@ class Event(ChildContract, SourceMapping): name, parameters = self.signature return name+'('+','.join(parameters)+')' + @property + def canonical_name(self): + ''' Return the function signature as a str + Returns: + str: contract.func_name(type1,type2) + ''' + return self.contract.name + self.full_name + @property def elems(self): return self._elems + def is_declared_by(self, contract): + """ + Check if the element is declared by the contract + :param contract: + :return: + """ + return self.contract == contract + def __str__(self): return self.name diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index 577c77b1a..1f7247102 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -6,6 +6,7 @@ from collections import namedtuple from itertools import groupby from slither.core.children.child_contract import ChildContract +from slither.core.children.child_inheritance import ChildInheritance from slither.core.declarations.solidity_variables import (SolidityFunction, SolidityVariable, SolidityVariableComposed) @@ -18,7 +19,7 @@ logger = logging.getLogger("Function") ReacheableNode = namedtuple('ReacheableNode', ['node', 'ir']) -class Function(ChildContract, SourceMapping): +class Function(ChildContract, ChildInheritance, SourceMapping): """ Function class """ @@ -84,6 +85,8 @@ class Function(ChildContract, SourceMapping): self._all_conditional_solidity_variables_read_with_loop = None self._all_solidity_variables_used_as_args = None + self._is_shadowed = False + # set(ReacheableNode) self._reachable_from_nodes = set() self._reachable_from_functions = set() @@ -116,12 +119,21 @@ class Function(ChildContract, SourceMapping): name, parameters, _ = self.signature return name+'('+','.join(parameters)+')' + @property + def canonical_name(self): + """ + str: contract.func_name(type1,type2) + Return the function signature without the return values + """ + name, parameters, _ = self.signature + return self.contract_declarer.name + '.' + name + '(' + ','.join(parameters) + ')' + @property def is_constructor(self): """ bool: True if the function is the constructor """ - return self._is_constructor or self._name == self.contract.name + return self._is_constructor or self._name == self.contract_declarer.name @property def contains_assembly(self): @@ -131,6 +143,14 @@ class Function(ChildContract, SourceMapping): def slither(self): return self.contract.slither + def is_declared_by(self, contract): + """ + Check if the element is declared by the contract + :param contract: + :return: + """ + return self.contract_declarer == contract + # endregion ################################################################################### ################################################################################### @@ -173,6 +193,14 @@ class Function(ChildContract, SourceMapping): """ return self._pure + @property + def is_shadowed(self): + return self._is_shadowed + + @is_shadowed.setter + def is_shadowed(self, is_shadowed): + self._is_shadowed = is_shadowed + # endregion ################################################################################### ################################################################################### @@ -307,7 +335,7 @@ class Function(ChildContract, SourceMapping): included. """ # This is a list of contracts internally, so we convert it to a list of constructor functions. - return [c.constructor_not_inherited for c in self._explicit_base_constructor_calls if c.constructor_not_inherited] + return [c.constructors_declared for c in self._explicit_base_constructor_calls if c.constructors_declared] # endregion @@ -560,7 +588,7 @@ class Function(ChildContract, SourceMapping): list(core.Function) ''' - candidates = [c.functions_not_inherited for c in self.contract.inheritance] + candidates = [c.functions_declared for c in self.contract.inheritance] candidates = [candidate for sublist in candidates for candidate in sublist] return [f for f in candidates if f.full_name == self.full_name] @@ -933,7 +961,7 @@ class Function(ChildContract, SourceMapping): (str, str, str, list(str), list(str), listr(str), list(str), list(str); contract_name, name, visibility, modifiers, vars read, vars written, internal_calls, external_calls_as_expressions """ - return (self.contract.name, self.full_name, self.visibility, + return (self.contract_declarer.name, self.full_name, self.visibility, [str(x) for x in self.modifiers], [str(x) for x in self.state_variables_read + self.solidity_variables_read], [str(x) for x in self.state_variables_written], diff --git a/slither/core/declarations/structure.py b/slither/core/declarations/structure.py index 6584cbe19..087a06a1c 100644 --- a/slither/core/declarations/structure.py +++ b/slither/core/declarations/structure.py @@ -25,6 +25,15 @@ class Structure(ChildContract, SourceMapping): def elems(self): return self._elems + + def is_declared_by(self, contract): + """ + Check if the element is declared by the contract + :param contract: + :return: + """ + return self.contract == contract + @property def elems_ordered(self): ret = [] @@ -32,5 +41,6 @@ class Structure(ChildContract, SourceMapping): ret.append(self._elems[e]) return ret + def __str__(self): return self.name diff --git a/slither/core/variables/local_variable.py b/slither/core/variables/local_variable.py index 414910f67..39e237271 100644 --- a/slither/core/variables/local_variable.py +++ b/slither/core/variables/local_variable.py @@ -50,3 +50,8 @@ class LocalVariable(ChildFunction, Variable): return False + @property + def canonical_name(self): + return self.name + + diff --git a/slither/core/variables/state_variable.py b/slither/core/variables/state_variable.py index e85ca2e09..8cebc8758 100644 --- a/slither/core/variables/state_variable.py +++ b/slither/core/variables/state_variable.py @@ -4,6 +4,16 @@ from slither.utils.type import export_nested_types_from_variable class StateVariable(ChildContract, Variable): + + def is_declared_by(self, contract): + """ + Check if the element is declared by the contract + :param contract: + :return: + """ + return self.contract == contract + + ################################################################################### ################################################################################### # region Signature @@ -36,7 +46,7 @@ class StateVariable(ChildContract, Variable): @property def canonical_name(self): - return '{}:{}'.format(self.contract.name, self.name) + return '{}.{}'.format(self.contract.name, self.name) @property def full_name(self): @@ -51,3 +61,4 @@ class StateVariable(ChildContract, Variable): # endregion ################################################################################### ################################################################################### + diff --git a/slither/core/variables/variable.py b/slither/core/variables/variable.py index e1476ed19..8b37c6da1 100644 --- a/slither/core/variables/variable.py +++ b/slither/core/variables/variable.py @@ -78,6 +78,7 @@ class Variable(SourceMapping): assert isinstance(t, (Type, list)) or t is None self._type = t + def __str__(self): return self._name diff --git a/slither/detectors/abstract_detector.py b/slither/detectors/abstract_detector.py index df50a0e4d..39651c12a 100644 --- a/slither/detectors/abstract_detector.py +++ b/slither/detectors/abstract_detector.py @@ -160,7 +160,13 @@ class AbstractDetector(metaclass=abc.ABCMeta): def _create_parent_element(element): from slither.core.children.child_contract import ChildContract from slither.core.children.child_function import ChildFunction - if isinstance(element, ChildContract): + from slither.core.children.child_inheritance import ChildInheritance + if isinstance(element, ChildInheritance): + if element.contract_declarer: + contract = {'elements': []} + AbstractDetector.add_contract_to_json(element.contract_declarer, contract) + return contract['elements'][0] + elif isinstance(element, ChildContract): if element.contract: contract = {'elements': []} AbstractDetector.add_contract_to_json(element.contract, contract) @@ -211,10 +217,11 @@ class AbstractDetector(metaclass=abc.ABCMeta): additional_fields) d['elements'].append(element) + @staticmethod - def add_functions_to_json(functions, d): + def add_functions_to_json(functions, d, additional_fields={}): for function in sorted(functions, key=lambda x: x.name): - AbstractDetector.add_function_to_json(function, d) + AbstractDetector.add_function_to_json(function, d, additional_fields) @staticmethod def add_enum_to_json(enum, d, additional_fields={}): @@ -267,6 +274,7 @@ class AbstractDetector(metaclass=abc.ABCMeta): additional_fields) d['elements'].append(element) + @staticmethod def add_nodes_to_json(nodes, d): for node in sorted(nodes, key=lambda x: x.node_id): diff --git a/slither/detectors/attributes/const_functions.py b/slither/detectors/attributes/const_functions.py index 1e890f8cd..2f217eb97 100644 --- a/slither/detectors/attributes/const_functions.py +++ b/slither/detectors/attributes/const_functions.py @@ -51,13 +51,13 @@ All the calls to `get` revert, breaking Bob's smart contract execution.''' results = [] for c in self.contracts: for f in c.functions: - if f.contract != c: + if f.contract_declarer != c: continue if f.view or f.pure: if f.contains_assembly: attr = 'view' if f.view else 'pure' - info = '{}.{} ({}) is declared {} but contains assembly code\n' - info = info.format(f.contract.name, f.name, f.source_mapping_str, attr) + info = '{} ({}) is declared {} but contains assembly code\n' + info = info.format(f.canonical_name, f.source_mapping_str, attr) json = self.generate_json_result(info, {'contains_assembly': True}) self.add_function_to_json(f, json) results.append(json) @@ -65,11 +65,10 @@ All the calls to `get` revert, breaking Bob's smart contract execution.''' variables_written = f.all_state_variables_written() if variables_written: attr = 'view' if f.view else 'pure' - info = '{}.{} ({}) is declared {} but changes state variables:\n' - info = info.format(f.contract.name, f.name, f.source_mapping_str, attr) + info = '{} ({}) is declared {} but changes state variables:\n' + info = info.format(f.canonical_name, f.source_mapping_str, attr) for variable_written in variables_written: - info += '\t- {}.{}\n'.format(variable_written.contract.name, - variable_written.name) + info += '\t- {}\n'.format(variable_written.canonical_name) json = self.generate_json_result(info, {'contains_assembly': False}) self.add_function_to_json(f, json) diff --git a/slither/detectors/erc/incorrect_erc20_interface.py b/slither/detectors/erc/incorrect_erc20_interface.py index fe2916da9..c2c0a4112 100644 --- a/slither/detectors/erc/incorrect_erc20_interface.py +++ b/slither/detectors/erc/incorrect_erc20_interface.py @@ -61,6 +61,7 @@ contract Token{ Returns: list(str) : list of incorrect function signatures """ + # Verify this is an ERC20 contract. if not contract.is_possible_erc20(): return [] @@ -72,6 +73,7 @@ contract Token{ funcs = contract.functions functions = [f for f in funcs if IncorrectERC20InterfaceDetection.incorrect_erc20_interface(f.signature)] + return functions def _detect(self): @@ -87,7 +89,7 @@ contract Token{ for function in functions: info = "{} ({}) has incorrect ERC20 function interface: {} ({})\n".format(c.name, c.source_mapping_str, - function.name, + function.full_name, function.source_mapping_str) json = self.generate_json_result(info) self.add_function_to_json(function, json) diff --git a/slither/detectors/erc/incorrect_erc721_interface.py b/slither/detectors/erc/incorrect_erc721_interface.py index 431c076b7..bff88413c 100644 --- a/slither/detectors/erc/incorrect_erc721_interface.py +++ b/slither/detectors/erc/incorrect_erc721_interface.py @@ -87,9 +87,9 @@ contract Token{ if functions: for function in functions: info = "{} ({}) has incorrect ERC721 function interface: {} ({})\n".format(c.name, - c.source_mapping_str, - function.name, - function.source_mapping_str) + c.source_mapping_str, + function.full_name, + function.source_mapping_str) json = self.generate_json_result(info) self.add_function_to_json(function, json) results.append(json) diff --git a/slither/detectors/erc/unindexed_event_parameters.py b/slither/detectors/erc/unindexed_event_parameters.py index b4f16e69c..55ab15e25 100644 --- a/slither/detectors/erc/unindexed_event_parameters.py +++ b/slither/detectors/erc/unindexed_event_parameters.py @@ -47,11 +47,7 @@ In this case, Transfer and Approval events should have the 'indexed' keyword on return results # Loop through all events to look for poor form. - for event in contract.events: - - # Only handle events which are declared in this contract. - if event.contract != contract: - continue + for event in contract.events_declared: # If this is transfer/approval events, expect the first two parameters to be indexed. if event.full_name in ["Transfer(address,address,uint256)", @@ -74,6 +70,7 @@ In this case, Transfer and Approval events should have the 'indexed' keyword on if unindexed_params: # Add each problematic event definition to our result list for (event, parameter) in unindexed_params: + info = "ERC20 event {}.{} ({}) does not index parameter '{}'\n".format(c.name, event.name, event.source_mapping_str, parameter.name) # Add the events to the JSON (note: we do not add the params/vars as they have no source mapping). @@ -83,4 +80,5 @@ In this case, Transfer and Approval events should have the 'indexed' keyword on }) results.append(json) + return results diff --git a/slither/detectors/functions/arbitrary_send.py b/slither/detectors/functions/arbitrary_send.py index 59f33fcab..d28cd1258 100644 --- a/slither/detectors/functions/arbitrary_send.py +++ b/slither/detectors/functions/arbitrary_send.py @@ -94,7 +94,7 @@ Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract list((Function), (list (Node))) """ ret = [] - for f in [f for f in contract.functions if f.contract == contract]: + for f in [f for f in contract.functions if f.contract_declarer == contract]: nodes = self.arbitrary_send(f) if nodes: ret.append((f, nodes)) @@ -109,9 +109,8 @@ Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract arbitrary_send = self.detect_arbitrary_send(c) for (func, nodes) in arbitrary_send: - info = "{}.{} ({}) sends eth to arbitrary user\n" - info = info.format(func.contract.name, - func.name, + info = "{} ({}) sends eth to arbitrary user\n" + info = info.format(func.canonical_name, func.source_mapping_str) info += '\tDangerous calls:\n' for node in nodes: diff --git a/slither/detectors/functions/complex_function.py b/slither/detectors/functions/complex_function.py index 5da617db3..fae9a0923 100644 --- a/slither/detectors/functions/complex_function.py +++ b/slither/detectors/functions/complex_function.py @@ -90,7 +90,7 @@ class ComplexFunction(AbstractDetector): for issue in issues: func, cause = issue.values() - txt = "{}.{} ({}) is a complex function:\n" + txt = "{} ({}) is a complex function:\n" if cause == self.CAUSE_EXTERNAL_CALL: txt += "\t- Reason: High number of external calls" @@ -99,8 +99,7 @@ class ComplexFunction(AbstractDetector): if cause == self.CAUSE_STATE_VARS: txt += "\t- Reason: High number of modified state variables" - info = txt.format(func.contract.name, - func.name, + info = txt.format(func.canonical_name, func.source_mapping_str) info = info + "\n" self.log(info) diff --git a/slither/detectors/functions/external_function.py b/slither/detectors/functions/external_function.py index 1d80e4e95..9c95bde31 100644 --- a/slither/detectors/functions/external_function.py +++ b/slither/detectors/functions/external_function.py @@ -71,7 +71,7 @@ class ExternalFunction(AbstractDetector): for contract in function.contract.inheritance + [function.contract]: # Loop through the functions not inherited (explicitly defined in this contract). - for f in contract.functions_not_inherited: + for f in contract.functions_declared: # If it matches names, this is the base most function. if f.full_name == function.full_name: @@ -120,7 +120,7 @@ class ExternalFunction(AbstractDetector): continue # Next we'll want to loop through all functions defined directly in this contract. - for function in contract.functions_not_inherited: + for function in contract.functions_declared: # If the function is a constructor, or is public, we skip it. if function.is_constructor or function.visibility != "public": @@ -165,9 +165,8 @@ class ExternalFunction(AbstractDetector): # Loop for each function definition, and recommend it be declared external. for function_definition in all_function_definitions: - txt = "{}.{} ({}) should be declared external\n" - info = txt.format(function_definition.contract.name, - function_definition.name, + txt = "{} ({}) should be declared external\n" + info = txt.format(function_definition.canonical_name, function_definition.source_mapping_str) json = self.generate_json_result(info) diff --git a/slither/detectors/functions/suicidal.py b/slither/detectors/functions/suicidal.py index 66751dc9c..fef1c1224 100644 --- a/slither/detectors/functions/suicidal.py +++ b/slither/detectors/functions/suicidal.py @@ -59,7 +59,7 @@ Bob calls `kill` and destructs the contract.''' def detect_suicidal(self, contract): ret = [] - for f in [f for f in contract.functions if f.contract == contract]: + for f in [f for f in contract.functions if f.contract_declarer == contract]: if self.detect_suicidal_func(f): ret.append(f) return ret @@ -72,9 +72,8 @@ Bob calls `kill` and destructs the contract.''' functions = self.detect_suicidal(c) for func in functions: - txt = "{}.{} ({}) allows anyone to destruct the contract\n" - info = txt.format(func.contract.name, - func.name, + txt = "{} ({}) allows anyone to destruct the contract\n" + info = txt.format(func.canonical_name, func.source_mapping_str) json = self.generate_json_result(info) diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index e0e9619bf..61d917b26 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -67,13 +67,10 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 }) results.append(json) - for struct in contract.structures: - if struct.contract != contract: - continue - + for struct in contract.structures_declared: if not self.is_cap_words(struct.name): - info = "Struct '{}.{}' ({}) is not in CapWords\n" - info = info.format(struct.contract.name, struct.name, struct.source_mapping_str) + info = "Struct '{}' ({}) is not in CapWords\n" + info = info.format(struct.canonical_name, struct.source_mapping_str) json = self.generate_json_result(info) self.add_struct_to_json(struct, json, { @@ -82,13 +79,10 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 }) results.append(json) - for event in contract.events: - if event.contract != contract: - continue - + for event in contract.events_declared: if not self.is_cap_words(event.name): - info = "Event '{}.{}' ({}) is not in CapWords\n" - info = info.format(event.contract.name, event.name, event.source_mapping_str) + info = "Event '{}' ({}) is not in CapWords\n" + info = info.format(event.canonical_name, event.source_mapping_str) json = self.generate_json_result(info) self.add_event_to_json(event, json, { @@ -97,13 +91,10 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 }) results.append(json) - for func in contract.functions: - if func.contract != contract: - continue - + for func in contract.functions_declared: if not self.is_mixed_case(func.name): - info = "Function '{}.{}' ({}) is not in mixedCase\n" - info = info.format(func.contract.name, func.name, func.source_mapping_str) + info = "Function '{}' ({}) is not in mixedCase\n" + info = info.format(func.canonical_name, func.source_mapping_str) json = self.generate_json_result(info) self.add_function_to_json(func, json, { @@ -118,10 +109,9 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 else: correct_naming = self.is_mixed_case_with_underscore(argument.name) if not correct_naming: - info = "Parameter '{}' of {}.{} ({}) is not in mixedCase\n" + info = "Parameter '{}' of {} ({}) is not in mixedCase\n" info = info.format(argument.name, - argument.function.contract.name, - argument.function, + argument.canonical_name, argument.source_mapping_str) json = self.generate_json_result(info) @@ -131,14 +121,11 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 }) results.append(json) - for var in contract.state_variables: - if var.contract != contract: - continue - + for var in contract.state_variables_declared: if self.should_avoid_name(var.name): if not self.is_upper_case_with_underscores(var.name): - info = "Variable '{}.{}' ({}) used l, O, I, which should not be used\n" - info = info.format(var.contract.name, var.name, var.source_mapping_str) + info = "Variable '{}' ({}) used l, O, I, which should not be used\n" + info = info.format(var.canonical_name, var.source_mapping_str) json = self.generate_json_result(info) self.add_variable_to_json(var, json, { @@ -153,8 +140,8 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 continue if not self.is_upper_case_with_underscores(var.name): - info = "Constant '{}.{}' ({}) is not in UPPER_CASE_WITH_UNDERSCORES\n" - info = info.format(var.contract.name, var.name, var.source_mapping_str) + info = "Constant '{}' ({}) is not in UPPER_CASE_WITH_UNDERSCORES\n" + info = info.format(var.canonical_name, var.source_mapping_str) json = self.generate_json_result(info) self.add_variable_to_json(var, json, { @@ -169,8 +156,8 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 else: correct_naming = self.is_mixed_case(var.name) if not correct_naming: - info = "Variable '{}.{}' ({}) is not in mixedCase\n" - info = info.format(var.contract.name, var.name, var.source_mapping_str) + info = "Variable '{}' ({}) is not in mixedCase\n" + info = info.format(var.canonical_name, var.source_mapping_str) json = self.generate_json_result(info) self.add_variable_to_json(var, json, { @@ -179,13 +166,10 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 }) results.append(json) - for enum in contract.enums: - if enum.contract != contract: - continue - + for enum in contract.enums_declared: if not self.is_cap_words(enum.name): - info = "Enum '{}.{}' ({}) is not in CapWords\n" - info = info.format(enum.contract.name, enum.name, enum.source_mapping_str) + info = "Enum '{}' ({}) is not in CapWords\n" + info = info.format(enum.canonical_name, enum.source_mapping_str) json = self.generate_json_result(info) self.add_enum_to_json(enum, json, { @@ -194,15 +178,10 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 }) results.append(json) - - for modifier in contract.modifiers: - if modifier.contract != contract: - continue - + for modifier in contract.modifiers_declared: if not self.is_mixed_case(modifier.name): - info = "Modifier '{}.{}' ({}) is not in mixedCase\n" - info = info.format(modifier.contract.name, - modifier.name, + info = "Modifier '{}' ({}) is not in mixedCase\n" + info = info.format(modifier.canonical_name, modifier.source_mapping_str) json = self.generate_json_result(info) @@ -212,5 +191,4 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 }) results.append(json) - return results diff --git a/slither/detectors/operations/block_timestamp.py b/slither/detectors/operations/block_timestamp.py index 86912098d..81c115341 100644 --- a/slither/detectors/operations/block_timestamp.py +++ b/slither/detectors/operations/block_timestamp.py @@ -54,7 +54,7 @@ class Timestamp(AbstractDetector): list((Function), (list (Node))) """ ret = [] - for f in [f for f in contract.functions if f.contract == contract]: + for f in [f for f in contract.functions if f.contract_declarer == contract]: nodes = self.timestamp(f) if nodes: ret.append((f, nodes)) @@ -69,9 +69,8 @@ class Timestamp(AbstractDetector): dangerous_timestamp = self.detect_dangerous_timestamp(c) for (func, nodes) in dangerous_timestamp: - info = "{}.{} ({}) uses timestamp for comparisons\n" - info = info.format(func.contract.name, - func.name, + info = "{} ({}) uses timestamp for comparisons\n" + info = info.format(func.canonical_name, func.source_mapping_str) info += '\tDangerous comparisons:\n' for node in nodes: diff --git a/slither/detectors/operations/low_level_calls.py b/slither/detectors/operations/low_level_calls.py index 9123a2c67..4e36448a4 100644 --- a/slither/detectors/operations/low_level_calls.py +++ b/slither/detectors/operations/low_level_calls.py @@ -33,7 +33,7 @@ class LowLevelCalls(AbstractDetector): def detect_low_level_calls(self, contract): ret = [] - for f in [f for f in contract.functions if contract == f.contract]: + for f in [f for f in contract.functions if contract == f.contract_declarer]: nodes = f.nodes assembly_nodes = [n for n in nodes if self._contains_low_level_calls(n)] @@ -48,8 +48,8 @@ class LowLevelCalls(AbstractDetector): for c in self.contracts: values = self.detect_low_level_calls(c) for func, nodes in values: - info = "Low level call in {}.{} ({}):\n" - info = info.format(func.contract.name, func.name, func.source_mapping_str) + info = "Low level call in {} ({}):\n" + info = info.format(func.canonical_name, func.source_mapping_str) for node in nodes: info += "\t-{} {}\n".format(str(node.expression), node.source_mapping_str) diff --git a/slither/detectors/operations/unused_return_values.py b/slither/detectors/operations/unused_return_values.py index 7abc6525f..532b9a72e 100644 --- a/slither/detectors/operations/unused_return_values.py +++ b/slither/detectors/operations/unused_return_values.py @@ -67,14 +67,14 @@ contract MyConc{ results = [] for c in self.slither.contracts: for f in c.functions + c.modifiers: - if f.contract != c: + if f.contract_declarer != c: continue unused_return = self.detect_unused_return_values(f) if unused_return: + for node in unused_return: - info = "{}.{} ({}) ignores return value by {} \"{}\" ({})\n" - info = info.format(f.contract.name, - f.name, + info = "{} ({}) ignores return value by {} \"{}\" ({})\n" + info = info.format(f.canonical_name, f.source_mapping_str, self._txt_description, node.expression, diff --git a/slither/detectors/reentrancy/reentrancy.py b/slither/detectors/reentrancy/reentrancy.py index 527e80273..be5f95dd9 100644 --- a/slither/detectors/reentrancy/reentrancy.py +++ b/slither/detectors/reentrancy/reentrancy.py @@ -181,7 +181,7 @@ class Reentrancy(AbstractDetector): def detect_reentrancy(self, contract): """ """ - for function in contract.functions_and_modifiers_not_inherited: + for function in contract.functions_and_modifiers_declared: if function.is_implemented: if self.KEY in function.context: continue diff --git a/slither/detectors/reentrancy/reentrancy_benign.py b/slither/detectors/reentrancy/reentrancy_benign.py index 7f8b22596..85daabb5d 100644 --- a/slither/detectors/reentrancy/reentrancy_benign.py +++ b/slither/detectors/reentrancy/reentrancy_benign.py @@ -45,7 +45,7 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr def find_reentrancies(self): result = {} for contract in self.contracts: - for f in contract.functions_and_modifiers_not_inherited: + for f in contract.functions_and_modifiers_declared: for node in f.nodes: # dead code if not self.KEY in node.context: @@ -84,8 +84,8 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr for (func, calls, send_eth), varsWritten in result_sorted: calls = sorted(list(set(calls)), key=lambda x: x.node_id) send_eth = sorted(list(set(send_eth)), key=lambda x: x.node_id) - info = 'Reentrancy in {}.{} ({}):\n' - info = info.format(func.contract.name, func.name, func.source_mapping_str) + info = 'Reentrancy in {} ({}):\n' + info = info.format(func.canonical_name, func.source_mapping_str) info += '\tExternal calls:\n' for call_info in calls: info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) diff --git a/slither/detectors/reentrancy/reentrancy_eth.py b/slither/detectors/reentrancy/reentrancy_eth.py index e74e0fb45..05a0c7a5a 100644 --- a/slither/detectors/reentrancy/reentrancy_eth.py +++ b/slither/detectors/reentrancy/reentrancy_eth.py @@ -47,7 +47,7 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m def find_reentrancies(self): result = {} for contract in self.contracts: - for f in contract.functions_and_modifiers_not_inherited: + for f in contract.functions_and_modifiers_declared: for node in f.nodes: # dead code if not self.KEY in node.context: @@ -87,8 +87,8 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m calls = sorted(list(set(calls)), key=lambda x: x.node_id) send_eth = sorted(list(set(send_eth)), key=lambda x: x.node_id) - info = 'Reentrancy in {}.{} ({}):\n' - info = info.format(func.contract.name, func.name, func.source_mapping_str) + info = 'Reentrancy in {} ({}):\n' + info = info.format(func.canonical_name, func.source_mapping_str) info += '\tExternal calls:\n' for call_info in calls: info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) diff --git a/slither/detectors/reentrancy/reentrancy_read_before_write.py b/slither/detectors/reentrancy/reentrancy_read_before_write.py index 19c706043..dfb8aa9cd 100644 --- a/slither/detectors/reentrancy/reentrancy_read_before_write.py +++ b/slither/detectors/reentrancy/reentrancy_read_before_write.py @@ -46,7 +46,7 @@ Do not report reentrancies that involve ethers (see `reentrancy-eth`)''' def find_reentrancies(self): result = {} for contract in self.contracts: - for f in contract.functions_and_modifiers_not_inherited: + for f in contract.functions_and_modifiers_declared: for node in f.nodes: # dead code if not self.KEY in node.context: @@ -82,8 +82,8 @@ Do not report reentrancies that involve ethers (see `reentrancy-eth`)''' result_sorted = sorted(list(reentrancies.items()), key=lambda x:x[0][0].name) for (func, calls), varsWritten in result_sorted: calls = sorted(list(set(calls)), key=lambda x: x.node_id) - info = 'Reentrancy in {}.{} ({}):\n' - info = info.format(func.contract.name, func.name, func.source_mapping_str) + info = 'Reentrancy in {} ({}):\n' + info = info.format(func.canonical_name, func.source_mapping_str) info += '\tExternal calls:\n' for call_info in calls: info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) diff --git a/slither/detectors/shadowing/abstract.py b/slither/detectors/shadowing/abstract.py index cafdf96f2..15bb7e2c1 100644 --- a/slither/detectors/shadowing/abstract.py +++ b/slither/detectors/shadowing/abstract.py @@ -41,9 +41,9 @@ contract DerivedContract is BaseContract{ variables_fathers = [] for father in contract.inheritance: if all(not f.is_implemented for f in father.functions + father.modifiers): - variables_fathers += [v for v in father.variables if v.contract == father] + variables_fathers += father.state_variables_declared - for var in [v for v in contract.variables if v.contract == contract]: + for var in contract.state_variables_declared: shadow = [v for v in variables_fathers if v.name == var.name] if shadow: ret.append([var] + shadow) @@ -65,12 +65,10 @@ contract DerivedContract is BaseContract{ for all_variables in shadowing: shadow = all_variables[0] variables = all_variables[1:] - info = '{}.{} ({}) shadows:\n'.format(shadow.contract.name, - shadow.name, - shadow.source_mapping_str) + info = '{} ({}) shadows:\n'.format(shadow.canonical_name, + shadow.source_mapping_str) for var in variables: - info += "\t- {}.{} ({})\n".format(var.contract.name, - var.name, + info += "\t- {} ({})\n".format(var.canonical_name, var.source_mapping_str) json = self.generate_json_result(info) diff --git a/slither/detectors/shadowing/builtin_symbols.py b/slither/detectors/shadowing/builtin_symbols.py index 35d9bccf4..2cd4cff09 100644 --- a/slither/detectors/shadowing/builtin_symbols.py +++ b/slither/detectors/shadowing/builtin_symbols.py @@ -90,24 +90,20 @@ contract Bug { result = [] # Loop through all functions, modifiers, variables (state and local) to detect any built-in symbol keywords. - for function in contract.functions: - if function.contract == contract: - if self.is_builtin_symbol(function.name): - result.append((self.SHADOWING_FUNCTION, function, None)) - result += self.detect_builtin_shadowing_locals(function) - for modifier in contract.modifiers: - if modifier.contract == contract: - if self.is_builtin_symbol(modifier.name): - result.append((self.SHADOWING_MODIFIER, modifier, None)) - result += self.detect_builtin_shadowing_locals(modifier) - for variable in contract.variables: - if variable.contract == contract: - if self.is_builtin_symbol(variable.name): - result.append((self.SHADOWING_STATE_VARIABLE, variable, None)) - for event in contract.events: - if event.contract == contract: - if self.is_builtin_symbol(event.name): - result.append((self.SHADOWING_EVENT, event, None)) + for function in contract.functions_declared: + if self.is_builtin_symbol(function.name): + result.append((self.SHADOWING_FUNCTION, function, None)) + result += self.detect_builtin_shadowing_locals(function) + for modifier in contract.modifiers_declared: + if self.is_builtin_symbol(modifier.name): + result.append((self.SHADOWING_MODIFIER, modifier, None)) + result += self.detect_builtin_shadowing_locals(modifier) + for variable in contract.state_variables_declared: + if self.is_builtin_symbol(variable.name): + result.append((self.SHADOWING_STATE_VARIABLE, variable, None)) + for event in contract.events_declared: + if self.is_builtin_symbol(event.name): + result.append((self.SHADOWING_EVENT, event, None)) return result diff --git a/slither/detectors/shadowing/local.py b/slither/detectors/shadowing/local.py index 0c9e830dd..66f769882 100644 --- a/slither/detectors/shadowing/local.py +++ b/slither/detectors/shadowing/local.py @@ -58,7 +58,7 @@ contract Bug { # Loop through all functions + modifiers in this contract. for function in contract.functions + contract.modifiers: # We should only look for functions declared directly in this contract (not in a base contract). - if function.contract != contract: + if function.contract_declarer != contract: continue # This function was declared in this contract, we check what its local variables might shadow. @@ -66,20 +66,20 @@ contract Bug { overshadowed = [] for scope_contract in [contract] + contract.inheritance: # Check functions - for scope_function in scope_contract.functions: - if variable.name == scope_function.name and scope_function.contract == scope_contract: + for scope_function in scope_contract.functions_declared: + if variable.name == scope_function.name: overshadowed.append((self.OVERSHADOWED_FUNCTION, scope_contract.name, scope_function)) # Check modifiers - for scope_modifier in scope_contract.modifiers: - if variable.name == scope_modifier.name and scope_modifier.contract == scope_contract: + for scope_modifier in scope_contract.modifiers_declared: + if variable.name == scope_modifier.name: overshadowed.append((self.OVERSHADOWED_MODIFIER, scope_contract.name, scope_modifier)) # Check events - for scope_event in scope_contract.events: - if variable.name == scope_event.name and scope_event.contract == scope_contract: + for scope_event in scope_contract.events_declared: + if variable.name == scope_event.name: overshadowed.append((self.OVERSHADOWED_EVENT, scope_contract.name, scope_event)) # Check state variables - for scope_state_variable in scope_contract.variables: - if variable.name == scope_state_variable.name and scope_state_variable.contract == scope_contract: + for scope_state_variable in scope_contract.state_variables_declared: + if variable.name == scope_state_variable.name: overshadowed.append((self.OVERSHADOWED_STATE_VARIABLE, scope_contract.name, scope_state_variable)) # If we have found any overshadowed objects, we'll want to add it to our result list. diff --git a/slither/detectors/shadowing/state.py b/slither/detectors/shadowing/state.py index bd0b67d89..41da711f3 100644 --- a/slither/detectors/shadowing/state.py +++ b/slither/detectors/shadowing/state.py @@ -53,9 +53,9 @@ contract DerivedContract is BaseContract{ variables_fathers = [] for father in contract.inheritance: if any(f.is_implemented for f in father.functions + father.modifiers): - variables_fathers += [v for v in father.variables if v.contract == father] + variables_fathers += father.state_variables_declared - for var in [v for v in contract.variables if v.contract == contract]: + for var in contract.state_variables_declared: shadow = [v for v in variables_fathers if v.name == var.name] if shadow: ret.append([var] + shadow) @@ -76,13 +76,11 @@ contract DerivedContract is BaseContract{ for all_variables in shadowing: shadow = all_variables[0] variables = all_variables[1:] - info = '{}.{} ({}) shadows:\n'.format(shadow.contract.name, - shadow.name, - shadow.source_mapping_str) + info = '{} ({}) shadows:\n'.format(shadow.canonical_name, + shadow.source_mapping_str) for var in variables: - info += "\t- {}.{} ({})\n".format(var.contract.name, - var.name, - var.source_mapping_str) + info += "\t- {} ({})\n".format(var.canonical_name, + var.source_mapping_str) json = self.generate_json_result(info) self.add_variables_to_json(all_variables, json) diff --git a/slither/detectors/statements/assembly.py b/slither/detectors/statements/assembly.py index e1b35a6f2..936794366 100644 --- a/slither/detectors/statements/assembly.py +++ b/slither/detectors/statements/assembly.py @@ -35,7 +35,7 @@ class Assembly(AbstractDetector): def detect_assembly(self, contract): ret = [] for f in contract.functions: - if f.contract != contract: + if f.contract_declarer != contract: continue nodes = f.nodes assembly_nodes = [n for n in nodes if @@ -51,8 +51,8 @@ class Assembly(AbstractDetector): for c in self.contracts: values = self.detect_assembly(c) for func, nodes in values: - info = "{}.{} uses assembly ({})\n" - info = info.format(func.contract.name, func.name, func.source_mapping_str) + info = "{} uses assembly ({})\n" + info = info.format(func.canonical_name, func.source_mapping_str) for node in nodes: info += "\t- {}\n".format(node.source_mapping_str) diff --git a/slither/detectors/statements/calls_in_loop.py b/slither/detectors/statements/calls_in_loop.py index 187e2a748..27622ad4a 100644 --- a/slither/detectors/statements/calls_in_loop.py +++ b/slither/detectors/statements/calls_in_loop.py @@ -72,7 +72,7 @@ If one of the destinations has a fallback function which reverts, `bad` will alw def detect_call_in_loop(contract): ret = [] for f in contract.functions + contract.modifiers: - if f.contract == contract and f.is_implemented: + if f.contract_declarer == contract and f.is_implemented: MultipleCallsInLoop.call_in_loop(f.entry_point, False, [], ret) @@ -86,8 +86,9 @@ If one of the destinations has a fallback function which reverts, `bad` will alw values = self.detect_call_in_loop(c) for node in values: func = node.function - info = "{}.{} has external calls inside a loop: \"{}\" ({})\n" - info = info.format(func.contract.name, func.name, node.expression, node.source_mapping_str) + + info = "{} has external calls inside a loop: \"{}\" ({})\n" + info = info.format(func.canonical_name, node.expression, node.source_mapping_str) json = self.generate_json_result(info) self.add_node_to_json(node, json) diff --git a/slither/detectors/statements/controlled_delegatecall.py b/slither/detectors/statements/controlled_delegatecall.py index 4b952426e..e84277009 100644 --- a/slither/detectors/statements/controlled_delegatecall.py +++ b/slither/detectors/statements/controlled_delegatecall.py @@ -42,7 +42,7 @@ Bob calls `delegate` and delegates the execution to its malicious contract. As a for contract in self.slither.contracts: for f in contract.functions: - if f.contract != contract: + if f.contract_declarer != contract: continue nodes = self.controlled_delegatecall(f) if nodes: diff --git a/slither/detectors/statements/deprecated_calls.py b/slither/detectors/statements/deprecated_calls.py index 6d0566549..c18843125 100644 --- a/slither/detectors/statements/deprecated_calls.py +++ b/slither/detectors/statements/deprecated_calls.py @@ -111,20 +111,14 @@ contract ContractWithDeprecatedReferences { list of tuple: (state_variable | node, (detecting_signature, original_text, recommended_text))""" results = [] - for state_variable in contract.variables: - if state_variable.contract != contract: - continue + for state_variable in contract.state_variables_declared: if state_variable.expression: deprecated_results = self.detect_deprecation_in_expression(state_variable.expression) if deprecated_results: results.append((state_variable, deprecated_results)) # Loop through all functions + modifiers in this contract. - for function in contract.functions + contract.modifiers: - # We should only look for functions declared directly in this contract (not in a base contract). - if function.contract != contract: - continue - + for function in contract.functions_and_modifiers_declared: # Loop through each node in this function. for node in function.nodes: # Detect deprecated references in the node. diff --git a/slither/detectors/statements/incorrect_strict_equality.py b/slither/detectors/statements/incorrect_strict_equality.py index 2178a2fd6..fe5da8cbf 100644 --- a/slither/detectors/statements/incorrect_strict_equality.py +++ b/slither/detectors/statements/incorrect_strict_equality.py @@ -111,9 +111,9 @@ contract Crowdsale{ # sort ret to get deterministic results ret = sorted(list(ret.items()), key=lambda x:x[0].name) for f, nodes in ret: - func_info = "{}.{} ({}) uses a dangerous strict equality:\n".format(f.contract.name, - f.name, - f.source_mapping_str) + + func_info = "{} ({}) uses a dangerous strict equality:\n".format(f.canonical_name, + f.source_mapping_str) # sort the nodes to get deterministic results nodes.sort(key=lambda x: x.node_id) diff --git a/slither/detectors/statements/tx_origin.py b/slither/detectors/statements/tx_origin.py index fa49fc0b3..e759366eb 100644 --- a/slither/detectors/statements/tx_origin.py +++ b/slither/detectors/statements/tx_origin.py @@ -65,11 +65,11 @@ Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls ` for c in self.contracts: values = self.detect_tx_origin(c) for func, nodes in values: + for node in nodes: - info = "{}.{} uses tx.origin for authorization: \"{}\" ({})\n".format(func.contract.name, - func.name, - node.expression, - node.source_mapping_str) + info = "{} uses tx.origin for authorization: \"{}\" ({})\n".format(func.canonical_name, + node.expression, + node.source_mapping_str) json = self.generate_json_result(info) self.add_node_to_json(node, json) diff --git a/slither/detectors/variables/possible_const_state_variables.py b/slither/detectors/variables/possible_const_state_variables.py index 9e03634a4..d509f4569 100644 --- a/slither/detectors/variables/possible_const_state_variables.py +++ b/slither/detectors/variables/possible_const_state_variables.py @@ -86,11 +86,11 @@ class ConstCandidateStateVars(AbstractDetector): # Create a result for each finding for v in constable_variables: - info = "{}.{} should be constant ({})\n".format(v.contract.name, - v.name, - v.source_mapping_str) + info = "{} should be constant ({})\n".format(v.canonical_name, + v.source_mapping_str) json = self.generate_json_result(info) self.add_variable_to_json(v, json) + results.append(json) return results diff --git a/slither/detectors/variables/uninitialized_local_variables.py b/slither/detectors/variables/uninitialized_local_variables.py index d9854b339..39219ae4a 100644 --- a/slither/detectors/variables/uninitialized_local_variables.py +++ b/slither/detectors/variables/uninitialized_local_variables.py @@ -90,7 +90,7 @@ Bob calls `transfer`. As a result, the ethers are sent to the address 0x0 and ar for contract in self.slither.contracts: for function in contract.functions: - if function.is_implemented and function.contract == contract: + if function.is_implemented and function.contract_declarer == contract: if function.contains_assembly: continue # dont consider storage variable, as they are detected by another detector @@ -101,10 +101,9 @@ Bob calls `transfer`. As a result, the ethers are sent to the address 0x0 and ar for(function, uninitialized_local_variable) in all_results: var_name = uninitialized_local_variable.name - info = "{} in {}.{} ({}) is a local variable never initialiazed\n" + info = "{} in {} ({}) is a local variable never initialiazed\n" info = info.format(var_name, - function.contract.name, - function.name, + function.canonical_name, uninitialized_local_variable.source_mapping_str) diff --git a/slither/detectors/variables/uninitialized_state_variables.py b/slither/detectors/variables/uninitialized_state_variables.py index 2dec5e7e5..18b89324b 100644 --- a/slither/detectors/variables/uninitialized_state_variables.py +++ b/slither/detectors/variables/uninitialized_state_variables.py @@ -92,9 +92,8 @@ Initialize all the variables. If a variable is meant to be initialized to zero, for c in self.slither.contracts_derived: ret = self.detect_uninitialized(c) for variable, functions in ret: - info = "{}.{} ({}) is never initialized. It is used in:\n" - info = info.format(variable.contract.name, - variable.name, + info = "{} ({}) is never initialized. It is used in:\n" + info = info.format(variable.canonical_name, variable.source_mapping_str) for f in functions: info += "\t- {} ({})\n".format(f.name, f.source_mapping_str) diff --git a/slither/detectors/variables/uninitialized_storage_variables.py b/slither/detectors/variables/uninitialized_storage_variables.py index 3cc5a56ef..ef1d9ba3c 100644 --- a/slither/detectors/variables/uninitialized_storage_variables.py +++ b/slither/detectors/variables/uninitialized_storage_variables.py @@ -105,8 +105,8 @@ Bob calls `func`. As a result, `owner` is override to 0. for(function, uninitialized_storage_variable) in self.results: var_name = uninitialized_storage_variable.name - info = "{} in {}.{} ({}) is a storage variable never initialiazed\n" - info = info.format(var_name, function.contract.name, function.name, uninitialized_storage_variable.source_mapping_str) + info = "{} in {} ({}) is a storage variable never initialiazed\n" + info = info.format(var_name, function.canonical_name, uninitialized_storage_variable.source_mapping_str) json = self.generate_json_result(info) diff --git a/slither/detectors/variables/unused_state_variables.py b/slither/detectors/variables/unused_state_variables.py index 5c29562b3..8f03cae8e 100644 --- a/slither/detectors/variables/unused_state_variables.py +++ b/slither/detectors/variables/unused_state_variables.py @@ -56,10 +56,10 @@ class UnusedStateVars(AbstractDetector): unusedVars = self.detect_unused(c) if unusedVars: for var in unusedVars: - info = "{}.{} ({}) is never used in {}\n".format(var.contract.name, - var.name, - var.source_mapping_str, - c.name) + info = "{} ({}) is never used in {}\n".format(var.canonical_name, + var.source_mapping_str, + c.name) + json = self.generate_json_result(info) self.add_variable_to_json(var, json) diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py index 468969002..73ee72af8 100644 --- a/slither/printers/inheritance/inheritance_graph.py +++ b/slither/printers/inheritance/inheritance_graph.py @@ -91,8 +91,8 @@ class PrinterInheritanceGraph(AbstractPrinter): indirect_shadows = detect_c3_function_shadowing(contract) if indirect_shadows: for collision_set in sorted(indirect_shadows, key=lambda x: x[0][1].name): - winner = collision_set[-1][1].contract.name - collision_steps = [colliding_function.contract.name for _, colliding_function in collision_set] + winner = collision_set[-1][1].contract_declarer.name + collision_steps = [colliding_function.contract_declarer.name for _, colliding_function in collision_set] collision_steps = ', '.join(collision_steps) result.append(f"'{collision_set[0][1].full_name}' collides in inherited contracts {collision_steps} where {winner} is chosen.") return '\n'.join(result) @@ -116,23 +116,23 @@ class PrinterInheritanceGraph(AbstractPrinter): # Functions visibilities = ['public', 'external'] public_functions = [self._get_pattern_func(f, contract) for f in contract.functions if - not f.is_constructor and f.contract == contract and f.visibility in visibilities] + not f.is_constructor and f.contract_declarer == contract and f.visibility in visibilities] public_functions = ''.join(public_functions) private_functions = [self._get_pattern_func(f, contract) for f in contract.functions if - not f.is_constructor and f.contract == contract and f.visibility not in visibilities] + not f.is_constructor and f.contract_declarer == contract and f.visibility not in visibilities] private_functions = ''.join(private_functions) # Modifiers - modifiers = [self._get_pattern_func(m, contract) for m in contract.modifiers if m.contract == contract] + modifiers = [self._get_pattern_func(m, contract) for m in contract.modifiers if m.contract_declarer == contract] modifiers = ''.join(modifiers) # Public variables - public_variables = [self._get_pattern_var(v, contract) for v in contract.variables if - v.contract == contract and v.visibility in visibilities] + public_variables = [self._get_pattern_var(v, contract) for v in contract.state_variables_declared + if v.visibility in visibilities] public_variables = ''.join(public_variables) - private_variables = [self._get_pattern_var(v, contract) for v in contract.variables if - v.contract == contract and v.visibility not in visibilities] + private_variables = [self._get_pattern_var(v, contract) for v in contract.state_variables_declared + if v.visibility not in visibilities] private_variables = ''.join(private_variables) # Obtain any indirect shadowing information for this node. diff --git a/slither/printers/summary/data_depenency.py b/slither/printers/summary/data_depenency.py index d64a0f638..c8fb38277 100644 --- a/slither/printers/summary/data_depenency.py +++ b/slither/printers/summary/data_depenency.py @@ -35,7 +35,7 @@ class DataDependency(AbstractPrinter): txt += str(table) txt += "\n" - for f in c.functions_and_modifiers_not_inherited: + for f in c.functions_and_modifiers_declared: txt += "\nFunction %s\n"%f.full_name table = PrettyTable(['Variable', 'Dependencies']) for v in f.variables: diff --git a/slither/printers/summary/slithir.py b/slither/printers/summary/slithir.py index 3cad7b4e4..cd4a7299f 100644 --- a/slither/printers/summary/slithir.py +++ b/slither/printers/summary/slithir.py @@ -23,26 +23,24 @@ class PrinterSlithIR(AbstractPrinter): for contract in self.contracts: print('Contract {}'.format(contract.name)) for function in contract.functions: - if function.contract == contract: - print('\tFunction {}'.format(function.full_name)) - for node in function.nodes: - if node.expression: - print('\t\tExpression: {}'.format(node.expression)) - print('\t\tIRs:') - for ir in node.irs: - print('\t\t\t{}'.format(ir)) - elif node.irs: - print('\t\tIRs:') - for ir in node.irs: - print('\t\t\t{}'.format(ir)) + print(f'\tFunction {function.canonical_name}') + for node in function.nodes: + if node.expression: + print('\t\tExpression: {}'.format(node.expression)) + print('\t\tIRs:') + for ir in node.irs: + print('\t\t\t{}'.format(ir)) + elif node.irs: + print('\t\tIRs:') + for ir in node.irs: + print('\t\t\t{}'.format(ir)) for modifier in contract.modifiers: - if modifier.contract == contract: - print('\tModifier {}'.format(modifier.full_name)) - for node in modifier.nodes: - print(node) - if node.expression: - print('\t\tExpression: {}'.format(node.expression)) - print('\t\tIRs:') - for ir in node.irs: - print('\t\t\t{}'.format(ir)) + print('\tModifier {}'.format(modifier.canonical_name)) + for node in modifier.nodes: + print(node) + if node.expression: + print('\t\tExpression: {}'.format(node.expression)) + print('\t\tIRs:') + for ir in node.irs: + print('\t\t\t{}'.format(ir)) self.info(txt) diff --git a/slither/printers/summary/slithir_ssa.py b/slither/printers/summary/slithir_ssa.py index 6227c4167..c97a291fa 100644 --- a/slither/printers/summary/slithir_ssa.py +++ b/slither/printers/summary/slithir_ssa.py @@ -23,24 +23,22 @@ class PrinterSlithIRSSA(AbstractPrinter): for contract in self.contracts: print('Contract {}'.format(contract.name)) for function in contract.functions: - if function.contract == contract: - print('\tFunction {}'.format(function.full_name)) - for node in function.nodes: - if node.expression: - print('\t\tExpression: {}'.format(node.expression)) - if node.irs_ssa: - print('\t\tIRs:') - for ir in node.irs_ssa: - print('\t\t\t{}'.format(ir)) + print('\tFunction {}'.format(function.canonical_name)) + for node in function.nodes: + if node.expression: + print('\t\tExpression: {}'.format(node.expression)) + if node.irs_ssa: + print('\t\tIRs:') + for ir in node.irs_ssa: + print('\t\t\t{}'.format(ir)) for modifier in contract.modifiers: - if modifier.contract == contract: - print('\tModifier {}'.format(modifier.full_name)) - for node in modifier.nodes: - print(node) - if node.expression: - print('\t\tExpression: {}'.format(node.expression)) - if node.irs_ssa: - print('\t\tIRs:') - for ir in node.irs_ssa: - print('\t\t\t{}'.format(ir)) + print('\tModifier {}'.format(modifier.canonical_name)) + for node in modifier.nodes: + print(node) + if node.expression: + print('\t\tExpression: {}'.format(node.expression)) + if node.irs_ssa: + print('\t\tIRs:') + for ir in node.irs_ssa: + print('\t\t\t{}'.format(ir)) self.info(txt) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 13c51d193..c9014edf2 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -104,6 +104,21 @@ def get_sig(ir, name): argss = convert_arguments(ir.arguments) return [sig.format(name, ','.join(args)) for args in argss] +def get_canonical_names(ir, function_name, contract_name): + ''' + Return a list of potential signature + It is a list, as Constant variables can be converted to int256 + Args: + ir (slithIR.operation) + Returns: + list(str) + ''' + sig = '{}({})' + + # list of list of arguments + argss = convert_arguments(ir.arguments) + return [sig.format(f'{contract_name}.{function_name}', ','.join(args)) for args in argss] + def convert_arguments(arguments): argss = [[]] for arg in arguments: @@ -399,7 +414,7 @@ def propagate_types(ir, node): elif isinstance(ir, InternalCall): # if its not a tuple, return a singleton if ir.function is None: - convert_type_of_high_and_internal_level_call(ir, ir.contract) + convert_type_of_high_and_internal_level_call(ir, node.function.contract) return_type = ir.function.return_type if return_type: if len(return_type) == 1: @@ -520,7 +535,7 @@ def extract_tmp_call(ins, contract): # If there is a call on an inherited contract, it is an internal call or an event if ins.ori.variable_left in contract.inheritance + [contract]: if str(ins.ori.variable_right) in [f.name for f in contract.functions]: - internalcall = InternalCall(ins.ori.variable_right, ins.ori.variable_left, ins.nbr_arguments, ins.lvalue, ins.type_call) + internalcall = InternalCall((ins.ori.variable_right, ins.ori.variable_left.name), ins.nbr_arguments, ins.lvalue, ins.type_call) internalcall.call_id = ins.call_id return internalcall if str(ins.ori.variable_right) in [f.name for f in contract.events]: @@ -695,7 +710,10 @@ def look_for_library(contract, ir, node, using_for, t): return None def convert_to_library(ir, node, using_for): - contract = node.function.contract + # We use contract_declarer, because Solidity resolve the library + # before resolving the inheritance. + # Though we could use .contract as libraries cannot be shadowed + contract = node.function.contract_declarer t = ir.destination.type if t in using_for: @@ -759,14 +777,25 @@ def convert_type_library_call(ir, lib_contract): def convert_type_of_high_and_internal_level_call(ir, contract): func = None - sigs = get_sig(ir, ir.function_name) - for sig in sigs: - func = contract.get_function_from_signature(sig) - if not func: - func = contract.get_state_variable_from_name(ir.function_name) - if func: - # stop to explore if func is found (prevent dupplicate issue) - break + if isinstance(ir, InternalCall): + sigs = get_canonical_names(ir, ir.function_name, ir.contract_name) + for sig in sigs: + func = contract.get_function_from_canonical_name(sig) + if not func: + func = contract.get_state_variable_from_name(ir.function_name) + if func: + # stop to explore if func is found (prevent dupplicate issue) + break + else: + assert isinstance(ir, HighLevelCall) + sigs = get_sig(ir, ir.function_name) + for sig in sigs: + func = contract.get_function_from_canonical_name(sig) + if not func: + func = contract.get_state_variable_from_name(ir.function_name) + if func: + # stop to explore if func is found (prevent dupplicate issue) + break if not func: # specific lookup when the compiler does implicit conversion # for example diff --git a/slither/slithir/operations/internal_call.py b/slither/slithir/operations/internal_call.py index 5f2210e90..8056695f3 100644 --- a/slither/slithir/operations/internal_call.py +++ b/slither/slithir/operations/internal_call.py @@ -1,21 +1,20 @@ from slither.core.declarations.function import Function from slither.slithir.operations.call import Call from slither.slithir.operations.lvalue import OperationWithLValue -from slither.core.variables.variable import Variable from slither.slithir.variables import Constant class InternalCall(Call, OperationWithLValue): - def __init__(self, function, contract, nbr_arguments, result, type_call): + def __init__(self, function, nbr_arguments, result, type_call): super(InternalCall, self).__init__() if isinstance(function, Function): self._function = function self._function_name = function.name + self._contract_name = function.contract_declarer.name else: - isinstance(function, Constant) self._function = None - self._function_name = function - self._contract = contract + self._function_name, self._contract_name = function + #self._contract = contract self._nbr_arguments = nbr_arguments self._type_call = type_call self._lvalue = result @@ -32,14 +31,14 @@ class InternalCall(Call, OperationWithLValue): def function(self, f): self._function = f - @property - def contract(self): - return self._contract - @property def function_name(self): return self._function_name + @property + def contract_name(self): + return self._contract_name + @property def nbr_arguments(self): return self._nbr_arguments @@ -56,9 +55,8 @@ class InternalCall(Call, OperationWithLValue): lvalue = '{}({}) = '.format(self.lvalue, ','.join(str(x) for x in self.lvalue.type)) else: lvalue = '{}({}) = '.format(self.lvalue, self.lvalue.type) - txt = '{}INTERNAL_CALL, {}.{}({})' + txt = '{}INTERNAL_CALL, {}({})' return txt.format(lvalue, - self.function.contract.name, - self.function.full_name, + self.function.canonical_name, ','.join(args)) diff --git a/slither/slithir/utils/ssa.py b/slither/slithir/utils/ssa.py index 64acac84c..fde9f5eba 100644 --- a/slither/slithir/utils/ssa.py +++ b/slither/slithir/utils/ssa.py @@ -566,7 +566,7 @@ def copy_ir(ir, *instances): nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: x.lvalue, *instances) type_call = ir.type_call - new_ir = InternalCall(function, function.contract, nbr_arguments, lvalue, type_call) + new_ir = InternalCall(function, nbr_arguments, lvalue, type_call) new_ir.arguments = get_arguments(ir, *instances) return new_ir elif isinstance(ir, InternalDynamicCall): diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index ff50df013..0bedaf9c9 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -232,8 +232,9 @@ class ContractSolc04(Contract): def _parse_modifier(self, modifier): - modif = ModifierSolc(modifier, self) + modif = ModifierSolc(modifier, self, self) modif.set_contract(self) + modif.set_contract_declarer(self) modif.set_offset(modifier['src'], self.slither) self.slither.add_modifier(modif) self._modifiers_no_params.append(modif) @@ -247,7 +248,7 @@ class ContractSolc04(Contract): return def _parse_function(self, function): - func = FunctionSolc(function, self) + func = FunctionSolc(function, self, self) func.set_offset(function['src'], self.slither) self.slither.add_function(func) self._functions_no_params.append(func) @@ -281,26 +282,52 @@ class ContractSolc04(Contract): return def analyze_params_modifiers(self): - for father in self.inheritance_reverse: - self._modifiers.update(father.modifiers_as_dict()) - for modifier in self._modifiers_no_params: - modifier.analyze_params() - self._modifiers[modifier.full_name] = modifier + elements_no_params = self._modifiers_no_params + getter = lambda f: f.modifiers + getter_available = lambda f: f.available_modifiers_as_dict().items() + Cls = ModifierSolc + self._modifiers = self._analyze_params_elements(elements_no_params, getter, getter_available, Cls) self._modifiers_no_params = [] + return def analyze_params_functions(self): - # keep track of the contracts visited - # to prevent an ovveride due to multiple inheritance of the same contract - # A is B, C, D is C, --> the second C was already seen - contracts_visited = [] - for father in self.inheritance_reverse: - functions = {k:v for (k, v) in father.functions_as_dict().items() - if not v.contract in contracts_visited} - contracts_visited.append(father) - self._functions.update(functions) + + elements_no_params = self._functions_no_params + getter = lambda f: f.functions + getter_available = lambda f: f.available_functions_as_dict().items() + Cls = FunctionSolc + self._functions = self._analyze_params_elements(elements_no_params, getter, getter_available, Cls) + + self._functions_no_params = [] + return + + + def _analyze_params_elements(self, elements_no_params, getter, getter_available, Cls): + """ + Analyze the parameters of the given elements (Function or Modifier). + The function iterates over the inheritance to create an instance or inherited elements (Function or Modifier) + If the element is shadowed, set is_shadowed to True + :param elements_no_params: list of elements to analyzer + :param getter: fun x + :param getter_available: fun x + :param Cls: Class to create for collision + :return: + """ + all_elements = {} + accessible_elements = {} + + for father in self.inheritance: + for element in getter(father): + elem = Cls(element._functionNotParsed, self, element.contract_declarer) + elem.set_offset(element._functionNotParsed['src'], self.slither) + elem.analyze_params() + self.slither.add_function(elem) + all_elements[elem.canonical_name] = elem + + accessible_elements = self.available_elements_from_inheritances(all_elements, getter_available) # If there is a constructor in the functions # We remove the previous constructor @@ -308,20 +335,25 @@ class ContractSolc04(Contract): # # Note: contract.all_functions_called returns the constructors of the base contracts has_constructor = False - for function in self._functions_no_params: - function.analyze_params() - if function.is_constructor: + for element in elements_no_params: + element.analyze_params() + if element.is_constructor: has_constructor = True if has_constructor: - _functions = {k:v for (k, v) in self._functions.items() if not v.is_constructor} - self._functions = _functions + _accessible_functions = {k: v for (k, v) in accessible_elements.items() if not v.is_constructor} + + for element in elements_no_params: + accessible_elements[element.full_name] = element + all_elements[element.canonical_name] = element + + for element in all_elements.values(): + if accessible_elements[element.full_name] != all_elements[element.canonical_name]: + element.is_shadowed = True + + return all_elements - for function in self._functions_no_params: - self._functions[function.full_name] = function - self._functions_no_params = [] - return def analyze_constant_state_variables(self): from slither.solc_parsing.expressions.expression_parsing import VariableNotFound @@ -434,17 +466,15 @@ class ContractSolc04(Contract): def convert_expression_to_slithir(self): for func in self.functions + self.modifiers: - if func.contract == self: - func.generate_slithir_and_analyze() + func.generate_slithir_and_analyze() all_ssa_state_variables_instances = dict() for contract in self.inheritance: - for v in contract.variables: - if v.contract == contract: - new_var = StateIRVariable(v) - all_ssa_state_variables_instances[v.canonical_name] = new_var - self._initial_state_variables.append(new_var) + for v in contract.state_variables_declared: + new_var = StateIRVariable(v) + all_ssa_state_variables_instances[v.canonical_name] = new_var + self._initial_state_variables.append(new_var) for v in self.variables: if v.contract == self: @@ -453,8 +483,7 @@ class ContractSolc04(Contract): self._initial_state_variables.append(new_var) for func in self.functions + self.modifiers: - if func.contract == self: - func.generate_slithir_ssa(all_ssa_state_variables_instances) + func.generate_slithir_ssa(all_ssa_state_variables_instances) def fix_phi(self): last_state_variables_instances = dict() diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 7619dea08..f66b3efd7 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -36,9 +36,10 @@ class FunctionSolc(Function): """ # elems = [(type, name)] - def __init__(self, function, contract): + def __init__(self, function, contract, contract_declarer): super(FunctionSolc, self).__init__() self._contract = contract + self._contract_declarer = contract_declarer # Only present if compact AST self._referenced_declaration = None diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py index e871c53d9..5055c886f 100644 --- a/slither/solc_parsing/expressions/expression_parsing.py +++ b/slither/solc_parsing/expressions/expression_parsing.py @@ -60,15 +60,31 @@ def get_pointer_name(variable): return None -def find_variable(var_name, caller_context, referenced_declaration=None): - +def find_variable(var_name, caller_context, referenced_declaration=None, is_super=False): + + # variable are looked from the contract declarer + # functions can be shadowed, but are looked from the contract instance, rather than the contract declarer + # the difference between function and variable come from the fact that an internal call, or an variable access + # in a function does not behave similariy, for example in: + # contract C{ + # function f(){ + # state_var = 1 + # f2() + # } + # state_var will refer to C.state_var, no mater if C is inherited + # while f2() will refer to the function definition of the inherited contract (C.f2() in the context of C, or + # the contract inheriting from C) + # for events it's unclear what should be the behavior, as they can be shadowed, but there is not impact + # structure/enums cannot be shadowed if isinstance(caller_context, Contract): function = None contract = caller_context + contract_declarer = caller_context elif isinstance(caller_context, Function): function = caller_context contract = function.contract + contract_declarer = function.contract_declarer else: raise ParsingError('Incorrect caller context') @@ -90,24 +106,35 @@ def find_variable(var_name, caller_context, referenced_declaration=None): if var_name and var_name in func_variables_ptr: return func_variables_ptr[var_name] - contract_variables = contract.variables_as_dict() + # variable are looked from the contract declarer + contract_variables = contract_declarer.variables_as_dict() if var_name in contract_variables: return contract_variables[var_name] # A state variable can be a pointer - conc_variables_ptr = {get_pointer_name(f) : f for f in contract.variables} + conc_variables_ptr = {get_pointer_name(f) : f for f in contract_declarer.variables} if var_name and var_name in conc_variables_ptr: return conc_variables_ptr[var_name] - - functions = contract.functions_as_dict() + if is_super: + getter_available = lambda f: f.available_functions_as_dict().items() + d = {f.canonical_name:f for f in contract.functions} + functions = {f.full_name:f for f in contract.available_elements_from_inheritances(d, getter_available).values()} + else: + functions = contract.available_functions_as_dict() if var_name in functions: return functions[var_name] - modifiers = contract.modifiers_as_dict() + if is_super: + getter_available = lambda m: m.available_modifiers_as_dict().items() + d = {m.canonical_name: m for m in contract.modifiers} + modifiers = {m.full_name: m for m in contract.available_elements_from_inheritances(d, getter_available).values()} + else: + modifiers = contract.available_modifiers_as_dict() if var_name in modifiers: return modifiers[var_name] + # structures are looked on the contract declarer structures = contract.structures_as_dict() if var_name in structures: return structures[var_name] @@ -530,6 +557,7 @@ def parse_expression(expression, caller_context): referenced_declaration = expression['referencedDeclaration'] else: referenced_declaration = None + var = find_variable(value, caller_context, referenced_declaration) identifier = Identifier(var) @@ -571,18 +599,7 @@ def parse_expression(expression, caller_context): member_expression = parse_expression(children[0], caller_context) if str(member_expression) == 'super': super_name = parse_super_name(expression, is_compact_ast) - if isinstance(caller_context, Contract): - inheritance = caller_context.inheritance - else: - assert isinstance(caller_context, Function) - inheritance = caller_context.contract.inheritance - var = None - for father in inheritance: - try: - var = find_variable(super_name, father) - break - except VariableNotFound: - continue + var = find_variable(super_name, caller_context, is_super=True) if var is None: raise VariableNotFound('Variable not found: {}'.format(super_name)) return SuperIdentifier(var) diff --git a/slither/solc_parsing/solidity_types/type_parsing.py b/slither/solc_parsing/solidity_types/type_parsing.py index af9a0bdb4..305c38812 100644 --- a/slither/solc_parsing/solidity_types/type_parsing.py +++ b/slither/solc_parsing/solidity_types/type_parsing.py @@ -59,7 +59,7 @@ def _find_from_type_name(name, contract, contracts, structures, enums): all_enums = [item for sublist in all_enums for item in sublist] var_type = next((e for e in all_enums if e.name == enum_name), None) if not var_type: - var_type = next((e for e in all_enums if e.contract.name+"."+e.name == enum_name), None) + var_type = next((e for e in all_enums if e.canonical_name == enum_name), None) if not var_type: # any contract can refer to another contract's structure name_struct = name @@ -70,14 +70,14 @@ def _find_from_type_name(name, contract, contracts, structures, enums): all_structures = [item for sublist in all_structures for item in sublist] var_type = next((st for st in all_structures if st.name == name_struct), None) if not var_type: - var_type = next((st for st in all_structures if st.contract.name+"."+st.name == name_struct), None) + var_type = next((st for st in all_structures if st.canonical_name == name_struct), None) # case where struct xxx.xx[] where not well formed in the AST if not var_type: depth = 0 while name_struct.endswith('[]'): name_struct = name_struct[0:-2] depth+=1 - var_type = next((st for st in all_structures if st.contract.name+"."+st.name == name_struct), None) + var_type = next((st for st in all_structures if st.canonical_name == name_struct), None) if var_type: return ArrayType(UserDefinedType(var_type), Literal(depth, 'uint256')) diff --git a/slither/utils/inheritance_analysis.py b/slither/utils/inheritance_analysis.py index de05b246f..013de531e 100644 --- a/slither/utils/inheritance_analysis.py +++ b/slither/utils/inheritance_analysis.py @@ -19,7 +19,7 @@ def detect_c3_function_shadowing(contract): for i in range(0, len(contract.immediate_inheritance) - 1): inherited_contract1 = contract.immediate_inheritance[i] - for function1 in inherited_contract1.functions_and_modifiers: + for function1 in inherited_contract1.functions_and_modifiers_declared: # If this function has already be handled or is unimplemented, we skip it if function1.full_name in results or function1.is_constructor or not function1.is_implemented: continue @@ -61,7 +61,7 @@ def detect_direct_function_shadowing(contract): function (could have provided it through inheritance, does not need to directly define it). -overshadowed_function is the function definition which is overshadowed by the provided contract's definition. """ - functions_declared = {function.full_name: function for function in contract.functions_and_modifiers_not_inherited} + functions_declared = {function.full_name: function for function in contract.functions_and_modifiers_declared} results = {} for base_contract in reversed(contract.immediate_inheritance): for base_function in base_contract.functions_and_modifiers: @@ -109,7 +109,7 @@ def detect_function_shadowing(contracts, direct_shadowing=True, indirect_shadowi for y in range(x + 1, len(colliding_functions)): # The same function definition can appear more than once in the inheritance chain, # overshadowing items between, so it is important to remember to filter it out here. - if colliding_functions[y][1].contract != colliding_functions[x][1].contract: + if colliding_functions[y][1].contract_declarer != colliding_functions[x][1].contract_declarer: results.add((contract, colliding_functions[y][0], colliding_functions[y][1], colliding_functions[x][0], colliding_functions[x][1])) @@ -128,8 +128,7 @@ def detect_state_variable_shadowing(contracts): """ results = set() for contract in contracts: - variables_declared = {variable.name: variable for variable in contract.variables - if variable.contract == contract} + variables_declared = {variable.name: variable for variable in contract.state_variables_declared} for immediate_base_contract in contract.immediate_inheritance: for variable in immediate_base_contract.variables: if variable.name in variables_declared: diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index b1f5acbce..7799cf128 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -129,7 +129,7 @@ class ExpressionToSlithIR(ExpressionVisitor): val = TupleVariable(self._node) else: val = TemporaryVariable(self._node) - internal_call = InternalCall(called, called.contract, len(args), val, expression.type_call) + internal_call = InternalCall(called, len(args), val, expression.type_call) self._result.append(internal_call) set_val(expression, val) else: diff --git a/tests/check-upgradeability/test_5.txt b/tests/check-upgradeability/test_5.txt index 8ddb49d85..fc7bf6e2c 100644 --- a/tests/check-upgradeability/test_5.txt +++ b/tests/check-upgradeability/test_5.txt @@ -1,6 +1,6 @@ INFO:CheckInitialization:Run initialization checks... (see https://github.com/crytic/slither/wiki/Upgradeability-Checks#initialization-checks) -INFO:CheckInitialization:Contract_lack_to_call_modifier.initialize does not call initializer -INFO:CheckInitialization:Missing call to Contract_no_bug.initialize in Contract_not_called_super_init +INFO:CheckInitialization:Contract_lack_to_call_modifier.initialize() does not call initializer +INFO:CheckInitialization:Missing call to Contract_no_bug.initialize() in Contract_not_called_super_init INFO:CheckInitialization:Contract_no_bug.initialize() is called multiple time in Contract_double_call INFO:CheckInitialization:Check the deployement script to ensure that these functions are called: Contract_no_bug needs to be initialized by initialize() diff --git a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json index 28aee86f5..60542bbe6 100644 --- a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json +++ b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json @@ -7,7 +7,7 @@ "check": "arbitrary-send", "impact": "High", "confidence": "Medium", - "description": "Test.direct (tests/arbitrary_send-0.5.1.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#12)\n", + "description": "Test.direct() (tests/arbitrary_send-0.5.1.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#12)\n", "elements": [ { "type": "function", @@ -192,7 +192,7 @@ "check": "arbitrary-send", "impact": "High", "confidence": "Medium", - "description": "Test.indirect (tests/arbitrary_send-0.5.1.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#20)\n", + "description": "Test.indirect() (tests/arbitrary_send-0.5.1.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#20)\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt index 3861f0b9b..cc2b1953f 100644 --- a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt +++ b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt @@ -1,8 +1,8 @@ INFO:Detectors: -Test.direct (tests/arbitrary_send-0.5.1.sol#11-13) sends eth to arbitrary user +Test.direct() (tests/arbitrary_send-0.5.1.sol#11-13) sends eth to arbitrary user Dangerous calls: - msg.sender.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#12) -Test.indirect (tests/arbitrary_send-0.5.1.sol#19-21) sends eth to arbitrary user +Test.indirect() (tests/arbitrary_send-0.5.1.sol#19-21) sends eth to arbitrary user Dangerous calls: - destination.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#20) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations diff --git a/tests/expected_json/arbitrary_send.arbitrary-send.json b/tests/expected_json/arbitrary_send.arbitrary-send.json index 30f75bec4..87223d6d8 100644 --- a/tests/expected_json/arbitrary_send.arbitrary-send.json +++ b/tests/expected_json/arbitrary_send.arbitrary-send.json @@ -7,7 +7,7 @@ "check": "arbitrary-send", "impact": "High", "confidence": "Medium", - "description": "Test.direct (tests/arbitrary_send.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send.sol#12)\n", + "description": "Test.direct() (tests/arbitrary_send.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send.sol#12)\n", "elements": [ { "type": "function", @@ -192,7 +192,7 @@ "check": "arbitrary-send", "impact": "High", "confidence": "Medium", - "description": "Test.indirect (tests/arbitrary_send.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send.sol#20)\n", + "description": "Test.indirect() (tests/arbitrary_send.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send.sol#20)\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/arbitrary_send.arbitrary-send.txt b/tests/expected_json/arbitrary_send.arbitrary-send.txt index 07fd98b5a..ee8440aa4 100644 --- a/tests/expected_json/arbitrary_send.arbitrary-send.txt +++ b/tests/expected_json/arbitrary_send.arbitrary-send.txt @@ -1,8 +1,8 @@ INFO:Detectors: -Test.direct (tests/arbitrary_send.sol#11-13) sends eth to arbitrary user +Test.direct() (tests/arbitrary_send.sol#11-13) sends eth to arbitrary user Dangerous calls: - msg.sender.send(address(this).balance) (tests/arbitrary_send.sol#12) -Test.indirect (tests/arbitrary_send.sol#19-21) sends eth to arbitrary user +Test.indirect() (tests/arbitrary_send.sol#19-21) sends eth to arbitrary user Dangerous calls: - destination.send(address(this).balance) (tests/arbitrary_send.sol#20) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations diff --git a/tests/expected_json/backdoor.suicidal.json b/tests/expected_json/backdoor.suicidal.json index b2614f59c..9d4a073df 100644 --- a/tests/expected_json/backdoor.suicidal.json +++ b/tests/expected_json/backdoor.suicidal.json @@ -7,7 +7,7 @@ "check": "suicidal", "impact": "High", "confidence": "High", - "description": "C.i_am_a_backdoor (tests/backdoor.sol#4-6) allows anyone to destruct the contract\n", + "description": "C.i_am_a_backdoor() (tests/backdoor.sol#4-6) allows anyone to destruct the contract\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/backdoor.suicidal.txt b/tests/expected_json/backdoor.suicidal.txt index 441cfb34d..eefe0e4bf 100644 --- a/tests/expected_json/backdoor.suicidal.txt +++ b/tests/expected_json/backdoor.suicidal.txt @@ -1,5 +1,5 @@ INFO:Detectors: -C.i_am_a_backdoor (tests/backdoor.sol#4-6) allows anyone to destruct the contract +C.i_am_a_backdoor() (tests/backdoor.sol#4-6) allows anyone to destruct the contract Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal INFO:Slither:/home/travis/build/crytic/slither/scripts/../tests/expected_json/backdoor.suicidal.json exists already, the overwrite is prevented INFO:Slither:tests/backdoor.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/constant-0.5.1.constant-function.json b/tests/expected_json/constant-0.5.1.constant-function.json index 51813e3e5..f88dd2fe4 100644 --- a/tests/expected_json/constant-0.5.1.constant-function.json +++ b/tests/expected_json/constant-0.5.1.constant-function.json @@ -7,7 +7,7 @@ "check": "constant-function", "impact": "Medium", "confidence": "Medium", - "description": "Constant.test_assembly_bug (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code\n", + "description": "Constant.test_assembly_bug() (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/constant-0.5.1.constant-function.txt b/tests/expected_json/constant-0.5.1.constant-function.txt index c3090ad40..2f308dd12 100644 --- a/tests/expected_json/constant-0.5.1.constant-function.txt +++ b/tests/expected_json/constant-0.5.1.constant-function.txt @@ -1,4 +1,4 @@ INFO:Detectors: -Constant.test_assembly_bug (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code +Constant.test_assembly_bug() (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state INFO:Slither:tests/constant-0.5.1.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/constant.constant-function.json b/tests/expected_json/constant.constant-function.json index db339ba60..298faef95 100644 --- a/tests/expected_json/constant.constant-function.json +++ b/tests/expected_json/constant.constant-function.json @@ -7,7 +7,7 @@ "check": "constant-function", "impact": "Medium", "confidence": "Medium", - "description": "Constant.test_view_bug (tests/constant.sol#5-7) is declared view but changes state variables:\n\t- Constant.a\n", + "description": "Constant.test_view_bug() (tests/constant.sol#5-7) is declared view but changes state variables:\n\t- Constant.a\n", "elements": [ { "type": "function", @@ -141,7 +141,7 @@ "check": "constant-function", "impact": "Medium", "confidence": "Medium", - "description": "Constant.test_constant_bug (tests/constant.sol#9-11) is declared view but changes state variables:\n\t- Constant.a\n", + "description": "Constant.test_constant_bug() (tests/constant.sol#9-11) is declared view but changes state variables:\n\t- Constant.a\n", "elements": [ { "type": "function", @@ -275,7 +275,7 @@ "check": "constant-function", "impact": "Medium", "confidence": "Medium", - "description": "Constant.test_assembly_bug (tests/constant.sol#22-24) is declared view but contains assembly code\n", + "description": "Constant.test_assembly_bug() (tests/constant.sol#22-24) is declared view but contains assembly code\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/constant.constant-function.txt b/tests/expected_json/constant.constant-function.txt index e0d191ca3..00eed4577 100644 --- a/tests/expected_json/constant.constant-function.txt +++ b/tests/expected_json/constant.constant-function.txt @@ -1,8 +1,8 @@ INFO:Detectors: -Constant.test_view_bug (tests/constant.sol#5-7) is declared view but changes state variables: +Constant.test_view_bug() (tests/constant.sol#5-7) is declared view but changes state variables: - Constant.a -Constant.test_constant_bug (tests/constant.sol#9-11) is declared view but changes state variables: +Constant.test_constant_bug() (tests/constant.sol#9-11) is declared view but changes state variables: - Constant.a -Constant.test_assembly_bug (tests/constant.sol#22-24) is declared view but contains assembly code +Constant.test_assembly_bug() (tests/constant.sol#22-24) is declared view but contains assembly code Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state INFO:Slither:tests/constant.sol analyzed (1 contracts), 3 result(s) found diff --git a/tests/expected_json/external_function.external-function.json b/tests/expected_json/external_function.external-function.json index 3c8369a91..c5f667494 100644 --- a/tests/expected_json/external_function.external-function.json +++ b/tests/expected_json/external_function.external-function.json @@ -7,7 +7,7 @@ "check": "external-function", "impact": "Informational", "confidence": "High", - "description": "ContractWithFunctionNotCalled.funcNotCalled3 (tests/external_function.sol#13-15) should be declared external\n", + "description": "ContractWithFunctionNotCalled.funcNotCalled3() (tests/external_function.sol#13-15) should be declared external\n", "elements": [ { "type": "function", @@ -72,7 +72,7 @@ "check": "external-function", "impact": "Informational", "confidence": "High", - "description": "ContractWithFunctionNotCalled.funcNotCalled2 (tests/external_function.sol#17-19) should be declared external\n", + "description": "ContractWithFunctionNotCalled.funcNotCalled2() (tests/external_function.sol#17-19) should be declared external\n", "elements": [ { "type": "function", @@ -137,7 +137,7 @@ "check": "external-function", "impact": "Informational", "confidence": "High", - "description": "ContractWithFunctionNotCalled.funcNotCalled (tests/external_function.sol#21-23) should be declared external\n", + "description": "ContractWithFunctionNotCalled.funcNotCalled() (tests/external_function.sol#21-23) should be declared external\n", "elements": [ { "type": "function", @@ -202,7 +202,7 @@ "check": "external-function", "impact": "Informational", "confidence": "High", - "description": "ContractWithFunctionNotCalled2.funcNotCalled (tests/external_function.sol#32-39) should be declared external\n", + "description": "ContractWithFunctionNotCalled2.funcNotCalled() (tests/external_function.sol#32-39) should be declared external\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/external_function.external-function.txt b/tests/expected_json/external_function.external-function.txt index 7a7fcfbd5..525880eda 100644 --- a/tests/expected_json/external_function.external-function.txt +++ b/tests/expected_json/external_function.external-function.txt @@ -1,7 +1,7 @@ INFO:Detectors: -ContractWithFunctionNotCalled.funcNotCalled3 (tests/external_function.sol#13-15) should be declared external -ContractWithFunctionNotCalled.funcNotCalled2 (tests/external_function.sol#17-19) should be declared external -ContractWithFunctionNotCalled.funcNotCalled (tests/external_function.sol#21-23) should be declared external -ContractWithFunctionNotCalled2.funcNotCalled (tests/external_function.sol#32-39) should be declared external +ContractWithFunctionNotCalled.funcNotCalled3() (tests/external_function.sol#13-15) should be declared external +ContractWithFunctionNotCalled.funcNotCalled2() (tests/external_function.sol#17-19) should be declared external +ContractWithFunctionNotCalled.funcNotCalled() (tests/external_function.sol#21-23) should be declared external +ContractWithFunctionNotCalled2.funcNotCalled() (tests/external_function.sol#32-39) should be declared external Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-as-external INFO:Slither:tests/external_function.sol analyzed (5 contracts), 4 result(s) found diff --git a/tests/expected_json/incorrect_equality.incorrect-equality.json b/tests/expected_json/incorrect_equality.incorrect-equality.json index 2c9053dc2..1337fbed5 100644 --- a/tests/expected_json/incorrect_equality.incorrect-equality.json +++ b/tests/expected_json/incorrect_equality.incorrect-equality.json @@ -7,7 +7,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "ERC20TestBalance.bad0 (tests/incorrect_equality.sol#21-23) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(address(this)) == 10)\n", + "description": "ERC20TestBalance.bad0(ERC20Function) (tests/incorrect_equality.sol#21-23) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(address(this)) == 10)\n", "elements": [ { "type": "node", @@ -148,7 +148,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "ERC20TestBalance.bad1 (tests/incorrect_equality.sol#25-27) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(msg.sender) == 10)\n", + "description": "ERC20TestBalance.bad1(ERC20Variable) (tests/incorrect_equality.sol#25-27) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(msg.sender) == 10)\n", "elements": [ { "type": "node", @@ -289,7 +289,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestContractBalance.bad0 (tests/incorrect_equality.sol#32-35) uses a dangerous strict equality:\n\t- require(bool)(address(address(this)).balance == 10000000000000000000)\n", + "description": "TestContractBalance.bad0() (tests/incorrect_equality.sol#32-35) uses a dangerous strict equality:\n\t- require(bool)(address(address(this)).balance == 10000000000000000000)\n", "elements": [ { "type": "node", @@ -530,7 +530,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestContractBalance.bad1 (tests/incorrect_equality.sol#37-40) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(address(this)).balance)\n", + "description": "TestContractBalance.bad1() (tests/incorrect_equality.sol#37-40) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(address(this)).balance)\n", "elements": [ { "type": "node", @@ -771,7 +771,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestContractBalance.bad2 (tests/incorrect_equality.sol#42-45) uses a dangerous strict equality:\n\t- require(bool)(address(this).balance == 10000000000000000000)\n", + "description": "TestContractBalance.bad2() (tests/incorrect_equality.sol#42-45) uses a dangerous strict equality:\n\t- require(bool)(address(this).balance == 10000000000000000000)\n", "elements": [ { "type": "node", @@ -1012,7 +1012,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestContractBalance.bad3 (tests/incorrect_equality.sol#47-50) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(this).balance)\n", + "description": "TestContractBalance.bad3() (tests/incorrect_equality.sol#47-50) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(this).balance)\n", "elements": [ { "type": "node", @@ -1253,7 +1253,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestContractBalance.bad4 (tests/incorrect_equality.sol#52-57) uses a dangerous strict equality:\n\t- balance == 10000000000000000000\n", + "description": "TestContractBalance.bad4() (tests/incorrect_equality.sol#52-57) uses a dangerous strict equality:\n\t- balance == 10000000000000000000\n", "elements": [ { "type": "node", @@ -1500,7 +1500,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestContractBalance.bad5 (tests/incorrect_equality.sol#59-64) uses a dangerous strict equality:\n\t- 10000000000000000000 == balance\n", + "description": "TestContractBalance.bad5() (tests/incorrect_equality.sol#59-64) uses a dangerous strict equality:\n\t- 10000000000000000000 == balance\n", "elements": [ { "type": "node", @@ -1747,7 +1747,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestContractBalance.bad6 (tests/incorrect_equality.sol#66-71) uses a dangerous strict equality:\n\t- balance == 10000000000000000000\n", + "description": "TestContractBalance.bad6() (tests/incorrect_equality.sol#66-71) uses a dangerous strict equality:\n\t- balance == 10000000000000000000\n", "elements": [ { "type": "node", @@ -1994,7 +1994,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestSolidityKeyword.bad0 (tests/incorrect_equality.sol#123-125) uses a dangerous strict equality:\n\t- require(bool)(now == 0)\n", + "description": "TestSolidityKeyword.bad0() (tests/incorrect_equality.sol#123-125) uses a dangerous strict equality:\n\t- require(bool)(now == 0)\n", "elements": [ { "type": "node", @@ -2171,7 +2171,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestSolidityKeyword.bad1 (tests/incorrect_equality.sol#127-129) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0)\n", + "description": "TestSolidityKeyword.bad1() (tests/incorrect_equality.sol#127-129) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0)\n", "elements": [ { "type": "node", @@ -2348,7 +2348,7 @@ "check": "incorrect-equality", "impact": "Medium", "confidence": "High", - "description": "TestSolidityKeyword.bad2 (tests/incorrect_equality.sol#131-133) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0)\n", + "description": "TestSolidityKeyword.bad2() (tests/incorrect_equality.sol#131-133) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/incorrect_equality.incorrect-equality.txt b/tests/expected_json/incorrect_equality.incorrect-equality.txt index 601f5494a..afe5a41c4 100644 --- a/tests/expected_json/incorrect_equality.incorrect-equality.txt +++ b/tests/expected_json/incorrect_equality.incorrect-equality.txt @@ -1,27 +1,27 @@ INFO:Detectors: -ERC20TestBalance.bad0 (tests/incorrect_equality.sol#21-23) uses a dangerous strict equality: +ERC20TestBalance.bad0(ERC20Function) (tests/incorrect_equality.sol#21-23) uses a dangerous strict equality: - require(bool)(erc.balanceOf(address(this)) == 10) -ERC20TestBalance.bad1 (tests/incorrect_equality.sol#25-27) uses a dangerous strict equality: +ERC20TestBalance.bad1(ERC20Variable) (tests/incorrect_equality.sol#25-27) uses a dangerous strict equality: - require(bool)(erc.balanceOf(msg.sender) == 10) -TestContractBalance.bad0 (tests/incorrect_equality.sol#32-35) uses a dangerous strict equality: +TestContractBalance.bad0() (tests/incorrect_equality.sol#32-35) uses a dangerous strict equality: - require(bool)(address(address(this)).balance == 10000000000000000000) -TestContractBalance.bad1 (tests/incorrect_equality.sol#37-40) uses a dangerous strict equality: +TestContractBalance.bad1() (tests/incorrect_equality.sol#37-40) uses a dangerous strict equality: - require(bool)(10000000000000000000 == address(address(this)).balance) -TestContractBalance.bad2 (tests/incorrect_equality.sol#42-45) uses a dangerous strict equality: +TestContractBalance.bad2() (tests/incorrect_equality.sol#42-45) uses a dangerous strict equality: - require(bool)(address(this).balance == 10000000000000000000) -TestContractBalance.bad3 (tests/incorrect_equality.sol#47-50) uses a dangerous strict equality: +TestContractBalance.bad3() (tests/incorrect_equality.sol#47-50) uses a dangerous strict equality: - require(bool)(10000000000000000000 == address(this).balance) -TestContractBalance.bad4 (tests/incorrect_equality.sol#52-57) uses a dangerous strict equality: +TestContractBalance.bad4() (tests/incorrect_equality.sol#52-57) uses a dangerous strict equality: - balance == 10000000000000000000 -TestContractBalance.bad5 (tests/incorrect_equality.sol#59-64) uses a dangerous strict equality: +TestContractBalance.bad5() (tests/incorrect_equality.sol#59-64) uses a dangerous strict equality: - 10000000000000000000 == balance -TestContractBalance.bad6 (tests/incorrect_equality.sol#66-71) uses a dangerous strict equality: +TestContractBalance.bad6() (tests/incorrect_equality.sol#66-71) uses a dangerous strict equality: - balance == 10000000000000000000 -TestSolidityKeyword.bad0 (tests/incorrect_equality.sol#123-125) uses a dangerous strict equality: +TestSolidityKeyword.bad0() (tests/incorrect_equality.sol#123-125) uses a dangerous strict equality: - require(bool)(now == 0) -TestSolidityKeyword.bad1 (tests/incorrect_equality.sol#127-129) uses a dangerous strict equality: +TestSolidityKeyword.bad1() (tests/incorrect_equality.sol#127-129) uses a dangerous strict equality: - require(bool)(block.number == 0) -TestSolidityKeyword.bad2 (tests/incorrect_equality.sol#131-133) uses a dangerous strict equality: +TestSolidityKeyword.bad2() (tests/incorrect_equality.sol#131-133) uses a dangerous strict equality: - require(bool)(block.number == 0) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities INFO:Slither:tests/incorrect_equality.sol analyzed (5 contracts), 12 result(s) found diff --git a/tests/expected_json/incorrect_erc20_interface.erc20-interface.json b/tests/expected_json/incorrect_erc20_interface.erc20-interface.json index 34f7ff786..e5b62fab1 100644 --- a/tests/expected_json/incorrect_erc20_interface.erc20-interface.json +++ b/tests/expected_json/incorrect_erc20_interface.erc20-interface.json @@ -7,7 +7,7 @@ "check": "erc20-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transfer (tests/incorrect_erc20_interface.sol#4)\n", + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transfer(address,uint256) (tests/incorrect_erc20_interface.sol#4)\n", "elements": [ { "type": "function", @@ -59,7 +59,7 @@ "check": "erc20-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: approve (tests/incorrect_erc20_interface.sol#5)\n", + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: approve(address,uint256) (tests/incorrect_erc20_interface.sol#5)\n", "elements": [ { "type": "function", @@ -111,7 +111,7 @@ "check": "erc20-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transferFrom (tests/incorrect_erc20_interface.sol#6)\n", + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc20_interface.sol#6)\n", "elements": [ { "type": "function", @@ -163,7 +163,7 @@ "check": "erc20-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: totalSupply (tests/incorrect_erc20_interface.sol#7)\n", + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: totalSupply() (tests/incorrect_erc20_interface.sol#7)\n", "elements": [ { "type": "function", @@ -215,7 +215,7 @@ "check": "erc20-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: balanceOf (tests/incorrect_erc20_interface.sol#8)\n", + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: balanceOf(address) (tests/incorrect_erc20_interface.sol#8)\n", "elements": [ { "type": "function", @@ -267,7 +267,7 @@ "check": "erc20-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: allowance (tests/incorrect_erc20_interface.sol#9)\n", + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: allowance(address,address) (tests/incorrect_erc20_interface.sol#9)\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt b/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt index 882880228..75b71be01 100644 --- a/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt +++ b/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt @@ -1,9 +1,9 @@ INFO:Detectors: -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transfer (tests/incorrect_erc20_interface.sol#4) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: approve (tests/incorrect_erc20_interface.sol#5) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transferFrom (tests/incorrect_erc20_interface.sol#6) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: totalSupply (tests/incorrect_erc20_interface.sol#7) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: balanceOf (tests/incorrect_erc20_interface.sol#8) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: allowance (tests/incorrect_erc20_interface.sol#9) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transfer(address,uint256) (tests/incorrect_erc20_interface.sol#4) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: approve(address,uint256) (tests/incorrect_erc20_interface.sol#5) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc20_interface.sol#6) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: totalSupply() (tests/incorrect_erc20_interface.sol#7) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: balanceOf(address) (tests/incorrect_erc20_interface.sol#8) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: allowance(address,address) (tests/incorrect_erc20_interface.sol#9) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface INFO:Slither:tests/incorrect_erc20_interface.sol analyzed (1 contracts), 6 result(s) found diff --git a/tests/expected_json/incorrect_erc721_interface.erc721-interface.json b/tests/expected_json/incorrect_erc721_interface.erc721-interface.json index 5eaab9f00..878900271 100644 --- a/tests/expected_json/incorrect_erc721_interface.erc721-interface.json +++ b/tests/expected_json/incorrect_erc721_interface.erc721-interface.json @@ -7,7 +7,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: supportsInterface (tests/incorrect_erc721_interface.sol#4)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: supportsInterface(bytes4) (tests/incorrect_erc721_interface.sol#4)\n", "elements": [ { "type": "function", @@ -54,7 +54,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: balanceOf (tests/incorrect_erc721_interface.sol#7)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: balanceOf(address) (tests/incorrect_erc721_interface.sol#7)\n", "elements": [ { "type": "function", @@ -109,7 +109,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: ownerOf (tests/incorrect_erc721_interface.sol#8)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: ownerOf(uint256) (tests/incorrect_erc721_interface.sol#8)\n", "elements": [ { "type": "function", @@ -164,7 +164,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom (tests/incorrect_erc721_interface.sol#9)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256,bytes) (tests/incorrect_erc721_interface.sol#9)\n", "elements": [ { "type": "function", @@ -219,7 +219,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom (tests/incorrect_erc721_interface.sol#10)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#10)\n", "elements": [ { "type": "function", @@ -274,7 +274,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: transferFrom (tests/incorrect_erc721_interface.sol#11)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#11)\n", "elements": [ { "type": "function", @@ -329,7 +329,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: approve (tests/incorrect_erc721_interface.sol#12)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: approve(address,uint256) (tests/incorrect_erc721_interface.sol#12)\n", "elements": [ { "type": "function", @@ -384,7 +384,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: setApprovalForAll (tests/incorrect_erc721_interface.sol#13)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: setApprovalForAll(address,bool) (tests/incorrect_erc721_interface.sol#13)\n", "elements": [ { "type": "function", @@ -439,7 +439,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: getApproved (tests/incorrect_erc721_interface.sol#14)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: getApproved(uint256) (tests/incorrect_erc721_interface.sol#14)\n", "elements": [ { "type": "function", @@ -494,7 +494,7 @@ "check": "erc721-interface", "impact": "Medium", "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: isApprovedForAll (tests/incorrect_erc721_interface.sol#15)\n", + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: isApprovedForAll(address,address) (tests/incorrect_erc721_interface.sol#15)\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt b/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt index f7c884a99..cfd388267 100644 --- a/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt +++ b/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt @@ -1,13 +1,13 @@ INFO:Detectors: -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: supportsInterface (tests/incorrect_erc721_interface.sol#4) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: balanceOf (tests/incorrect_erc721_interface.sol#7) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: ownerOf (tests/incorrect_erc721_interface.sol#8) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom (tests/incorrect_erc721_interface.sol#9) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom (tests/incorrect_erc721_interface.sol#10) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: transferFrom (tests/incorrect_erc721_interface.sol#11) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: approve (tests/incorrect_erc721_interface.sol#12) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: setApprovalForAll (tests/incorrect_erc721_interface.sol#13) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: getApproved (tests/incorrect_erc721_interface.sol#14) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: isApprovedForAll (tests/incorrect_erc721_interface.sol#15) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: supportsInterface(bytes4) (tests/incorrect_erc721_interface.sol#4) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: balanceOf(address) (tests/incorrect_erc721_interface.sol#7) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: ownerOf(uint256) (tests/incorrect_erc721_interface.sol#8) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256,bytes) (tests/incorrect_erc721_interface.sol#9) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#10) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#11) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: approve(address,uint256) (tests/incorrect_erc721_interface.sol#12) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: setApprovalForAll(address,bool) (tests/incorrect_erc721_interface.sol#13) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: getApproved(uint256) (tests/incorrect_erc721_interface.sol#14) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: isApprovedForAll(address,address) (tests/incorrect_erc721_interface.sol#15) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface INFO:Slither:tests/incorrect_erc721_interface.sol analyzed (2 contracts), 10 result(s) found diff --git a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json index d48921b4d..037b21636 100644 --- a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json +++ b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json @@ -7,7 +7,7 @@ "check": "assembly", "impact": "Informational", "confidence": "High", - "description": "GetCode.at uses assembly (tests/inline_assembly_contract-0.5.1.sol#6-20)\n\t- tests/inline_assembly_contract-0.5.1.sol#7-20\n", + "description": "GetCode.at(address) uses assembly (tests/inline_assembly_contract-0.5.1.sol#6-20)\n\t- tests/inline_assembly_contract-0.5.1.sol#7-20\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt index 40b941a00..f832cfe46 100644 --- a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt +++ b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt @@ -1,5 +1,5 @@ INFO:Detectors: -GetCode.at uses assembly (tests/inline_assembly_contract-0.5.1.sol#6-20) +GetCode.at(address) uses assembly (tests/inline_assembly_contract-0.5.1.sol#6-20) - tests/inline_assembly_contract-0.5.1.sol#7-20 Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage INFO:Slither:tests/inline_assembly_contract-0.5.1.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/inline_assembly_contract.assembly.json b/tests/expected_json/inline_assembly_contract.assembly.json index 4dda29a5b..d8d7ac358 100644 --- a/tests/expected_json/inline_assembly_contract.assembly.json +++ b/tests/expected_json/inline_assembly_contract.assembly.json @@ -7,7 +7,7 @@ "check": "assembly", "impact": "Informational", "confidence": "High", - "description": "GetCode.at uses assembly (tests/inline_assembly_contract.sol#6-20)\n\t- tests/inline_assembly_contract.sol#7-20\n", + "description": "GetCode.at(address) uses assembly (tests/inline_assembly_contract.sol#6-20)\n\t- tests/inline_assembly_contract.sol#7-20\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/inline_assembly_contract.assembly.txt b/tests/expected_json/inline_assembly_contract.assembly.txt index 197ec10b1..78c4fa50c 100644 --- a/tests/expected_json/inline_assembly_contract.assembly.txt +++ b/tests/expected_json/inline_assembly_contract.assembly.txt @@ -1,5 +1,5 @@ INFO:Detectors: -GetCode.at uses assembly (tests/inline_assembly_contract.sol#6-20) +GetCode.at(address) uses assembly (tests/inline_assembly_contract.sol#6-20) - tests/inline_assembly_contract.sol#7-20 Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage INFO:Slither:tests/inline_assembly_contract.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/inline_assembly_library-0.5.1.assembly.json b/tests/expected_json/inline_assembly_library-0.5.1.assembly.json index c75e719b1..90eaefbe0 100644 --- a/tests/expected_json/inline_assembly_library-0.5.1.assembly.json +++ b/tests/expected_json/inline_assembly_library-0.5.1.assembly.json @@ -7,7 +7,7 @@ "check": "assembly", "impact": "Informational", "confidence": "High", - "description": "VectorSum.sumAsm uses assembly (tests/inline_assembly_library-0.5.1.sol#16-22)\n\t- tests/inline_assembly_library-0.5.1.sol#18-21\n", + "description": "VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#16-22)\n\t- tests/inline_assembly_library-0.5.1.sol#18-21\n", "elements": [ { "type": "function", @@ -209,7 +209,7 @@ "check": "assembly", "impact": "Informational", "confidence": "High", - "description": "VectorSum.sumPureAsm uses assembly (tests/inline_assembly_library-0.5.1.sol#25-47)\n\t- tests/inline_assembly_library-0.5.1.sol#26-47\n", + "description": "VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#25-47)\n\t- tests/inline_assembly_library-0.5.1.sol#26-47\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt b/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt index ca8bb59ea..5624ad2cf 100644 --- a/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt +++ b/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt @@ -1,7 +1,7 @@ INFO:Detectors: -VectorSum.sumAsm uses assembly (tests/inline_assembly_library-0.5.1.sol#16-22) +VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#16-22) - tests/inline_assembly_library-0.5.1.sol#18-21 -VectorSum.sumPureAsm uses assembly (tests/inline_assembly_library-0.5.1.sol#25-47) +VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#25-47) - tests/inline_assembly_library-0.5.1.sol#26-47 Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage INFO:Slither:tests/inline_assembly_library-0.5.1.sol analyzed (1 contracts), 2 result(s) found diff --git a/tests/expected_json/inline_assembly_library.assembly.json b/tests/expected_json/inline_assembly_library.assembly.json index 04c388ea3..955f9ccf0 100644 --- a/tests/expected_json/inline_assembly_library.assembly.json +++ b/tests/expected_json/inline_assembly_library.assembly.json @@ -7,7 +7,7 @@ "check": "assembly", "impact": "Informational", "confidence": "High", - "description": "VectorSum.sumAsm uses assembly (tests/inline_assembly_library.sol#16-22)\n\t- tests/inline_assembly_library.sol#18-21\n", + "description": "VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#16-22)\n\t- tests/inline_assembly_library.sol#18-21\n", "elements": [ { "type": "function", @@ -209,7 +209,7 @@ "check": "assembly", "impact": "Informational", "confidence": "High", - "description": "VectorSum.sumPureAsm uses assembly (tests/inline_assembly_library.sol#25-47)\n\t- tests/inline_assembly_library.sol#26-47\n", + "description": "VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#25-47)\n\t- tests/inline_assembly_library.sol#26-47\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/inline_assembly_library.assembly.txt b/tests/expected_json/inline_assembly_library.assembly.txt index f8768203e..8bc566c04 100644 --- a/tests/expected_json/inline_assembly_library.assembly.txt +++ b/tests/expected_json/inline_assembly_library.assembly.txt @@ -1,7 +1,7 @@ INFO:Detectors: -VectorSum.sumAsm uses assembly (tests/inline_assembly_library.sol#16-22) +VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#16-22) - tests/inline_assembly_library.sol#18-21 -VectorSum.sumPureAsm uses assembly (tests/inline_assembly_library.sol#25-47) +VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#25-47) - tests/inline_assembly_library.sol#26-47 Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage INFO:Slither:tests/inline_assembly_library.sol analyzed (1 contracts), 2 result(s) found diff --git a/tests/expected_json/low_level_calls.low-level-calls.json b/tests/expected_json/low_level_calls.low-level-calls.json index 1676df916..529a522f8 100644 --- a/tests/expected_json/low_level_calls.low-level-calls.json +++ b/tests/expected_json/low_level_calls.low-level-calls.json @@ -7,7 +7,7 @@ "check": "low-level-calls", "impact": "Informational", "confidence": "High", - "description": "Low level call in Sender.send (tests/low_level_calls.sol#5-7):\n\t-_receiver.call.value(msg.value).gas(7777)() tests/low_level_calls.sol#6\n", + "description": "Low level call in Sender.send(address) (tests/low_level_calls.sol#5-7):\n\t-_receiver.call.value(msg.value).gas(7777)() tests/low_level_calls.sol#6\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/low_level_calls.low-level-calls.txt b/tests/expected_json/low_level_calls.low-level-calls.txt index d80302cdc..db7034d4a 100644 --- a/tests/expected_json/low_level_calls.low-level-calls.txt +++ b/tests/expected_json/low_level_calls.low-level-calls.txt @@ -1,5 +1,5 @@ INFO:Detectors: -Low level call in Sender.send (tests/low_level_calls.sol#5-7): +Low level call in Sender.send(address) (tests/low_level_calls.sol#5-7): -_receiver.call.value(msg.value).gas(7777)() tests/low_level_calls.sol#6 Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls INFO:Slither:tests/low_level_calls.sol analyzed (2 contracts), 1 result(s) found diff --git a/tests/expected_json/multiple_calls_in_loop.calls-loop.json b/tests/expected_json/multiple_calls_in_loop.calls-loop.json index 26875d7a5..93a904fa3 100644 --- a/tests/expected_json/multiple_calls_in_loop.calls-loop.json +++ b/tests/expected_json/multiple_calls_in_loop.calls-loop.json @@ -7,7 +7,7 @@ "check": "calls-loop", "impact": "Low", "confidence": "Medium", - "description": "CallInLoop.bad has external calls inside a loop: \"destinations[i].transfer(i)\" (tests/multiple_calls_in_loop.sol#11)\n", + "description": "CallInLoop.bad() has external calls inside a loop: \"destinations[i].transfer(i)\" (tests/multiple_calls_in_loop.sol#11)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/multiple_calls_in_loop.calls-loop.txt b/tests/expected_json/multiple_calls_in_loop.calls-loop.txt index c32b154f1..7803df6de 100644 --- a/tests/expected_json/multiple_calls_in_loop.calls-loop.txt +++ b/tests/expected_json/multiple_calls_in_loop.calls-loop.txt @@ -1,4 +1,4 @@ INFO:Detectors: -CallInLoop.bad has external calls inside a loop: "destinations[i].transfer(i)" (tests/multiple_calls_in_loop.sol#11) +CallInLoop.bad() has external calls inside a loop: "destinations[i].transfer(i)" (tests/multiple_calls_in_loop.sol#11) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation/_edit#calls-inside-a-loop INFO:Slither:tests/multiple_calls_in_loop.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/naming_convention.naming-convention.json b/tests/expected_json/naming_convention.naming-convention.json index 18fdb44d4..bbc38da9d 100644 --- a/tests/expected_json/naming_convention.naming-convention.json +++ b/tests/expected_json/naming_convention.naming-convention.json @@ -176,7 +176,7 @@ "check": "naming-convention", "impact": "Informational", "confidence": "High", - "description": "Event 'naming.event_' (tests/naming_convention.sol#23) is not in CapWords\n", + "description": "Event 'namingevent_(uint256)' (tests/naming_convention.sol#23) is not in CapWords\n", "elements": [ { "type": "event", @@ -270,7 +270,7 @@ "check": "naming-convention", "impact": "Informational", "confidence": "High", - "description": "Function 'naming.GetOne' (tests/naming_convention.sol#30-33) is not in mixedCase\n", + "description": "Function 'naming.GetOne()' (tests/naming_convention.sol#30-33) is not in mixedCase\n", "elements": [ { "type": "function", @@ -367,7 +367,7 @@ "check": "naming-convention", "impact": "Informational", "confidence": "High", - "description": "Parameter 'Number2' of naming.setInt (tests/naming_convention.sol#35) is not in mixedCase\n", + "description": "Parameter 'Number2' of Number2 (tests/naming_convention.sol#35) is not in mixedCase\n", "elements": [ { "type": "variable", @@ -762,7 +762,7 @@ "check": "naming-convention", "impact": "Informational", "confidence": "High", - "description": "Modifier 'naming.CantDo' (tests/naming_convention.sol#41-43) is not in mixedCase\n", + "description": "Modifier 'naming.CantDo()' (tests/naming_convention.sol#41-43) is not in mixedCase\n", "elements": [ { "type": "function", @@ -858,7 +858,7 @@ "check": "naming-convention", "impact": "Informational", "confidence": "High", - "description": "Parameter '_used' of T.test (tests/naming_convention.sol#59) is not in mixedCase\n", + "description": "Parameter '_used' of _used (tests/naming_convention.sol#59) is not in mixedCase\n", "elements": [ { "type": "variable", diff --git a/tests/expected_json/naming_convention.naming-convention.txt b/tests/expected_json/naming_convention.naming-convention.txt index ae34a6944..500b50836 100644 --- a/tests/expected_json/naming_convention.naming-convention.txt +++ b/tests/expected_json/naming_convention.naming-convention.txt @@ -1,14 +1,14 @@ INFO:Detectors: Contract 'naming' (tests/naming_convention.sol#3-48) is not in CapWords Struct 'naming.test' (tests/naming_convention.sol#14-16) is not in CapWords -Event 'naming.event_' (tests/naming_convention.sol#23) is not in CapWords -Function 'naming.GetOne' (tests/naming_convention.sol#30-33) is not in mixedCase -Parameter 'Number2' of naming.setInt (tests/naming_convention.sol#35) is not in mixedCase +Event 'namingevent_(uint256)' (tests/naming_convention.sol#23) is not in CapWords +Function 'naming.GetOne()' (tests/naming_convention.sol#30-33) is not in mixedCase +Parameter 'Number2' of Number2 (tests/naming_convention.sol#35) is not in mixedCase Constant 'naming.MY_other_CONSTANT' (tests/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES Variable 'naming.Var_One' (tests/naming_convention.sol#11) is not in mixedCase Enum 'naming.numbers' (tests/naming_convention.sol#6) is not in CapWords -Modifier 'naming.CantDo' (tests/naming_convention.sol#41-43) is not in mixedCase -Parameter '_used' of T.test (tests/naming_convention.sol#59) is not in mixedCase +Modifier 'naming.CantDo()' (tests/naming_convention.sol#41-43) is not in mixedCase +Parameter '_used' of _used (tests/naming_convention.sol#59) is not in mixedCase Variable 'T._myPublicVar' (tests/naming_convention.sol#56) is not in mixedCase Variable 'T.l' (tests/naming_convention.sol#67) used l, O, I, which should not be used Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions diff --git a/tests/expected_json/old_solc.sol.json.solc-version.txt b/tests/expected_json/old_solc.sol.json.solc-version.txt index 547cbd3f2..119e34692 100644 --- a/tests/expected_json/old_solc.sol.json.solc-version.txt +++ b/tests/expected_json/old_solc.sol.json.solc-version.txt @@ -1,5 +1,5 @@ INFO:Detectors: Pragma version "0.4.21" allows old versions (None) -Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-version-of-solidity +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity INFO:Slither:/home/travis/build/crytic/slither/scripts/../tests/expected_json/old_solc.sol.json.solc-version.json exists already, the overwrite is prevented INFO:Slither:tests/old_solc.sol.json analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json index df690d7c7..02e406d89 100644 --- a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json +++ b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json @@ -7,7 +7,7 @@ "check": "reentrancy-eth", "impact": "High", "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance (tests/reentrancy-0.5.1.sol#14-22):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(userBalance[msg.sender])() (tests/reentrancy-0.5.1.sol#17)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy-0.5.1.sol#21)\n", + "description": "Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy-0.5.1.sol#14-22):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(userBalance[msg.sender])() (tests/reentrancy-0.5.1.sol#17)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy-0.5.1.sol#21)\n", "elements": [ { "type": "function", @@ -348,7 +348,7 @@ "check": "reentrancy-eth", "impact": "High", "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance_fixed_3 (tests/reentrancy-0.5.1.sol#44-53):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(amount)() (tests/reentrancy-0.5.1.sol#49)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy-0.5.1.sol#51)\n", + "description": "Reentrancy in Reentrancy.withdrawBalance_fixed_3() (tests/reentrancy-0.5.1.sol#44-53):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(amount)() (tests/reentrancy-0.5.1.sol#49)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy-0.5.1.sol#51)\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt index 465e75502..ebf2a8c52 100644 --- a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt +++ b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt @@ -1,10 +1,10 @@ INFO:Detectors: -Reentrancy in Reentrancy.withdrawBalance (tests/reentrancy-0.5.1.sol#14-22): +Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy-0.5.1.sol#14-22): External calls: - (ret,mem) = msg.sender.call.value(userBalance[msg.sender])() (tests/reentrancy-0.5.1.sol#17) State variables written after the call(s): - userBalance (tests/reentrancy-0.5.1.sol#21) -Reentrancy in Reentrancy.withdrawBalance_fixed_3 (tests/reentrancy-0.5.1.sol#44-53): +Reentrancy in Reentrancy.withdrawBalance_fixed_3() (tests/reentrancy-0.5.1.sol#44-53): External calls: - (ret,mem) = msg.sender.call.value(amount)() (tests/reentrancy-0.5.1.sol#49) State variables written after the call(s): diff --git a/tests/expected_json/reentrancy.reentrancy-eth.json b/tests/expected_json/reentrancy.reentrancy-eth.json index 4ffb63851..01a58ed4f 100644 --- a/tests/expected_json/reentrancy.reentrancy-eth.json +++ b/tests/expected_json/reentrancy.reentrancy-eth.json @@ -7,7 +7,7 @@ "check": "reentrancy-eth", "impact": "High", "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance (tests/reentrancy.sol#14-21):\n\tExternal calls:\n\t- ! (msg.sender.call.value(userBalance[msg.sender])()) (tests/reentrancy.sol#17-19)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy.sol#20)\n", + "description": "Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy.sol#14-21):\n\tExternal calls:\n\t- ! (msg.sender.call.value(userBalance[msg.sender])()) (tests/reentrancy.sol#17-19)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy.sol#20)\n", "elements": [ { "type": "function", @@ -401,7 +401,7 @@ "check": "reentrancy-eth", "impact": "High", "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance_nested (tests/reentrancy.sol#64-70):\n\tExternal calls:\n\t- msg.sender.call.value(amount / 2)() (tests/reentrancy.sol#67)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy.sol#68)\n", + "description": "Reentrancy in Reentrancy.withdrawBalance_nested() (tests/reentrancy.sol#64-70):\n\tExternal calls:\n\t- msg.sender.call.value(amount / 2)() (tests/reentrancy.sol#67)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy.sol#68)\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/reentrancy.reentrancy-eth.txt b/tests/expected_json/reentrancy.reentrancy-eth.txt index b5534660e..243541a7c 100644 --- a/tests/expected_json/reentrancy.reentrancy-eth.txt +++ b/tests/expected_json/reentrancy.reentrancy-eth.txt @@ -1,10 +1,10 @@ INFO:Detectors: -Reentrancy in Reentrancy.withdrawBalance (tests/reentrancy.sol#14-21): +Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy.sol#14-21): External calls: - ! (msg.sender.call.value(userBalance[msg.sender])()) (tests/reentrancy.sol#17-19) State variables written after the call(s): - userBalance (tests/reentrancy.sol#20) -Reentrancy in Reentrancy.withdrawBalance_nested (tests/reentrancy.sol#64-70): +Reentrancy in Reentrancy.withdrawBalance_nested() (tests/reentrancy.sol#64-70): External calls: - msg.sender.call.value(amount / 2)() (tests/reentrancy.sol#67) State variables written after the call(s): diff --git a/tests/expected_json/solc_version_incorrect.solc-version.txt b/tests/expected_json/solc_version_incorrect.solc-version.txt index be0f7a443..60a0c9707 100644 --- a/tests/expected_json/solc_version_incorrect.solc-version.txt +++ b/tests/expected_json/solc_version_incorrect.solc-version.txt @@ -1,5 +1,5 @@ INFO:Detectors: Pragma version "^0.4.23" allows old versions (tests/solc_version_incorrect.sol#2) Pragma version ">=0.4.0<0.6.0" allows old versions (tests/solc_version_incorrect.sol#3) -Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-version-of-solidity +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity INFO:Slither:tests/solc_version_incorrect.sol analyzed (1 contracts), 2 result(s) found diff --git a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt index 80b3f5dbc..6673c1a56 100644 --- a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt +++ b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt @@ -1,5 +1,5 @@ INFO:Detectors: Pragma version "^0.5.5" is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html) (None) Pragma version "0.5.7" necessitates versions too recent to be trusted. Consider deploying with 0.5.3 (None) -Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-version-of-solidity +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity INFO:Slither:tests/solc_version_incorrect_05.ast.json analyzed (1 contracts), 2 result(s) found diff --git a/tests/expected_json/timestamp.timestamp.json b/tests/expected_json/timestamp.timestamp.json index d60bd3692..dc2adae7c 100644 --- a/tests/expected_json/timestamp.timestamp.json +++ b/tests/expected_json/timestamp.timestamp.json @@ -7,7 +7,7 @@ "check": "timestamp", "impact": "Low", "confidence": "Medium", - "description": "Timestamp.bad0 (tests/timestamp.sol#4-6) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(block.timestamp == 0) (tests/timestamp.sol#5)\n", + "description": "Timestamp.bad0() (tests/timestamp.sol#4-6) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(block.timestamp == 0) (tests/timestamp.sol#5)\n", "elements": [ { "type": "function", @@ -150,7 +150,7 @@ "check": "timestamp", "impact": "Low", "confidence": "Medium", - "description": "Timestamp.bad1 (tests/timestamp.sol#8-11) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(time == 0) (tests/timestamp.sol#10)\n", + "description": "Timestamp.bad1() (tests/timestamp.sol#8-11) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(time == 0) (tests/timestamp.sol#10)\n", "elements": [ { "type": "function", @@ -295,7 +295,7 @@ "check": "timestamp", "impact": "Low", "confidence": "Medium", - "description": "Timestamp.bad2 (tests/timestamp.sol#13-15) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- block.timestamp > 0 (tests/timestamp.sol#14)\n", + "description": "Timestamp.bad2() (tests/timestamp.sol#13-15) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- block.timestamp > 0 (tests/timestamp.sol#14)\n", "elements": [ { "type": "function", diff --git a/tests/expected_json/timestamp.timestamp.txt b/tests/expected_json/timestamp.timestamp.txt index 4c6c54479..ef64d694e 100644 --- a/tests/expected_json/timestamp.timestamp.txt +++ b/tests/expected_json/timestamp.timestamp.txt @@ -1,11 +1,11 @@ INFO:Detectors: -Timestamp.bad0 (tests/timestamp.sol#4-6) uses timestamp for comparisons +Timestamp.bad0() (tests/timestamp.sol#4-6) uses timestamp for comparisons Dangerous comparisons: - require(bool)(block.timestamp == 0) (tests/timestamp.sol#5) -Timestamp.bad1 (tests/timestamp.sol#8-11) uses timestamp for comparisons +Timestamp.bad1() (tests/timestamp.sol#8-11) uses timestamp for comparisons Dangerous comparisons: - require(bool)(time == 0) (tests/timestamp.sol#10) -Timestamp.bad2 (tests/timestamp.sol#13-15) uses timestamp for comparisons +Timestamp.bad2() (tests/timestamp.sol#13-15) uses timestamp for comparisons Dangerous comparisons: - block.timestamp > 0 (tests/timestamp.sol#14) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp diff --git a/tests/expected_json/tx_origin-0.5.1.tx-origin.json b/tests/expected_json/tx_origin-0.5.1.tx-origin.json index 579212f4e..b68f18578 100644 --- a/tests/expected_json/tx_origin-0.5.1.tx-origin.json +++ b/tests/expected_json/tx_origin-0.5.1.tx-origin.json @@ -7,7 +7,7 @@ "check": "tx-origin", "impact": "Medium", "confidence": "Medium", - "description": "TxOrigin.bug0 uses tx.origin for authorization: \"require(bool)(tx.origin == owner)\" (tests/tx_origin-0.5.1.sol#10)\n", + "description": "TxOrigin.bug0() uses tx.origin for authorization: \"require(bool)(tx.origin == owner)\" (tests/tx_origin-0.5.1.sol#10)\n", "elements": [ { "type": "node", @@ -96,7 +96,7 @@ "check": "tx-origin", "impact": "Medium", "confidence": "Medium", - "description": "TxOrigin.bug2 uses tx.origin for authorization: \"tx.origin != owner\" (tests/tx_origin-0.5.1.sol#14-16)\n", + "description": "TxOrigin.bug2() uses tx.origin for authorization: \"tx.origin != owner\" (tests/tx_origin-0.5.1.sol#14-16)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/tx_origin-0.5.1.tx-origin.txt b/tests/expected_json/tx_origin-0.5.1.tx-origin.txt index e39dcdd09..5a12a42f8 100644 --- a/tests/expected_json/tx_origin-0.5.1.tx-origin.txt +++ b/tests/expected_json/tx_origin-0.5.1.tx-origin.txt @@ -1,5 +1,5 @@ INFO:Detectors: -TxOrigin.bug0 uses tx.origin for authorization: "require(bool)(tx.origin == owner)" (tests/tx_origin-0.5.1.sol#10) -TxOrigin.bug2 uses tx.origin for authorization: "tx.origin != owner" (tests/tx_origin-0.5.1.sol#14-16) +TxOrigin.bug0() uses tx.origin for authorization: "require(bool)(tx.origin == owner)" (tests/tx_origin-0.5.1.sol#10) +TxOrigin.bug2() uses tx.origin for authorization: "tx.origin != owner" (tests/tx_origin-0.5.1.sol#14-16) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin INFO:Slither:tests/tx_origin-0.5.1.sol analyzed (1 contracts), 2 result(s) found diff --git a/tests/expected_json/tx_origin.tx-origin.json b/tests/expected_json/tx_origin.tx-origin.json index 6a30badb3..192d82792 100644 --- a/tests/expected_json/tx_origin.tx-origin.json +++ b/tests/expected_json/tx_origin.tx-origin.json @@ -7,7 +7,7 @@ "check": "tx-origin", "impact": "Medium", "confidence": "Medium", - "description": "TxOrigin.bug0 uses tx.origin for authorization: \"require(bool)(tx.origin == owner)\" (tests/tx_origin.sol#10)\n", + "description": "TxOrigin.bug0() uses tx.origin for authorization: \"require(bool)(tx.origin == owner)\" (tests/tx_origin.sol#10)\n", "elements": [ { "type": "node", @@ -96,7 +96,7 @@ "check": "tx-origin", "impact": "Medium", "confidence": "Medium", - "description": "TxOrigin.bug2 uses tx.origin for authorization: \"tx.origin != owner\" (tests/tx_origin.sol#14-16)\n", + "description": "TxOrigin.bug2() uses tx.origin for authorization: \"tx.origin != owner\" (tests/tx_origin.sol#14-16)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/tx_origin.tx-origin.txt b/tests/expected_json/tx_origin.tx-origin.txt index a1335bf99..62a9c9f85 100644 --- a/tests/expected_json/tx_origin.tx-origin.txt +++ b/tests/expected_json/tx_origin.tx-origin.txt @@ -1,5 +1,5 @@ INFO:Detectors: -TxOrigin.bug0 uses tx.origin for authorization: "require(bool)(tx.origin == owner)" (tests/tx_origin.sol#10) -TxOrigin.bug2 uses tx.origin for authorization: "tx.origin != owner" (tests/tx_origin.sol#14-16) +TxOrigin.bug0() uses tx.origin for authorization: "require(bool)(tx.origin == owner)" (tests/tx_origin.sol#10) +TxOrigin.bug2() uses tx.origin for authorization: "tx.origin != owner" (tests/tx_origin.sol#14-16) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin INFO:Slither:tests/tx_origin.sol analyzed (1 contracts), 2 result(s) found diff --git a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json index 463896045..79ba492aa 100644 --- a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json +++ b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json @@ -7,7 +7,7 @@ "check": "unchecked-lowlevel", "impact": "Medium", "confidence": "Medium", - "description": "MyConc.bad (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by low-level calls \"dst.call.value(msg.value)()\" (tests/unchecked_lowlevel-0.5.1.sol#3)\n", + "description": "MyConc.bad(address) (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by low-level calls \"dst.call.value(msg.value)()\" (tests/unchecked_lowlevel-0.5.1.sol#3)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt index 52ec766ee..42dbda5b4 100644 --- a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt +++ b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt @@ -1,4 +1,4 @@ INFO:Detectors: -MyConc.bad (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by low-level calls "dst.call.value(msg.value)()" (tests/unchecked_lowlevel-0.5.1.sol#3) -Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level +MyConc.bad(address) (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by low-level calls "dst.call.value(msg.value)()" (tests/unchecked_lowlevel-0.5.1.sol#3) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls INFO:Slither:tests/unchecked_lowlevel-0.5.1.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json index c6a339f92..96abc874d 100644 --- a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json +++ b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json @@ -7,7 +7,7 @@ "check": "unchecked-lowlevel", "impact": "Medium", "confidence": "Medium", - "description": "MyConc.bad (tests/unchecked_lowlevel.sol#2-4) ignores return value by low-level calls \"dst.call.value(msg.value)()\" (tests/unchecked_lowlevel.sol#3)\n", + "description": "MyConc.bad(address) (tests/unchecked_lowlevel.sol#2-4) ignores return value by low-level calls \"dst.call.value(msg.value)()\" (tests/unchecked_lowlevel.sol#3)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt index b01b56d91..18ab55207 100644 --- a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt +++ b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt @@ -1,4 +1,4 @@ INFO:Detectors: -MyConc.bad (tests/unchecked_lowlevel.sol#2-4) ignores return value by low-level calls "dst.call.value(msg.value)()" (tests/unchecked_lowlevel.sol#3) -Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level +MyConc.bad(address) (tests/unchecked_lowlevel.sol#2-4) ignores return value by low-level calls "dst.call.value(msg.value)()" (tests/unchecked_lowlevel.sol#3) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls INFO:Slither:tests/unchecked_lowlevel.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json index bf4bc8184..b679a4360 100644 --- a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json +++ b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json @@ -7,7 +7,7 @@ "check": "unchecked-send", "impact": "Medium", "confidence": "Medium", - "description": "MyConc.bad (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by send calls \"dst.send(msg.value)\" (tests/unchecked_send-0.5.1.sol#3)\n", + "description": "MyConc.bad(address) (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by send calls \"dst.send(msg.value)\" (tests/unchecked_send-0.5.1.sol#3)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt index 9f98626c3..9feafa034 100644 --- a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt +++ b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt @@ -1,4 +1,4 @@ INFO:Detectors: -MyConc.bad (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by send calls "dst.send(msg.value)" (tests/unchecked_send-0.5.1.sol#3) +MyConc.bad(address) (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by send calls "dst.send(msg.value)" (tests/unchecked_send-0.5.1.sol#3) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send INFO:Slither:tests/unchecked_send-0.5.1.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/uninitialized_local_variable.uninitialized-local.json b/tests/expected_json/uninitialized_local_variable.uninitialized-local.json index 4b403fddc..8eca553d8 100644 --- a/tests/expected_json/uninitialized_local_variable.uninitialized-local.json +++ b/tests/expected_json/uninitialized_local_variable.uninitialized-local.json @@ -7,7 +7,7 @@ "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium", - "description": "uint_not_init in Uninitialized.func (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed\n", + "description": "uint_not_init in Uninitialized.func() (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed\n", "elements": [ { "type": "variable", diff --git a/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt b/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt index f4ff963e3..6a013ffd9 100644 --- a/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt +++ b/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt @@ -1,4 +1,4 @@ INFO:Detectors: -uint_not_init in Uninitialized.func (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed +uint_not_init in Uninitialized.func() (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables INFO:Slither:tests/uninitialized_local_variable.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json index 81128da24..27a99fd31 100644 --- a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json +++ b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json @@ -7,7 +7,7 @@ "check": "uninitialized-storage", "impact": "High", "confidence": "High", - "description": "st_bug in Uninitialized.func (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed\n", + "description": "st_bug in Uninitialized.func() (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed\n", "elements": [ { "type": "variable", diff --git a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt index 29bb6e6b2..486ff5ec1 100644 --- a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt +++ b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt @@ -1,4 +1,4 @@ INFO:Detectors: -st_bug in Uninitialized.func (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed +st_bug in Uninitialized.func() (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables INFO:Slither:tests/uninitialized_storage_pointer.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/unused_return.unused-return.json b/tests/expected_json/unused_return.unused-return.json index ad8f40b12..727ee6020 100644 --- a/tests/expected_json/unused_return.unused-return.json +++ b/tests/expected_json/unused_return.unused-return.json @@ -7,7 +7,7 @@ "check": "unused-return", "impact": "Medium", "confidence": "Medium", - "description": "User.test (tests/unused_return.sol#17-29) ignores return value by external calls \"t.f()\" (tests/unused_return.sol#18)\n", + "description": "User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls \"t.f()\" (tests/unused_return.sol#18)\n", "elements": [ { "type": "node", @@ -166,7 +166,7 @@ "check": "unused-return", "impact": "Medium", "confidence": "Medium", - "description": "User.test (tests/unused_return.sol#17-29) ignores return value by external calls \"a.add(0)\" (tests/unused_return.sol#22)\n", + "description": "User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls \"a.add(0)\" (tests/unused_return.sol#22)\n", "elements": [ { "type": "node", diff --git a/tests/expected_json/unused_return.unused-return.txt b/tests/expected_json/unused_return.unused-return.txt index ff69c40a5..cae24dcf1 100644 --- a/tests/expected_json/unused_return.unused-return.txt +++ b/tests/expected_json/unused_return.unused-return.txt @@ -1,5 +1,5 @@ INFO:Detectors: -User.test (tests/unused_return.sol#17-29) ignores return value by external calls "t.f()" (tests/unused_return.sol#18) -User.test (tests/unused_return.sol#17-29) ignores return value by external calls "a.add(0)" (tests/unused_return.sol#22) +User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls "t.f()" (tests/unused_return.sol#18) +User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls "a.add(0)" (tests/unused_return.sol#22) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return INFO:Slither:tests/unused_return.sol analyzed (3 contracts), 2 result(s) found diff --git a/tests/uninitialized_local_variable.sol b/tests/uninitialized_local_variable.sol new file mode 100644 index 000000000..d28eef957 --- /dev/null +++ b/tests/uninitialized_local_variable.sol @@ -0,0 +1,9 @@ +contract Uninitialized{ + + function func() external returns(uint){ + uint uint_not_init; + uint uint_init = 1; + return uint_not_init + uint_init; + } + +} diff --git a/utils/possible_paths/__main__.py b/utils/possible_paths/__main__.py index 7023efc3c..70aea8003 100644 --- a/utils/possible_paths/__main__.py +++ b/utils/possible_paths/__main__.py @@ -48,7 +48,7 @@ def main(): # Print out all target functions. print(f"Target functions:") for target in targets: - print(f"- {target.contract.name}.{target.full_name}") + print(f"- {target.contract_declarer.name}.{target.full_name}") print("\n") # Obtain all paths which reach the target functions. @@ -57,12 +57,12 @@ def main(): # Print out all function names which can reach the targets. print(f"The following functions reach the specified targets:") - for function_desc in sorted([f"{f.contract.name}.{f.full_name}" for f in reaching_functions]): + for function_desc in sorted([f"{f.canonical_name}" for f in reaching_functions]): print(f"- {function_desc}") print("\n") # Format all function paths. - reaching_paths_str = [' -> '.join([f"{f.contract.name}.{f.full_name}" for f in reaching_path]) for reaching_path in reaching_paths] + reaching_paths_str = [' -> '.join([f"{f.canonical_name}" for f in reaching_path]) for reaching_path in reaching_paths] # Print a sorted list of all function paths which can reach the targets. print(f"The following paths reach the specified targets:") diff --git a/utils/possible_paths/possible_paths.py b/utils/possible_paths/possible_paths.py index 0d9976e08..e638b00ad 100644 --- a/utils/possible_paths/possible_paths.py +++ b/utils/possible_paths/possible_paths.py @@ -67,7 +67,7 @@ def all_function_definitions(function): :return: Returns a list composed of the provided function definition and any base definitions. """ return [function] + [f for c in function.contract.inheritance - for f in c.functions_and_modifiers_not_inherited + for f in c.functions_and_modifiers_declared if f.full_name == function.full_name] @@ -84,7 +84,7 @@ def __find_target_paths(slither, target_function, current_path=[]): # Look through all functions for contract in slither.contracts: - for function in contract.functions_and_modifiers_not_inherited: + for function in contract.functions_and_modifiers_declared: # If the function is already in our path, skip it. if function in current_path: diff --git a/utils/similarity/encode.py b/utils/similarity/encode.py index 3ea47ca7c..f20d316a8 100644 --- a/utils/similarity/encode.py +++ b/utils/similarity/encode.py @@ -193,7 +193,7 @@ def encode_contract(cfilename, **kwargs): for contract in slither.contracts: # Iterate over all the functions - for function in contract.functions_not_inherited: + for function in contract.functions_declared: if function.nodes == []: continue diff --git a/utils/upgradeability/check_initialization.py b/utils/upgradeability/check_initialization.py index ac9d29d47..22885ed31 100644 --- a/utils/upgradeability/check_initialization.py +++ b/utils/upgradeability/check_initialization.py @@ -11,7 +11,7 @@ class MultipleInitTarget(Exception): pass def _get_initialize_functions(contract): - return [f for father in contract.inheritance + [contract] for f in father.functions_not_inherited if f.name == 'initialize'] + return [f for f in contract.functions if f.name == 'initialize'] def _get_all_internal_calls(function): all_ir = function.all_slithir_operations() @@ -19,12 +19,11 @@ def _get_all_internal_calls(function): def _get_most_derived_init(contract): - for c in [contract] + contract.inheritance: - init_functions = [f for f in c.functions_not_inherited if f.name == 'initialize'] - if len(init_functions) > 1: - raise MultipleInitTarget - if init_functions: - return init_functions[0] + init_functions = [f for f in contract.functions if not f.is_shadowed and f.name == 'initialize'] + if len(init_functions) > 1: + raise MultipleInitTarget + if init_functions: + return init_functions[0] return None def check_initialization(s): @@ -37,8 +36,6 @@ def check_initialization(s): logger.info(yellow('Initializable contract not found, the contract does not follow a standard initalization schema.')) return - initializer = initializable.get_modifier_from_signature('initializer()') - init_info = '' double_calls_found = False @@ -47,25 +44,26 @@ def check_initialization(s): for contract in s.contracts: if initializable in contract.inheritance: + initializer = contract.get_modifier_from_canonical_name('Initializable.initializer()') all_init_functions = _get_initialize_functions(contract) for f in all_init_functions: if not initializer in f.modifiers: initializer_modifier_missing = True - logger.info(red(f'{f.contract.name}.{f.name} does not call initializer')) + logger.info(red(f'{f.canonical_name} does not call initializer')) most_derived_init = _get_most_derived_init(contract) if most_derived_init is None: init_info += f'{contract.name} has no initialize function\n' continue else: init_info += f'{contract.name} needs to be initialized by {most_derived_init.full_name}\n' - all_init_functions_called = _get_all_internal_calls(most_derived_init) + [most_derived_init] + all_init_functions_called = _get_all_internal_calls(most_derived_init) + [most_derived_init] missing_calls = [f for f in all_init_functions if not f in all_init_functions_called] for f in missing_calls: - logger.info(red(f'Missing call to {f.contract.name}.{f.name} in {contract.name}')) + logger.info(red(f'Missing call to {f.canonical_name} in {contract.name}')) missing_call = True double_calls = list(set([f for f in all_init_functions_called if all_init_functions_called.count(f) > 1])) for f in double_calls: - logger.info(red(f'{f.contract.name + "." + f.full_name} is called multiple time in {contract.name}')) + logger.info(red(f'{f.canonical_name} is called multiple time in {contract.name}')) double_calls_found = True if not initializer_modifier_missing: