Improve types in detectors

pull/1624/head
Feist Josselin 2 years ago
parent 83d4d5030f
commit 8b6ac75905
  1. 6
      slither/detectors/assembly/shift_parameter_mixup.py
  2. 5
      slither/detectors/attributes/constant_pragma.py
  3. 6
      slither/detectors/attributes/incorrect_solc.py
  4. 7
      slither/detectors/attributes/locked_ether.py
  5. 10
      slither/detectors/attributes/unimplemented_interface.py
  6. 5
      slither/detectors/compiler_bugs/array_by_reference.py
  7. 9
      slither/detectors/compiler_bugs/enum_conversion.py
  8. 5
      slither/detectors/compiler_bugs/multiple_constructor_schemes.py
  9. 4
      slither/detectors/compiler_bugs/storage_signed_integer_array.py
  10. 13
      slither/detectors/erc/erc20/incorrect_erc20_interface.py
  11. 2
      slither/detectors/erc/incorrect_erc721_interface.py
  12. 2
      slither/detectors/erc/unindexed_event_parameters.py
  13. 5
      slither/detectors/examples/backdoor.py
  14. 4
      slither/detectors/functions/dead_code.py
  15. 4
      slither/detectors/functions/modifier.py
  16. 4
      slither/detectors/functions/permit_domain_signature_collision.py
  17. 4
      slither/detectors/functions/protected_variable.py
  18. 8
      slither/detectors/functions/suicidal.py
  19. 4
      slither/detectors/functions/unimplemented.py
  20. 6
      slither/detectors/naming_convention/naming_convention.py
  21. 4
      slither/detectors/operations/block_timestamp.py
  22. 6
      slither/detectors/operations/low_level_calls.py
  23. 13
      slither/detectors/operations/missing_events_access_control.py
  24. 17
      slither/detectors/operations/missing_events_arithmetic.py
  25. 19
      slither/detectors/operations/missing_zero_address_validation.py
  26. 13
      slither/detectors/operations/unused_return_values.py
  27. 5
      slither/detectors/operations/void_constructor.py
  28. 4
      slither/detectors/reentrancy/reentrancy_benign.py
  29. 6
      slither/detectors/reentrancy/reentrancy_events.py
  30. 13
      slither/detectors/reentrancy/reentrancy_no_gas.py
  31. 3
      slither/detectors/reentrancy/token.py
  32. 19
      slither/detectors/shadowing/builtin_symbols.py
  33. 17
      slither/detectors/shadowing/local.py
  34. 8
      slither/detectors/shadowing/state.py
  35. 7
      slither/detectors/slither/name_reused.py
  36. 5
      slither/detectors/source/rtlo.py
  37. 11
      slither/detectors/statements/assembly.py
  38. 11
      slither/detectors/statements/assert_state_change.py
  39. 15
      slither/detectors/statements/boolean_constant_equality.py
  40. 15
      slither/detectors/statements/boolean_constant_misuse.py
  41. 11
      slither/detectors/statements/controlled_delegatecall.py
  42. 42
      slither/detectors/statements/deprecated_calls.py
  43. 29
      slither/detectors/statements/divide_before_multiply.py
  44. 2
      slither/detectors/statements/incorrect_strict_equality.py
  45. 16
      slither/detectors/statements/mapping_deletion.py
  46. 11
      slither/detectors/statements/redundant_statements.py
  47. 12
      slither/detectors/statements/too_many_digits.py
  48. 11
      slither/detectors/statements/tx_origin.py
  49. 19
      slither/detectors/statements/type_based_tautology.py
  50. 11
      slither/detectors/statements/unary.py
  51. 4
      slither/detectors/statements/unprotected_upgradeable.py
  52. 4
      slither/detectors/statements/write_after_write.py
  53. 13
      slither/detectors/variables/function_init_state_variables.py
  54. 17
      slither/detectors/variables/predeclaration_usage_local.py
  55. 7
      slither/detectors/variables/similar_variables.py
  56. 8
      slither/detectors/variables/uninitialized_local_variables.py
  57. 34
      slither/detectors/variables/uninitialized_state_variables.py
  58. 9
      slither/detectors/variables/uninitialized_storage_variables.py
  59. 11
      slither/detectors/variables/unused_state_variables.py
  60. 4
      slither/detectors/variables/var_read_using_this.py

@ -1,4 +1,4 @@
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Binary, BinaryType from slither.slithir.operations import Binary, BinaryType
from slither.slithir.variables import Constant from slither.slithir.variables import Constant
@ -39,7 +39,7 @@ The shift statement will right-shift the constant 8 by `a` bits"""
WIKI_RECOMMENDATION = "Swap the order of parameters." WIKI_RECOMMENDATION = "Swap the order of parameters."
def _check_function(self, f: FunctionContract) -> List[Union[Output, Any]]: def _check_function(self, f: FunctionContract) -> List[Output]:
results = [] results = []
for node in f.nodes: for node in f.nodes:
@ -55,7 +55,7 @@ The shift statement will right-shift the constant 8 by `a` bits"""
results.append(json) results.append(json)
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
for c in self.contracts: for c in self.contracts:
for f in c.functions: for f in c.functions:

@ -1,7 +1,8 @@
""" """
Check that the same pragma is used in all the files Check that the same pragma is used in all the files
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.formatters.attributes.constant_pragma import custom_format from slither.formatters.attributes.constant_pragma import custom_format
from slither.utils.output import Output from slither.utils.output import Output
@ -23,7 +24,7 @@ class ConstantPragma(AbstractDetector):
WIKI_DESCRIPTION = "Detect whether different Solidity versions are used." WIKI_DESCRIPTION = "Detect whether different Solidity versions are used."
WIKI_RECOMMENDATION = "Use one Solidity version." WIKI_RECOMMENDATION = "Use one Solidity version."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
pragma = self.compilation_unit.pragma_directives pragma = self.compilation_unit.pragma_directives
versions = [p.version for p in pragma if p.is_solidity_version] versions = [p.version for p in pragma if p.is_solidity_version]

@ -3,12 +3,12 @@
""" """
import re import re
from typing import Any, List, Optional, Tuple, Union from typing import List, Optional, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.formatters.attributes.incorrect_solc import custom_format from slither.formatters.attributes.incorrect_solc import custom_format
from slither.utils.output import Output from slither.utils.output import Output
# group: # group:
# 0: ^ > >= < <= (optional) # 0: ^ > >= < <= (optional)
# 1: ' ' (optional) # 1: ' ' (optional)
@ -120,7 +120,7 @@ Consider using the latest version of Solidity for testing."""
return self._check_version(version_left) return self._check_version(version_left)
return self.COMPLEX_PRAGMA_TXT return self.COMPLEX_PRAGMA_TXT
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detects pragma statements that allow for outdated solc versions. Detects pragma statements that allow for outdated solc versions.
:return: Returns the relevant JSON data for the findings. :return: Returns the relevant JSON data for the findings.

@ -1,7 +1,9 @@
""" """
Check if ethers are locked in the contract Check if ethers are locked in the contract
""" """
from typing import Any, List, Union from typing import List
from slither.core.declarations.contract import Contract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import ( from slither.slithir.operations import (
HighLevelCall, HighLevelCall,
@ -12,7 +14,6 @@ from slither.slithir.operations import (
LibraryCall, LibraryCall,
InternalCall, InternalCall,
) )
from slither.core.declarations.contract import Contract
from slither.utils.output import Output from slither.utils.output import Output
@ -75,7 +76,7 @@ Every Ether sent to `Locked` will be lost."""
return True return True
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
results = [] results = []
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:

@ -4,7 +4,7 @@ Module detecting unimplemented interfaces
Collect all the interfaces Collect all the interfaces
Check for contracts which implement all interface functions but do not explicitly derive from those interfaces. Check for contracts which implement all interface functions but do not explicitly derive from those interfaces.
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.utils.output import Output from slither.utils.output import Output
@ -45,8 +45,8 @@ contract Something {
@staticmethod @staticmethod
def detect_unimplemented_interface( def detect_unimplemented_interface(
contract: Contract, interfaces: List[Union[Any, Contract]] contract: Contract, interfaces: List[Contract]
) -> List[Union[Any, Contract]]: ) -> List[Contract]:
""" """
Detects if contract intends to implement one of the interfaces but does not explicitly do so by deriving from it Detects if contract intends to implement one of the interfaces but does not explicitly do so by deriving from it
:param contract: The contract to check :param contract: The contract to check
@ -54,7 +54,7 @@ contract Something {
:return: Interfaces likely intended to implement by the contract :return: Interfaces likely intended to implement by the contract
""" """
intended_interfaces = [] intended_interfaces: List[Contract] = []
sigs_contract = {f.full_name for f in contract.functions_entry_points} sigs_contract = {f.full_name for f in contract.functions_entry_points}
if not sigs_contract: if not sigs_contract:
@ -115,7 +115,7 @@ contract Something {
return intended_interfaces return intended_interfaces
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect unimplemented interfaces """Detect unimplemented interfaces
Returns: Returns:
list: {'contract'} list: {'contract'}

@ -1,7 +1,7 @@
""" """
Detects the passing of arrays located in memory to functions which expect to modify arrays via storage reference. Detects the passing of arrays located in memory to functions which expect to modify arrays via storage reference.
""" """
from typing import Any, List, Set, Tuple, Union from typing import List, Set, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.solidity_types.array_type import ArrayType from slither.core.solidity_types.array_type import ArrayType
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
@ -93,7 +93,6 @@ As a result, Bob's usage of the contract is incorrect."""
Union[ Union[
Tuple[Node, StateVariable, FunctionContract], Tuple[Node, StateVariable, FunctionContract],
Tuple[Node, LocalVariable, FunctionContract], Tuple[Node, LocalVariable, FunctionContract],
Any,
] ]
]: ]:
""" """
@ -146,7 +145,7 @@ As a result, Bob's usage of the contract is incorrect."""
results.append((node, arg, ir.function)) results.append((node, arg, ir.function))
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detects passing of arrays located in memory to functions which expect to modify arrays via storage reference. Detects passing of arrays located in memory to functions which expect to modify arrays via storage reference.
:return: The JSON results of the detector, which contains the calling_node, affected_argument_variable and :return: The JSON results of the detector, which contains the calling_node, affected_argument_variable and

@ -1,7 +1,11 @@
""" """
Module detecting dangerous conversion to enum Module detecting dangerous conversion to enum
""" """
from typing import List, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations import Contract
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.detectors.abstract_detector import ( from slither.detectors.abstract_detector import (
AbstractDetector, AbstractDetector,
DetectorClassification, DetectorClassification,
@ -9,9 +13,10 @@ from slither.detectors.abstract_detector import (
) )
from slither.slithir.operations import TypeConversion from slither.slithir.operations import TypeConversion
from slither.core.declarations.enum import Enum from slither.core.declarations.enum import Enum
from slither.utils.output import Output
def _detect_dangerous_enum_conversions(contract): def _detect_dangerous_enum_conversions(contract: Contract) -> List[Tuple[Node, SourceMapping]]:
"""Detect dangerous conversion to enum by checking IR """Detect dangerous conversion to enum by checking IR
Args: Args:
contract (Contract) contract (Contract)
@ -61,7 +66,7 @@ Attackers can trigger unexpected behaviour by calling `bug(1)`."""
VULNERABLE_SOLC_VERSIONS = make_solc_versions(4, 0, 4) VULNERABLE_SOLC_VERSIONS = make_solc_versions(4, 0, 4)
def _detect(self): def _detect(self) -> List[Output]:
"""Detect dangerous conversion to enum""" """Detect dangerous conversion to enum"""
results = [] results = []

@ -1,4 +1,5 @@
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -45,7 +46,7 @@ In Solidity [0.4.22](https://github.com/ethereum/solidity/releases/tag/v0.4.23),
WIKI_RECOMMENDATION = "Only declare one constructor, preferably using the new scheme `constructor(...)` instead of `function <contractName>(...)`." WIKI_RECOMMENDATION = "Only declare one constructor, preferably using the new scheme `constructor(...)` instead of `function <contractName>(...)`."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detect multiple constructor schemes in the same contract Detect multiple constructor schemes in the same contract
:return: Returns a list of contract JSON result, where each result contains all constructor definitions. :return: Returns a list of contract JSON result, where each result contains all constructor definitions.

@ -1,6 +1,7 @@
""" """
Module detecting storage signed integer array bug Module detecting storage signed integer array bug
""" """
from typing import List
from slither.detectors.abstract_detector import ( from slither.detectors.abstract_detector import (
AbstractDetector, AbstractDetector,
@ -14,6 +15,7 @@ from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations.assignment import Assignment from slither.slithir.operations.assignment import Assignment
from slither.slithir.operations.init_array import InitArray from slither.slithir.operations.init_array import InitArray
from slither.utils.output import Output
class StorageSignedIntegerArray(AbstractDetector): class StorageSignedIntegerArray(AbstractDetector):
@ -108,7 +110,7 @@ contract A {
# Return the resulting set of tuples # Return the resulting set of tuples
return results return results
def _detect(self): def _detect(self) -> List[Output]:
""" """
Detect storage signed integer array init/assignment Detect storage signed integer array init/assignment
""" """

@ -2,10 +2,11 @@
Detect incorrect erc20 interface. Detect incorrect erc20 interface.
Some contracts do not return a bool on transfer/transferFrom/approve, which may lead to preventing the contract to be used with contracts compiled with recent solc (>0.4.22) Some contracts do not return a bool on transfer/transferFrom/approve, which may lead to preventing the contract to be used with contracts compiled with recent solc (>0.4.22)
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -40,9 +41,7 @@ contract Token{
) )
@staticmethod @staticmethod
def incorrect_erc20_interface( def incorrect_erc20_interface(signature: Tuple[str, List[str], List[str]]) -> bool:
signature: Union[Tuple[str, List[str], List[Any]], Tuple[str, List[Any], List[Any]]]
) -> bool:
(name, parameters, returnVars) = signature (name, parameters, returnVars) = signature
if name == "transfer" and parameters == ["address", "uint256"] and returnVars != ["bool"]: if name == "transfer" and parameters == ["address", "uint256"] and returnVars != ["bool"]:
@ -74,7 +73,7 @@ contract Token{
return False return False
@staticmethod @staticmethod
def detect_incorrect_erc20_interface(contract: Contract) -> List[Union[FunctionContract, Any]]: def detect_incorrect_erc20_interface(contract: Contract) -> List[FunctionContract]:
"""Detect incorrect ERC20 interface """Detect incorrect ERC20 interface
Returns: Returns:
@ -99,7 +98,7 @@ contract Token{
return functions return functions
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect incorrect erc20 interface """Detect incorrect erc20 interface
Returns: Returns:

@ -108,7 +108,7 @@ contract Token{
] ]
return functions return functions
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect incorrect erc721 interface """Detect incorrect erc721 interface
Returns: Returns:

@ -75,7 +75,7 @@ Failure to include these keywords will exclude the parameter data in the transac
# Return the results. # Return the results.
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detect un-indexed ERC20 event parameters in all contracts. Detect un-indexed ERC20 event parameters in all contracts.
""" """

@ -1,4 +1,5 @@
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -19,7 +20,7 @@ class Backdoor(AbstractDetector):
WIKI_EXPLOIT_SCENARIO = ".." WIKI_EXPLOIT_SCENARIO = ".."
WIKI_RECOMMENDATION = ".." WIKI_RECOMMENDATION = ".."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:

@ -1,7 +1,7 @@
""" """
Module detecting dead code Module detecting dead code
""" """
from typing import Any, Union, List, Tuple from typing import List, Tuple
from slither.core.declarations import Function, FunctionContract, Contract from slither.core.declarations import Function, FunctionContract, Contract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
@ -35,7 +35,7 @@ contract Contract{
WIKI_RECOMMENDATION = "Remove unused functions." WIKI_RECOMMENDATION = "Remove unused functions."
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
results = [] results = []

@ -5,7 +5,7 @@ Note that require()/assert() are not considered here. Even if they
are in the outermost scope, they do not guarantee a revert, so a are in the outermost scope, they do not guarantee a revert, so a
default value can still be returned. default value can still be returned.
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import Node, NodeType from slither.core.cfg.node import Node, NodeType
from slither.utils.output import Output from slither.utils.output import Output
@ -61,7 +61,7 @@ If the condition in `myModif` is false, the execution of `get()` will return 0."
WIKI_RECOMMENDATION = "All the paths in a modifier must execute `_` or revert." WIKI_RECOMMENDATION = "All the paths in a modifier must execute `_` or revert."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
for c in self.contracts: for c in self.contracts:
for mod in c.modifiers: for mod in c.modifiers:

@ -1,7 +1,7 @@
""" """
Module detecting EIP-2612 domain separator collision Module detecting EIP-2612 domain separator collision
""" """
from typing import Any, Union, List from typing import Union, List
from slither.core.declarations import Function from slither.core.declarations import Function
from slither.core.solidity_types.elementary_type import ElementaryType from slither.core.solidity_types.elementary_type import ElementaryType
@ -40,7 +40,7 @@ contract Contract{
WIKI_RECOMMENDATION = "Remove or rename the function that collides with DOMAIN_SEPARATOR()." WIKI_RECOMMENDATION = "Remove or rename the function that collides with DOMAIN_SEPARATOR()."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
domain_sig = get_function_id("DOMAIN_SEPARATOR()") domain_sig = get_function_id("DOMAIN_SEPARATOR()")
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:
if contract.is_erc20(): if contract.is_erc20():

@ -3,7 +3,7 @@ Module detecting suicidal contract
A suicidal contract is an unprotected function that calls selfdestruct A suicidal contract is an unprotected function that calls selfdestruct
""" """
from typing import Any, Union, List from typing import List
from slither.core.declarations import Function, Contract from slither.core.declarations import Function, Contract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
@ -71,7 +71,7 @@ contract Buggy{
results.append(res) results.append(res)
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect the suicidal functions""" """Detect the suicidal functions"""
results = [] results = []
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:

@ -3,11 +3,11 @@ Module detecting suicidal contract
A suicidal contract is an unprotected function that calls selfdestruct A suicidal contract is an unprotected function that calls selfdestruct
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -64,14 +64,14 @@ Bob calls `kill` and destructs the contract."""
return True return True
def detect_suicidal(self, contract: Contract) -> List[Union[Any, FunctionContract]]: def detect_suicidal(self, contract: Contract) -> List[FunctionContract]:
ret = [] ret = []
for f in contract.functions_declared: for f in contract.functions_declared:
if self.detect_suicidal_func(f): if self.detect_suicidal_func(f):
ret.append(f) ret.append(f)
return ret return ret
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect the suicidal functions""" """Detect the suicidal functions"""
results = [] results = []
for c in self.contracts: for c in self.contracts:

@ -7,7 +7,7 @@ Check for unimplemented functions that are never implemented
Consider public state variables as implemented functions Consider public state variables as implemented functions
Do not consider fallback function or constructor Do not consider fallback function or constructor
""" """
from typing import Any, List, Set, Union from typing import List, Set
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
@ -91,7 +91,7 @@ All unimplemented functions must be implemented on a contract that is meant to b
unimplemented.add(f) unimplemented.add(f)
return unimplemented return unimplemented
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect unimplemented functions """Detect unimplemented functions
Recursively visit the calls Recursively visit the calls

@ -1,5 +1,5 @@
import re import re
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.formatters.naming_convention.naming_convention import custom_format from slither.formatters.naming_convention.naming_convention import custom_format
from slither.utils.output import Output from slither.utils.output import Output
@ -60,9 +60,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2
return re.search("^[lOI]$", name) is not None return re.search("^[lOI]$", name) is not None
# pylint: disable=too-many-branches,too-many-statements # pylint: disable=too-many-branches,too-many-statements
def _detect( def _detect(self) -> List[Output]:
self,
) -> List[Union[Any, Output]]:
results = [] results = []
for contract in self.contracts: for contract in self.contracts:

@ -2,7 +2,7 @@
Module detecting dangerous use of block.timestamp Module detecting dangerous use of block.timestamp
""" """
from typing import Any, Union, List, Tuple from typing import List, Tuple
from slither.analyses.data_dependency.data_dependency import is_dependent from slither.analyses.data_dependency.data_dependency import is_dependent
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
@ -70,7 +70,7 @@ class Timestamp(AbstractDetector):
WIKI_EXPLOIT_SCENARIO = """"Bob's contract relies on `block.timestamp` for its randomness. Eve is a miner and manipulates `block.timestamp` to exploit Bob's contract.""" WIKI_EXPLOIT_SCENARIO = """"Bob's contract relies on `block.timestamp` for its randomness. Eve is a miner and manipulates `block.timestamp` to exploit Bob's contract."""
WIKI_RECOMMENDATION = "Avoid relying on `block.timestamp`." WIKI_RECOMMENDATION = "Avoid relying on `block.timestamp`."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""""" """"""
results = [] results = []

@ -1,7 +1,7 @@
""" """
Module detecting usage of low level calls Module detecting usage of low level calls
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall from slither.slithir.operations import LowLevelCall
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
@ -37,7 +37,7 @@ class LowLevelCalls(AbstractDetector):
def detect_low_level_calls( def detect_low_level_calls(
self, contract: Contract self, contract: Contract
) -> List[Union[Any, Tuple[FunctionContract, List[Node]]]]: ) -> List[Tuple[FunctionContract, List[Node]]]:
ret = [] ret = []
for f in [f for f in contract.functions if contract == f.contract_declarer]: for f in [f for f in contract.functions if contract == f.contract_declarer]:
nodes = f.nodes nodes = f.nodes
@ -46,7 +46,7 @@ class LowLevelCalls(AbstractDetector):
ret.append((f, assembly_nodes)) ret.append((f, assembly_nodes))
return ret return ret
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect the functions that use low level calls""" """Detect the functions that use low level calls"""
results = [] results = []
for c in self.contracts: for c in self.contracts:

@ -2,16 +2,17 @@
Module detecting missing events for critical contract parameters set by owners and used in access control Module detecting missing events for critical contract parameters set by owners and used in access control
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.analyses.data_dependency.data_dependency import is_tainted from slither.analyses.data_dependency.data_dependency import is_tainted
from slither.slithir.operations.event_call import EventCall
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.core.declarations.modifier import Modifier from slither.core.declarations.modifier import Modifier
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.event_call import EventCall
from slither.utils.output import Output from slither.utils.output import Output
@ -53,7 +54,7 @@ contract C {
@staticmethod @staticmethod
def _detect_missing_events( def _detect_missing_events(
contract: Contract, contract: Contract,
) -> List[Union[Any, Tuple[FunctionContract, List[Tuple[Node, StateVariable, Modifier]]]]]: ) -> List[Tuple[FunctionContract, List[Tuple[Node, StateVariable, Modifier]]]]:
""" """
Detects if critical contract parameters set by owners and used in access control are missing events Detects if critical contract parameters set by owners and used in access control are missing events
:param contract: The contract to check :param contract: The contract to check
@ -88,7 +89,7 @@ contract C {
results.append((function, nodes)) results.append((function, nodes))
return results return results
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect missing events for critical contract parameters set by owners and used in access control """Detect missing events for critical contract parameters set by owners and used in access control
Returns: Returns:
list: {'(function, node)'} list: {'(function, node)'}

@ -2,15 +2,16 @@
Module detecting missing events for critical contract parameters set by owners and used in arithmetic Module detecting missing events for critical contract parameters set by owners and used in arithmetic
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.analyses.data_dependency.data_dependency import is_tainted from slither.analyses.data_dependency.data_dependency import is_tainted
from slither.slithir.operations.event_call import EventCall
from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uint
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uint
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.event_call import EventCall
from slither.utils.output import Output from slither.utils.output import Output
@ -56,7 +57,7 @@ contract C {
@staticmethod @staticmethod
def _detect_unprotected_use( def _detect_unprotected_use(
contract: Contract, sv: StateVariable contract: Contract, sv: StateVariable
) -> List[Union[Tuple[Node, FunctionContract], Any]]: ) -> List[Tuple[Node, FunctionContract]]:
unprotected_functions = [ unprotected_functions = [
function for function in contract.functions_declared if not function.is_protected() function for function in contract.functions_declared if not function.is_protected()
] ]
@ -69,9 +70,7 @@ contract C {
def _detect_missing_events( def _detect_missing_events(
self, contract: Contract self, contract: Contract
) -> List[ ) -> List[Tuple[FunctionContract, List[Tuple[Node, List[Tuple[Node, FunctionContract]]]]]]:
Union[Tuple[FunctionContract, List[Tuple[Node, List[Tuple[Node, FunctionContract]]]]], Any]
]:
""" """
Detects if critical contract parameters set by owners and used in arithmetic are missing events Detects if critical contract parameters set by owners and used in arithmetic are missing events
:param contract: The contract to check :param contract: The contract to check
@ -112,7 +111,7 @@ contract C {
results.append((function, nodes)) results.append((function, nodes))
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect missing events for critical contract parameters set by owners and used in arithmetic """Detect missing events for critical contract parameters set by owners and used in arithmetic
Returns: Returns:
list: {'(function, node)'} list: {'(function, node)'}

@ -3,17 +3,18 @@ Module detecting missing zero address validation
""" """
from collections import defaultdict from collections import defaultdict
from typing import Any, DefaultDict, List, Tuple, Union from typing import DefaultDict, List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.analyses.data_dependency.data_dependency import is_tainted from slither.analyses.data_dependency.data_dependency import is_tainted
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.slithir.operations import Send, Transfer, LowLevelCall
from slither.slithir.operations import Call
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function import ModifierStatements from slither.core.declarations.function import ModifierStatements
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable import LocalVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Call
from slither.slithir.operations import Send, Transfer, LowLevelCall
from slither.utils.output import Output from slither.utils.output import Output
@ -53,7 +54,7 @@ Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownershi
WIKI_RECOMMENDATION = "Check that the address is not zero." WIKI_RECOMMENDATION = "Check that the address is not zero."
def _zero_address_validation_in_modifier( def _zero_address_validation_in_modifier(
self, var: LocalVariable, modifier_exprs: List[Union[ModifierStatements, Any]] self, var: LocalVariable, modifier_exprs: List[ModifierStatements]
) -> bool: ) -> bool:
for mod in modifier_exprs: for mod in modifier_exprs:
for node in mod.nodes: for node in mod.nodes:
@ -71,7 +72,7 @@ Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownershi
return False return False
def _zero_address_validation( def _zero_address_validation(
self, var: LocalVariable, node: Node, explored: List[Union[Any, Node]] self, var: LocalVariable, node: Node, explored: List[Node]
) -> bool: ) -> bool:
""" """
Detects (recursively) if var is (zero address) checked in the function node Detects (recursively) if var is (zero address) checked in the function node
@ -95,7 +96,7 @@ Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownershi
def _detect_missing_zero_address_validation( def _detect_missing_zero_address_validation(
self, contract: Contract self, contract: Contract
) -> List[Union[Tuple[FunctionContract, DefaultDict[LocalVariable, List[Node]]], Any]]: ) -> List[Union[Tuple[FunctionContract, DefaultDict[LocalVariable, List[Node]]]]]:
""" """
Detects if addresses are zero address validated before use. Detects if addresses are zero address validated before use.
:param contract: The contract to check :param contract: The contract to check
@ -142,7 +143,7 @@ Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownershi
results.append((function, var_nodes)) results.append((function, var_nodes))
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect if addresses are zero address validated before use. """Detect if addresses are zero address validated before use.
Returns: Returns:
list: {'(function, node)'} list: {'(function, node)'}

@ -1,13 +1,14 @@
""" """
Module detecting unused return values from external calls Module detecting unused return values from external calls
""" """
from typing import Any, List, Union from typing import List
from slither.core.cfg.node import Node
from slither.core.declarations import Function
from slither.core.declarations.function_contract import FunctionContract
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import HighLevelCall from slither.slithir.operations import HighLevelCall
from slither.core.declarations import Function
from slither.core.cfg.node import Node
from slither.core.declarations.function_contract import FunctionContract
from slither.slithir.operations.operation import Operation from slither.slithir.operations.operation import Operation
from slither.utils.output import Output from slither.utils.output import Output
@ -56,7 +57,7 @@ contract MyConc{
def detect_unused_return_values( def detect_unused_return_values(
self, f: FunctionContract self, f: FunctionContract
) -> List[Union[Node, Any]]: # pylint: disable=no-self-use ) -> List[Node]: # pylint: disable=no-self-use
""" """
Return the nodes where the return value of a call is unused Return the nodes where the return value of a call is unused
Args: Args:
@ -79,7 +80,7 @@ contract MyConc{
return [nodes_origin[value].node for value in values_returned] return [nodes_origin[value].node for value in values_returned]
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect high level calls which return a value that are never used""" """Detect high level calls which return a value that are never used"""
results = [] results = []
for c in self.compilation_unit.contracts: for c in self.compilation_unit.contracts:

@ -1,4 +1,5 @@
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Nop from slither.slithir.operations import Nop
from slither.utils.output import Output from slither.utils.output import Output
@ -28,7 +29,7 @@ contract B is A{
When reading `B`'s constructor definition, we might assume that `A()` initiates the contract, but no code is executed.""" When reading `B`'s constructor definition, we might assume that `A()` initiates the contract, but no code is executed."""
# endregion wiki_exploit_scenario # endregion wiki_exploit_scenario
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""""" """"""
results = [] results = []
for c in self.contracts: for c in self.contracts:

@ -5,7 +5,7 @@
Iterate over all the nodes of the graph until reaching a fixpoint Iterate over all the nodes of the graph until reaching a fixpoint
""" """
from collections import namedtuple, defaultdict from collections import namedtuple, defaultdict
from typing import Any, DefaultDict, Set, Union, List from typing import DefaultDict, Set, List
from slither.detectors.abstract_detector import DetectorClassification from slither.detectors.abstract_detector import DetectorClassification
from slither.detectors.reentrancy.reentrancy import Reentrancy, to_hashable from slither.detectors.reentrancy.reentrancy import Reentrancy, to_hashable
@ -88,7 +88,7 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr
result[finding_key] |= not_read_then_written result[finding_key] |= not_read_then_written
return result return result
def _detect(self) -> List[Union[Output, Any]]: # pylint: disable=too-many-branches def _detect(self) -> List[Output]: # pylint: disable=too-many-branches
"""""" """"""
super()._detect() super()._detect()

@ -5,12 +5,12 @@
Iterate over all the nodes of the graph until reaching a fixpoint Iterate over all the nodes of the graph until reaching a fixpoint
""" """
from collections import namedtuple, defaultdict from collections import namedtuple, defaultdict
from typing import Any, DefaultDict, List, Set, Union from typing import DefaultDict, List, Set
from slither.detectors.abstract_detector import DetectorClassification from slither.detectors.abstract_detector import DetectorClassification
from slither.detectors.reentrancy.reentrancy import Reentrancy, to_hashable from slither.detectors.reentrancy.reentrancy import Reentrancy, to_hashable
from slither.utils.output import Output from slither.utils.output import Output
FindingKey = namedtuple("FindingKey", ["function", "calls", "send_eth"]) FindingKey = namedtuple("FindingKey", ["function", "calls", "send_eth"])
FindingValue = namedtuple("FindingValue", ["variable", "node", "nodes"]) FindingValue = namedtuple("FindingValue", ["variable", "node", "nodes"])
@ -82,7 +82,7 @@ If `d.()` re-enters, the `Counter` events will be shown in an incorrect order, w
result[finding_key] |= finding_vars result[finding_key] |= finding_vars
return result return result
def _detect(self) -> List[Union[Any, Output]]: # pylint: disable=too-many-branches def _detect(self) -> List[Output]: # pylint: disable=too-many-branches
"""""" """"""
super()._detect() super()._detect()

@ -5,15 +5,16 @@
Iterate over all the nodes of the graph until reaching a fixpoint Iterate over all the nodes of the graph until reaching a fixpoint
""" """
from collections import namedtuple, defaultdict from collections import namedtuple, defaultdict
from typing import Any, DefaultDict, List, Union from typing import DefaultDict, List, Union, Set
from slither.core.variables.variable import Variable from slither.core.variables.variable import Variable
from slither.detectors.abstract_detector import DetectorClassification from slither.detectors.abstract_detector import DetectorClassification
from slither.slithir.operations import Send, Transfer, EventCall
from slither.detectors.reentrancy.reentrancy import Reentrancy, to_hashable from slither.detectors.reentrancy.reentrancy import Reentrancy, to_hashable
from slither.slithir.operations import Send, Transfer, EventCall
from slither.slithir.operations.high_level_call import HighLevelCall from slither.slithir.operations.high_level_call import HighLevelCall
from slither.slithir.operations.member import Member from slither.slithir.operations.member import Member
from slither.slithir.operations.return_operation import Return from slither.slithir.operations.return_operation import Return
from slither.utils.output import Output
FindingKey = namedtuple("FindingKey", ["function", "calls", "send_eth"]) FindingKey = namedtuple("FindingKey", ["function", "calls", "send_eth"])
FindingValue = namedtuple("FindingValue", ["variable", "node", "nodes"]) FindingValue = namedtuple("FindingValue", ["variable", "node", "nodes"])
@ -63,8 +64,8 @@ Only report reentrancy that is based on `transfer` or `send`."""
STANDARD_JSON = False STANDARD_JSON = False
def find_reentrancies(self) -> DefaultDict[Any, Any]: def find_reentrancies(self) -> DefaultDict[FindingKey, Set[FindingValue]]:
result = defaultdict(set) result: DefaultDict[FindingKey, Set[FindingValue]] = defaultdict(set)
for contract in self.contracts: for contract in self.contracts:
for f in contract.functions_and_modifiers_declared: for f in contract.functions_and_modifiers_declared:
for node in f.nodes: for node in f.nodes:
@ -101,7 +102,7 @@ Only report reentrancy that is based on `transfer` or `send`."""
result[finding_key] |= finding_vars result[finding_key] |= finding_vars
return result return result
def _detect(self) -> List[Any]: # pylint: disable=too-many-branches,too-many-locals def _detect(self) -> List[Output]: # pylint: disable=too-many-branches,too-many-locals
"""""" """"""
super()._detect() super()._detect()

@ -6,6 +6,7 @@ from slither.core.cfg.node import Node
from slither.core.declarations import Function, Contract, SolidityVariableComposed from slither.core.declarations import Function, Contract, SolidityVariableComposed
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall, HighLevelCall from slither.slithir.operations import LowLevelCall, HighLevelCall
from slither.utils.output import Output
def _detect_token_reentrant(contract: Contract) -> Dict[Function, List[Node]]: def _detect_token_reentrant(contract: Contract) -> Dict[Function, List[Node]]:
@ -82,7 +83,7 @@ contract MyDefi{
If you do, ensure your users are aware of the potential issues.""" If you do, ensure your users are aware of the potential issues."""
# endregion wiki_recommendation # endregion wiki_recommendation
def _detect(self): def _detect(self) -> List[Output]:
results = [] results = []
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:
vulns = _detect_token_reentrant(contract) vulns = _detect_token_reentrant(contract)

@ -1,12 +1,15 @@
""" """
Module detecting reserved keyword shadowing Module detecting reserved keyword shadowing
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple, Union, Optional
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations import Function, Event
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.core.declarations.modifier import Modifier from slither.core.declarations.modifier import Modifier
from slither.core.variables import Variable
from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable import LocalVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -119,7 +122,7 @@ contract Bug {
"unchecked", "unchecked",
] ]
def is_builtin_symbol(self, word: str) -> bool: def is_builtin_symbol(self, word: Optional[str]) -> bool:
"""Detects if a given word is a built-in symbol. """Detects if a given word is a built-in symbol.
Returns: Returns:
@ -129,7 +132,7 @@ contract Bug {
def detect_builtin_shadowing_locals( def detect_builtin_shadowing_locals(
self, function_or_modifier: Union[Modifier, FunctionContract] self, function_or_modifier: Union[Modifier, FunctionContract]
) -> List[Union[Any, Tuple[str, LocalVariable]]]: ) -> List[Tuple[str, LocalVariable]]:
"""Detects if local variables in a given function/modifier are named after built-in symbols. """Detects if local variables in a given function/modifier are named after built-in symbols.
Any such items are returned in a list. Any such items are returned in a list.
@ -142,14 +145,16 @@ contract Bug {
results.append((self.SHADOWING_LOCAL_VARIABLE, local)) results.append((self.SHADOWING_LOCAL_VARIABLE, local))
return results return results
def detect_builtin_shadowing_definitions(self, contract: Contract) -> List[Any]: def detect_builtin_shadowing_definitions(
self, contract: Contract
) -> List[Tuple[str, Union[Function, Variable, Event]]]:
"""Detects if functions, access modifiers, events, state variables, or local variables are named after built-in """Detects if functions, access modifiers, events, state variables, or local variables are named after built-in
symbols. Any such definitions are returned in a list. symbols. Any such definitions are returned in a list.
Returns: Returns:
list of tuple: (type, definition, [local variable parent])""" list of tuple: (type, definition, [local variable parent])"""
result = [] result: List[Tuple[str, Union[Function, Variable, Event]]] = []
# Loop through all functions, modifiers, variables (state and local) to detect any built-in symbol keywords. # Loop through all functions, modifiers, variables (state and local) to detect any built-in symbol keywords.
for function in contract.functions_declared: for function in contract.functions_declared:
@ -171,7 +176,7 @@ contract Bug {
return result return result
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect shadowing of built-in symbols """Detect shadowing of built-in symbols
Recursively visit the calls Recursively visit the calls

@ -1,14 +1,15 @@
""" """
Module detecting local variable shadowing Module detecting local variable shadowing
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.event import Event from slither.core.declarations.event import Event
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.core.declarations.modifier import Modifier from slither.core.declarations.modifier import Modifier
from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -62,7 +63,6 @@ contract Bug {
self, contract: Contract self, contract: Contract
) -> List[ ) -> List[
Union[ Union[
Any,
Tuple[LocalVariable, List[Tuple[str, StateVariable]]], Tuple[LocalVariable, List[Tuple[str, StateVariable]]],
Tuple[LocalVariable, List[Tuple[str, FunctionContract]]], Tuple[LocalVariable, List[Tuple[str, FunctionContract]]],
Tuple[LocalVariable, List[Tuple[str, Modifier]]], Tuple[LocalVariable, List[Tuple[str, Modifier]]],
@ -74,7 +74,14 @@ contract Bug {
Returns: Returns:
list of tuple: (type, contract name, definition)""" list of tuple: (type, contract name, definition)"""
result = [] result: List[
Union[
Tuple[LocalVariable, List[Tuple[str, StateVariable]]],
Tuple[LocalVariable, List[Tuple[str, FunctionContract]]],
Tuple[LocalVariable, List[Tuple[str, Modifier]]],
Tuple[LocalVariable, List[Tuple[str, Event]]],
]
] = []
# Loop through all functions + modifiers in this contract. # Loop through all functions + modifiers in this contract.
for function in contract.functions + contract.modifiers: for function in contract.functions + contract.modifiers:
@ -111,7 +118,7 @@ contract Bug {
return result return result
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect shadowing local variables """Detect shadowing local variables
Recursively visit the calls Recursively visit the calls

@ -2,16 +2,16 @@
Module detecting shadowing of state variables Module detecting shadowing of state variables
""" """
from typing import Any, List, Union from typing import List
from slither.core.declarations import Contract from slither.core.declarations import Contract
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output
from slither.detectors.shadowing.common import is_upgradable_gap_variable from slither.detectors.shadowing.common import is_upgradable_gap_variable
from slither.utils.output import Output
def detect_shadowing(contract: Contract) -> List[Union[List[StateVariable], Any]]: def detect_shadowing(contract: Contract) -> List[List[StateVariable]]:
ret = [] ret = []
variables_fathers = [] variables_fathers = []
for father in contract.inheritance: for father in contract.inheritance:
@ -74,7 +74,7 @@ contract DerivedContract is BaseContract{
WIKI_RECOMMENDATION = "Remove the state variable shadowing." WIKI_RECOMMENDATION = "Remove the state variable shadowing."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect shadowing """Detect shadowing
Recursively visit the calls Recursively visit the calls

@ -1,5 +1,6 @@
from collections import defaultdict from collections import defaultdict
from typing import Any, List, Union from typing import Any, List
from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.compilation_unit import SlitherCompilationUnit
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -52,9 +53,7 @@ As a result, the second contract cannot be analyzed.
WIKI_RECOMMENDATION = "Rename the contract." WIKI_RECOMMENDATION = "Rename the contract."
# pylint: disable=too-many-locals,too-many-branches # pylint: disable=too-many-locals,too-many-branches
def _detect( def _detect(self) -> List[Output]:
self,
) -> List[Union[Any, Output]]:
results = [] results = []
compilation_unit = self.compilation_unit compilation_unit = self.compilation_unit

@ -1,5 +1,6 @@
import re import re
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -55,7 +56,7 @@ contract Token
RTLO_CHARACTER_ENCODED = "\u202e".encode("utf-8") RTLO_CHARACTER_ENCODED = "\u202e".encode("utf-8")
STANDARD_JSON = False STANDARD_JSON = False
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
results = [] results = []
pattern = re.compile(".*\u202e.*".encode("utf-8")) pattern = re.compile(".*\u202e.*".encode("utf-8"))

@ -1,11 +1,12 @@
""" """
Module detecting usage of inline assembly Module detecting usage of inline assembly
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import Node, NodeType from slither.core.cfg.node import Node, NodeType
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -34,9 +35,7 @@ class Assembly(AbstractDetector):
""" """
return node.type == NodeType.ASSEMBLY return node.type == NodeType.ASSEMBLY
def detect_assembly( def detect_assembly(self, contract: Contract) -> List[Tuple[FunctionContract, List[Node]]]:
self, contract: Contract
) -> List[Union[Any, Tuple[FunctionContract, List[Node]]]]:
ret = [] ret = []
for f in contract.functions: for f in contract.functions:
if f.contract_declarer != contract: if f.contract_declarer != contract:
@ -47,7 +46,7 @@ class Assembly(AbstractDetector):
ret.append((f, assembly_nodes)) ret.append((f, assembly_nodes))
return ret return ret
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect the functions that use inline assembly""" """Detect the functions that use inline assembly"""
results = [] results = []
for c in self.contracts: for c in self.contracts:

@ -1,18 +1,19 @@
""" """
Module detecting state changes in assert calls Module detecting state changes in assert calls
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.internal_call import InternalCall
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.internal_call import InternalCall
from slither.utils.output import Output from slither.utils.output import Output
def detect_assert_state_change( def detect_assert_state_change(
contract: Contract, contract: Contract,
) -> List[Union[Tuple[FunctionContract, Node], Any]]: ) -> List[Tuple[FunctionContract, Node]]:
""" """
Detects and returns all nodes with assert calls that change contract state from within the invariant Detects and returns all nodes with assert calls that change contract state from within the invariant
:param contract: Contract to detect :param contract: Contract to detect
@ -76,7 +77,7 @@ The assert in `bad()` increments the state variable `s_a` while checking for the
WIKI_RECOMMENDATION = """Use `require` for invariants modifying the state.""" WIKI_RECOMMENDATION = """Use `require` for invariants modifying the state."""
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
""" """
Detect assert calls that change state from within the invariant Detect assert calls that change state from within the invariant
""" """

@ -1,16 +1,17 @@
""" """
Module detecting misuse of Boolean constants Module detecting misuse of Boolean constants
""" """
from typing import Any, List, Set, Tuple, Union from typing import List, Set, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations import Function
from slither.core.declarations.contract import Contract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import ( from slither.slithir.operations import (
Binary, Binary,
BinaryType, BinaryType,
) )
from slither.slithir.variables import Constant from slither.slithir.variables import Constant
from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.utils.output import Output from slither.utils.output import Output
@ -50,10 +51,10 @@ Boolean constants can be used directly and do not need to be compare to `true` o
@staticmethod @staticmethod
def _detect_boolean_equality( def _detect_boolean_equality(
contract: Contract, contract: Contract,
) -> List[Union[Tuple[FunctionContract, Set[Any]], Tuple[FunctionContract, Set[Node]], Any]]: ) -> List[Tuple[Function, Set[Node]]]:
# Create our result set. # Create our result set.
results = [] results: List[Tuple[Function, Set[Node]]] = []
# Loop for each function and modifier. # Loop for each function and modifier.
# pylint: disable=too-many-nested-blocks # pylint: disable=too-many-nested-blocks
@ -74,7 +75,7 @@ Boolean constants can be used directly and do not need to be compare to `true` o
# Return the resulting set of nodes with improper uses of Boolean constants # Return the resulting set of nodes with improper uses of Boolean constants
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detect Boolean constant misuses Detect Boolean constant misuses
""" """

@ -1,8 +1,11 @@
""" """
Module detecting misuse of Boolean constants Module detecting misuse of Boolean constants
""" """
from typing import Any, List, Set, Tuple, Union from typing import List, Set, Tuple
from slither.core.cfg.node import Node, NodeType from slither.core.cfg.node import Node, NodeType
from slither.core.declarations import Function
from slither.core.declarations.contract import Contract
from slither.core.solidity_types import ElementaryType from slither.core.solidity_types import ElementaryType
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import ( from slither.slithir.operations import (
@ -15,8 +18,6 @@ from slither.slithir.operations import (
Condition, Condition,
) )
from slither.slithir.variables import Constant from slither.slithir.variables import Constant
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.utils.output import Output from slither.utils.output import Output
@ -65,9 +66,7 @@ Other uses (in complex expressions, as conditionals) indicate either an error or
@staticmethod @staticmethod
def _detect_boolean_constant_misuses( def _detect_boolean_constant_misuses(
contract: Contract, contract: Contract,
) -> List[ ) -> List[Tuple[Function, Set[Node]]]: # pylint: disable=too-many-branches
Union[Tuple[FunctionContract, Set[Any]], Tuple[FunctionContract, Set[Node]], Any]
]: # pylint: disable=too-many-branches
""" """
Detects and returns all nodes which misuse a Boolean constant. Detects and returns all nodes which misuse a Boolean constant.
:param contract: Contract to detect assignment within. :param contract: Contract to detect assignment within.
@ -75,7 +74,7 @@ Other uses (in complex expressions, as conditionals) indicate either an error or
""" """
# Create our result set. # Create our result set.
results = [] results: List[Tuple[Function, Set[Node]]] = []
# Loop for each function and modifier. # Loop for each function and modifier.
for function in contract.functions_declared: for function in contract.functions_declared:
@ -112,7 +111,7 @@ Other uses (in complex expressions, as conditionals) indicate either an error or
# Return the resulting set of nodes with improper uses of Boolean constants # Return the resulting set of nodes with improper uses of Boolean constants
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detect Boolean constant misuses Detect Boolean constant misuses
""" """

@ -1,13 +1,14 @@
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall
from slither.analyses.data_dependency.data_dependency import is_tainted from slither.analyses.data_dependency.data_dependency import is_tainted
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall
from slither.utils.output import Output from slither.utils.output import Output
def controlled_delegatecall(function: FunctionContract) -> List[Union[Node, Any]]: def controlled_delegatecall(function: FunctionContract) -> List[Node]:
ret = [] ret = []
for node in function.nodes: for node in function.nodes:
for ir in node.irs: for ir in node.irs:
@ -46,7 +47,7 @@ Bob calls `delegate` and delegates the execution to his malicious contract. As a
WIKI_RECOMMENDATION = "Avoid using `delegatecall`. Use only trusted destinations." WIKI_RECOMMENDATION = "Avoid using `delegatecall`. Use only trusted destinations."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:

@ -1,20 +1,20 @@
""" """
Module detecting deprecated standards. Module detecting deprecated standards.
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple, Union
from slither.core.cfg.node import Node, NodeType from slither.core.cfg.node import Node, NodeType
from slither.core.declarations.contract import Contract
from slither.core.declarations.solidity_variables import ( from slither.core.declarations.solidity_variables import (
SolidityVariableComposed, SolidityVariableComposed,
SolidityFunction, SolidityFunction,
) )
from slither.core.expressions.expression import Expression
from slither.core.variables import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall from slither.slithir.operations import LowLevelCall
from slither.visitors.expression.export_values import ExportValues
from slither.core.declarations.contract import Contract
from slither.core.expressions.binary_operation import BinaryOperation
from slither.core.expressions.call_expression import CallExpression
from slither.core.expressions.member_access import MemberAccess
from slither.utils.output import Output from slither.utils.output import Output
from slither.visitors.expression.export_values import ExportValues
# Reference: https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-111 # Reference: https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-111
@ -79,8 +79,8 @@ contract ContractWithDeprecatedReferences {
DEPRECATED_LOW_LEVEL_CALLS = [("callcode", "callcode", "delegatecall")] DEPRECATED_LOW_LEVEL_CALLS = [("callcode", "callcode", "delegatecall")]
def detect_deprecation_in_expression( def detect_deprecation_in_expression(
self, expression: Union[BinaryOperation, MemberAccess, CallExpression] self, expression: Expression
) -> List[Union[Any, Tuple[str, str, str]]]: ) -> List[Tuple[str, str, str]]:
"""Detects if an expression makes use of any deprecated standards. """Detects if an expression makes use of any deprecated standards.
Returns: Returns:
@ -104,13 +104,13 @@ contract ContractWithDeprecatedReferences {
def detect_deprecated_references_in_node( def detect_deprecated_references_in_node(
self, node: Node self, node: Node
) -> List[Union[Any, Tuple[str, str, str], Tuple[NodeType, str, str]]]: ) -> List[Tuple[Union[str, NodeType], str, str]]:
"""Detects if a node makes use of any deprecated standards. """Detects if a node makes use of any deprecated standards.
Returns: Returns:
list of tuple: (detecting_signature, original_text, recommended_text)""" list of tuple: (detecting_signature, original_text, recommended_text)"""
# Define our results list # Define our results list
results = [] results: List[Tuple[Union[str, NodeType], str, str]] = []
# If this node has an expression, we check the underlying expression. # If this node has an expression, we check the underlying expression.
if node.expression: if node.expression:
@ -127,16 +127,20 @@ contract ContractWithDeprecatedReferences {
self, contract: Contract self, contract: Contract
) -> List[ ) -> List[
Union[ Union[
Any, Tuple[StateVariable, List[Tuple[str, str, str]]],
Tuple[Node, List[Tuple[str, str, str]]], Tuple[Node, List[Tuple[Union[str, NodeType], str, str]]],
Tuple[Node, List[Tuple[NodeType, str, str]]],
] ]
]: ]:
"""Detects the usage of any deprecated built-in symbols. """Detects the usage of any deprecated built-in symbols.
Returns: Returns:
list of tuple: (state_variable | node, (detecting_signature, original_text, recommended_text))""" list of tuple: (state_variable | node, (detecting_signature, original_text, recommended_text))"""
results = [] results: List[
Union[
Tuple[StateVariable, List[Tuple[str, str, str]]],
Tuple[Node, List[Tuple[Union[str, NodeType], str, str]]],
]
] = []
for state_variable in contract.state_variables_declared: for state_variable in contract.state_variables_declared:
if state_variable.expression: if state_variable.expression:
@ -152,22 +156,22 @@ contract ContractWithDeprecatedReferences {
# Loop through each node in this function. # Loop through each node in this function.
for node in function.nodes: for node in function.nodes:
# Detect deprecated references in the node. # Detect deprecated references in the node.
deprecated_results = self.detect_deprecated_references_in_node(node) deprecated_results_node = self.detect_deprecated_references_in_node(node)
# Detect additional deprecated low-level-calls. # Detect additional deprecated low-level-calls.
for ir in node.irs: for ir in node.irs:
if isinstance(ir, LowLevelCall): if isinstance(ir, LowLevelCall):
for dep_llc in self.DEPRECATED_LOW_LEVEL_CALLS: for dep_llc in self.DEPRECATED_LOW_LEVEL_CALLS:
if ir.function_name == dep_llc[0]: if ir.function_name == dep_llc[0]:
deprecated_results.append(dep_llc) deprecated_results_node.append(dep_llc)
# If we have any results from this iteration, add them to our results list. # If we have any results from this iteration, add them to our results list.
if deprecated_results: if deprecated_results_node:
results.append((node, deprecated_results)) results.append((node, deprecated_results_node))
return results return results
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detects if an expression makes use of any deprecated standards. """Detects if an expression makes use of any deprecated standards.
Recursively visit the calls Recursively visit the calls

@ -2,23 +2,18 @@
Module detecting possible loss of precision due to divide before multiple Module detecting possible loss of precision due to divide before multiple
""" """
from collections import defaultdict from collections import defaultdict
from typing import Any, DefaultDict, List, Set, Tuple, Union from typing import Any, DefaultDict, List, Set, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Binary, Assignment, BinaryType, LibraryCall
from slither.slithir.variables import Constant
import slither.slithir.operations.binary
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.slithir.operations.high_level_call import HighLevelCall from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.member import Member from slither.slithir.operations import Binary, Assignment, BinaryType, LibraryCall, Operation
from slither.slithir.operations.return_operation import Return from slither.slithir.variables import Constant
from slither.utils.output import Output from slither.utils.output import Output
def is_division( def is_division(ir: Operation) -> bool:
ir: Union[Member, slither.slithir.operations.binary.Binary, HighLevelCall, Return]
) -> bool:
if isinstance(ir, Binary): if isinstance(ir, Binary):
if ir.type == BinaryType.DIVISION: if ir.type == BinaryType.DIVISION:
return True return True
@ -34,9 +29,7 @@ def is_division(
return False return False
def is_multiplication( def is_multiplication(ir: Operation) -> bool:
ir: Union[Member, slither.slithir.operations.binary.Binary, HighLevelCall, Return]
) -> bool:
if isinstance(ir, Binary): if isinstance(ir, Binary):
if ir.type == BinaryType.MULTIPLICATION: if ir.type == BinaryType.MULTIPLICATION:
return True return True
@ -64,7 +57,9 @@ def is_assert(node: Node) -> bool:
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
def _explore(to_explore: Set[Node], f_results: List[Any], divisions: DefaultDict[Any, Any]) -> None: def _explore(
to_explore: Set[Node], f_results: List[Node], divisions: DefaultDict[Any, Any]
) -> None:
explored = set() explored = set()
while to_explore: # pylint: disable=too-many-nested-blocks while to_explore: # pylint: disable=too-many-nested-blocks
node = to_explore.pop() node = to_explore.pop()
@ -119,7 +114,7 @@ def _explore(to_explore: Set[Node], f_results: List[Any], divisions: DefaultDict
def detect_divide_before_multiply( def detect_divide_before_multiply(
contract: Contract, contract: Contract,
) -> List[Union[Tuple[FunctionContract, List[Node]], Any]]: ) -> List[Tuple[FunctionContract, List[Node]]]:
""" """
Detects and returns all nodes with multiplications of division results. Detects and returns all nodes with multiplications of division results.
:param contract: Contract to detect assignment within. :param contract: Contract to detect assignment within.
@ -185,7 +180,7 @@ In general, it's usually a good idea to re-arrange arithmetic to perform multipl
WIKI_RECOMMENDATION = """Consider ordering multiplication before division.""" WIKI_RECOMMENDATION = """Consider ordering multiplication before division."""
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detect divisions before multiplications Detect divisions before multiplications
""" """

@ -163,7 +163,7 @@ contract Crowdsale{
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
for c in self.compilation_unit.contracts_derived: for c in self.compilation_unit.contracts_derived:

@ -1,15 +1,15 @@
""" """
Detect deletion on structure containing a mapping Detect deletion on structure containing a mapping
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations import Structure from slither.core.declarations import Structure
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.core.solidity_types import MappingType, UserDefinedType from slither.core.solidity_types import MappingType, UserDefinedType
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Delete from slither.slithir.operations import Delete
from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.core.declarations.structure_contract import StructureContract
from slither.utils.output import Output from slither.utils.output import Output
@ -52,13 +52,13 @@ The mapping `balances` is never deleted, so `remove` does not work as intended."
@staticmethod @staticmethod
def detect_mapping_deletion( def detect_mapping_deletion(
contract: Contract, contract: Contract,
) -> List[Union[Any, Tuple[FunctionContract, StructureContract, Node]]]: ) -> List[Tuple[FunctionContract, Structure, Node]]:
"""Detect deletion on structure containing a mapping """Detect deletion on structure containing a mapping
Returns: Returns:
list (function, structure, node) list (function, structure, node)
""" """
ret = [] ret: List[Tuple[FunctionContract, Structure, Node]] = []
# pylint: disable=too-many-nested-blocks # pylint: disable=too-many-nested-blocks
for f in contract.functions: for f in contract.functions:
for node in f.nodes: for node in f.nodes:
@ -73,7 +73,7 @@ The mapping `balances` is never deleted, so `remove` does not work as intended."
ret.append((f, st, node)) ret.append((f, st, node))
return ret return ret
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect mapping deletion """Detect mapping deletion
Returns: Returns:

@ -1,12 +1,13 @@
""" """
Module detecting redundant statements. Module detecting redundant statements.
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import Node, NodeType from slither.core.cfg.node import Node, NodeType
from slither.core.declarations.contract import Contract
from slither.core.expressions.elementary_type_name_expression import ElementaryTypeNameExpression from slither.core.expressions.elementary_type_name_expression import ElementaryTypeNameExpression
from slither.core.expressions.identifier import Identifier from slither.core.expressions.identifier import Identifier
from slither.core.declarations.contract import Contract from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -52,7 +53,7 @@ Each commented line references types/identifiers, but performs no action with th
# This is a disallowed list of tuple (node.type, type(node.expression)) # This is a disallowed list of tuple (node.type, type(node.expression))
REDUNDANT_TOP_LEVEL_EXPRESSIONS = (ElementaryTypeNameExpression, Identifier) REDUNDANT_TOP_LEVEL_EXPRESSIONS = (ElementaryTypeNameExpression, Identifier)
def detect_redundant_statements_contract(self, contract: Contract) -> List[Union[Any, Node]]: def detect_redundant_statements_contract(self, contract: Contract) -> List[Node]:
"""Detects the usage of redundant statements in a contract. """Detects the usage of redundant statements in a contract.
Returns: Returns:
@ -72,7 +73,7 @@ Each commented line references types/identifiers, but performs no action with th
return results return results
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect redundant statements """Detect redundant statements
Recursively visit the calls Recursively visit the calls

@ -3,14 +3,14 @@ Module detecting numbers with too many digits.
""" """
import re import re
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.variables import Constant
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.variables import Constant
from slither.utils.output import Output from slither.utils.output import Output
_HEX_ADDRESS_REGEXP = re.compile("(0[xX])?[0-9a-fA-F]{40}") _HEX_ADDRESS_REGEXP = re.compile("(0[xX])?[0-9a-fA-F]{40}")
@ -62,7 +62,7 @@ Use:
# endregion wiki_recommendation # endregion wiki_recommendation
@staticmethod @staticmethod
def _detect_too_many_digits(f: FunctionContract) -> List[Union[Any, Node]]: def _detect_too_many_digits(f: FunctionContract) -> List[Node]:
ret = [] ret = []
for node in f.nodes: for node in f.nodes:
# each node contains a list of IR instruction # each node contains a list of IR instruction
@ -78,7 +78,7 @@ Use:
ret.append(node) ret.append(node)
return ret return ret
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
# iterate over all contracts # iterate over all contracts

@ -1,11 +1,12 @@
""" """
Module detecting usage of `tx.origin` in a conditional node Module detecting usage of `tx.origin` in a conditional node
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -56,9 +57,7 @@ Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls `
) )
return False return False
def detect_tx_origin( def detect_tx_origin(self, contract: Contract) -> List[Tuple[FunctionContract, List[Node]]]:
self, contract: Contract
) -> List[Union[Tuple[FunctionContract, List[Node]], Any]]:
ret = [] ret = []
for f in contract.functions: for f in contract.functions:
@ -73,7 +72,7 @@ Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls `
ret.append((f, bad_tx_nodes)) ret.append((f, bad_tx_nodes))
return ret return ret
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect the functions that use tx.origin in a conditional node""" """Detect the functions that use tx.origin in a conditional node"""
results = [] results = []
for c in self.contracts: for c in self.contracts:

@ -1,14 +1,15 @@
""" """
Module detecting tautologies and contradictions based on types in comparison operations over integers Module detecting tautologies and contradictions based on types in comparison operations over integers
""" """
from typing import Any, List, Set, Tuple, Union from typing import List, Set, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations import Function
from slither.core.declarations.contract import Contract
from slither.core.solidity_types.elementary_type import Int, Uint
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Binary, BinaryType from slither.slithir.operations import Binary, BinaryType
from slither.slithir.variables import Constant from slither.slithir.variables import Constant
from slither.core.solidity_types.elementary_type import Int, Uint
from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.utils.output import Output from slither.utils.output import Output
@ -114,9 +115,7 @@ contract A {
BinaryType.LESS_EQUAL: BinaryType.GREATER_EQUAL, BinaryType.LESS_EQUAL: BinaryType.GREATER_EQUAL,
} }
def detect_type_based_tautologies( def detect_type_based_tautologies(self, contract: Contract) -> List[Tuple[Function, Set[Node]]]:
self, contract: Contract
) -> List[Union[Any, Tuple[FunctionContract, Set[Node]], Tuple[FunctionContract, Set[Any]]]]:
""" """
Detects and returns all nodes with tautology/contradiction comparisons (based on type alone). Detects and returns all nodes with tautology/contradiction comparisons (based on type alone).
:param contract: Contract to detect assignment within. :param contract: Contract to detect assignment within.
@ -124,7 +123,7 @@ contract A {
""" """
# Create our result set. # Create our result set.
results = [] results: List[Tuple[Function, Set[Node]]] = []
allInts = Int + Uint allInts = Int + Uint
# Loop for each function and modifier. # Loop for each function and modifier.
@ -157,7 +156,7 @@ contract A {
# Return the resulting set of nodes with tautologies and contradictions # Return the resulting set of nodes with tautologies and contradictions
return results return results
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
""" """
Detect tautological (or contradictory) comparisons Detect tautological (or contradictory) comparisons
""" """

@ -1,12 +1,13 @@
""" """
Module detecting the incorrect use of unary expressions Module detecting the incorrect use of unary expressions
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.visitors.expression.expression import ExpressionVisitor
from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation
from slither.core.expressions.assignment_operation import AssignmentOperation from slither.core.expressions.assignment_operation import AssignmentOperation
from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
from slither.visitors.expression.expression import ExpressionVisitor
class InvalidUnaryExpressionDetector(ExpressionVisitor): class InvalidUnaryExpressionDetector(ExpressionVisitor):
@ -62,7 +63,7 @@ contract Bug{
WIKI_RECOMMENDATION = "Remove the unary expression." WIKI_RECOMMENDATION = "Remove the unary expression."
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
""" """
Detect the incorrect use of unary expressions Detect the incorrect use of unary expressions
""" """

@ -1,4 +1,4 @@
from typing import Any, Union, List from typing import List
from slither.core.declarations import SolidityFunction, Function from slither.core.declarations import SolidityFunction, Function
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
@ -88,7 +88,7 @@ Buggy is an upgradeable contract. Anyone can call initialize on the logic contra
"""Add a constructor to ensure `initialize` cannot be called on the logic contract.""" """Add a constructor to ensure `initialize` cannot be called on the logic contract."""
) )
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
results = [] results = []
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:

@ -1,4 +1,4 @@
from typing import Any, Union, List, Set, Tuple, Dict from typing import List, Set, Tuple, Dict
from slither.core.cfg.node import Node, NodeType from slither.core.cfg.node import Node, NodeType
from slither.core.solidity_types import ElementaryType from slither.core.solidity_types import ElementaryType
@ -122,7 +122,7 @@ class WriteAfterWrite(AbstractDetector):
WIKI_RECOMMENDATION = """Fix or remove the writes.""" WIKI_RECOMMENDATION = """Fix or remove the writes."""
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
results = [] results = []
for contract in self.compilation_unit.contracts_derived: for contract in self.compilation_unit.contracts_derived:

@ -1,16 +1,17 @@
""" """
Module detecting state variables initializing from an immediate function call (prior to constructor run). Module detecting state variables initializing from an immediate function call (prior to constructor run).
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.visitors.expression.export_values import ExportValues from slither.core.declarations.contract import Contract
from slither.core.declarations.function import Function from slither.core.declarations.function import Function
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.core.declarations.contract import Contract from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
from slither.visitors.expression.export_values import ExportValues
def detect_function_init_state_vars(contract: Contract) -> List[Union[StateVariable, Any]]: def detect_function_init_state_vars(contract: Contract) -> List[StateVariable]:
""" """
Detect any state variables that are initialized from an immediate function call (prior to constructor run). Detect any state variables that are initialized from an immediate function call (prior to constructor run).
:param contract: The contract to detect state variable definitions for. :param contract: The contract to detect state variable definitions for.
@ -89,7 +90,7 @@ Special care must be taken when initializing state variables from an immediate f
WIKI_RECOMMENDATION = "Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead." WIKI_RECOMMENDATION = "Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detect state variables defined from an immediate function call (pre-contract deployment). Detect state variables defined from an immediate function call (pre-contract deployment).

@ -1,12 +1,13 @@
""" """
Module detecting any path leading to usage of a local variable before it is declared. Module detecting any path leading to usage of a local variable before it is declared.
""" """
from typing import Any, List, Set, Tuple, Union from typing import List, Set, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations import Function
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable import LocalVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -56,7 +57,7 @@ Additionally, the for-loop uses the variable `max`, which is declared in a previ
def detect_predeclared_local_usage( def detect_predeclared_local_usage(
self, self,
node: Node, node: Node,
results: List[Union[Tuple[Node, LocalVariable], Any]], results: List[Tuple[Node, LocalVariable]],
already_declared: Set[LocalVariable], already_declared: Set[LocalVariable],
visited: Set[Node], visited: Set[Node],
) -> None: ) -> None:
@ -100,7 +101,7 @@ Additionally, the for-loop uses the variable `max`, which is declared in a previ
def detect_predeclared_in_contract( def detect_predeclared_in_contract(
self, contract: Contract self, contract: Contract
) -> List[Union[Any, Tuple[FunctionContract, List[Tuple[Node, LocalVariable]]]]]: ) -> List[Tuple[Function, List[Tuple[Node, LocalVariable]]]]:
""" """
Detects and returns all nodes in a contract which use a variable before it is declared. Detects and returns all nodes in a contract which use a variable before it is declared.
:param contract: Contract to detect pre-declaration usage of locals within. :param contract: Contract to detect pre-declaration usage of locals within.
@ -108,11 +109,11 @@ Additionally, the for-loop uses the variable `max`, which is declared in a previ
""" """
# Create our result set. # Create our result set.
results = [] results: List[Tuple[Function, List[Tuple[Node, LocalVariable]]]] = []
# Loop for each function and modifier's nodes and analyze for predeclared local variable usage. # Loop for each function and modifier's nodes and analyze for predeclared local variable usage.
for function in contract.functions_and_modifiers_declared: for function in contract.functions_and_modifiers_declared:
predeclared_usage = [] predeclared_usage: List[Tuple[Node, LocalVariable]] = []
if function.nodes: if function.nodes:
self.detect_predeclared_local_usage( self.detect_predeclared_local_usage(
function.nodes[0], function.nodes[0],
@ -126,7 +127,7 @@ Additionally, the for-loop uses the variable `max`, which is declared in a previ
# Return the resulting set of nodes which set array length. # Return the resulting set of nodes which set array length.
return results return results
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
""" """
Detect usage of a local variable before it is declared. Detect usage of a local variable before it is declared.
""" """

@ -3,10 +3,11 @@ Check for state variables too similar
Do not check contract inheritance Do not check contract inheritance
""" """
import difflib import difflib
from typing import Any, List, Set, Tuple, Union from typing import List, Set, Tuple
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations.contract import Contract from slither.core.declarations.contract import Contract
from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable import LocalVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -72,7 +73,7 @@ class SimilarVarsDetection(AbstractDetector):
return set(ret) return set(ret)
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect similar variables name """Detect similar variables name
Returns: Returns:

@ -4,11 +4,11 @@
Recursively explore the CFG to only report uninitialized local variables that are Recursively explore the CFG to only report uninitialized local variables that are
read before being written read before being written
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -42,7 +42,7 @@ Bob calls `transfer`. As a result, all Ether is sent to the address `0x0` and is
key = "UNINITIALIZEDLOCAL" key = "UNINITIALIZEDLOCAL"
def _detect_uninitialized( def _detect_uninitialized(
self, function: FunctionContract, node: Node, visited: List[Union[Any, Node]] self, function: FunctionContract, node: Node, visited: List[Node]
) -> None: ) -> None:
if node in visited: if node in visited:
return return
@ -79,7 +79,7 @@ Bob calls `transfer`. As a result, all Ether is sent to the address `0x0` and is
for son in node.sons: for son in node.sons:
self._detect_uninitialized(function, son, visited) self._detect_uninitialized(function, son, visited)
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect uninitialized local variables """Detect uninitialized local variables
Recursively visit the calls Recursively visit the calls

@ -8,13 +8,15 @@
Only analyze "leaf" contracts (contracts that are not inherited by another contract) Only analyze "leaf" contracts (contracts that are not inherited by another contract)
""" """
from typing import Any, List, Tuple, Union from typing import List, Tuple
from slither.core.declarations import Function
from slither.core.declarations.contract import Contract
from slither.core.variables import Variable
from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import InternalCall, LibraryCall from slither.slithir.operations import InternalCall, LibraryCall
from slither.slithir.variables import ReferenceVariable from slither.slithir.variables import ReferenceVariable
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.core.variables.state_variable import StateVariable
from slither.utils.output import Output from slither.utils.output import Output
@ -55,7 +57,7 @@ Initialize all the variables. If a variable is meant to be initialized to zero,
# endregion wiki_recommendation # endregion wiki_recommendation
@staticmethod @staticmethod
def _written_variables(contract: Contract) -> List[Union[Any, StateVariable]]: def _written_variables(contract: Contract) -> List[StateVariable]:
ret = [] ret = []
# pylint: disable=too-many-nested-blocks # pylint: disable=too-many-nested-blocks
for f in contract.all_functions_called + contract.modifiers: for f in contract.all_functions_called + contract.modifiers:
@ -92,8 +94,8 @@ Initialize all the variables. If a variable is meant to be initialized to zero,
self.__variables_written_in_proxy = list({v.name for v in variables_written_in_proxy}) self.__variables_written_in_proxy = list({v.name for v in variables_written_in_proxy})
return self.__variables_written_in_proxy return self.__variables_written_in_proxy
def _written_variables_in_proxy(self, contract: Contract) -> List[Any]: def _written_variables_in_proxy(self, contract: Contract) -> List[StateVariable]:
variables = [] variables: List[StateVariable] = []
if contract.is_upgradeable: if contract.is_upgradeable:
variables_name_written_in_proxy = self._variable_written_in_proxy() variables_name_written_in_proxy = self._variable_written_in_proxy()
if variables_name_written_in_proxy: if variables_name_written_in_proxy:
@ -101,20 +103,20 @@ Initialize all the variables. If a variable is meant to be initialized to zero,
contract.get_state_variable_from_name(v) contract.get_state_variable_from_name(v)
for v in variables_name_written_in_proxy for v in variables_name_written_in_proxy
] ]
variables_in_contract = [v for v in variables_in_contract if v] variables += [v for v in variables_in_contract if v]
variables += variables_in_contract
return list(set(variables)) return list(set(variables))
@staticmethod @staticmethod
def _read_variables(contract: Contract) -> List[Union[Any, StateVariable]]: def _read_variables(contract: Contract) -> List[StateVariable]:
ret = [] ret = []
for f in contract.all_functions_called + contract.modifiers: for f in contract.all_functions_called:
ret += f.state_variables_read if isinstance(f, Function):
ret += f.state_variables_read
for m in contract.modifiers:
ret += m.state_variables_read
return ret return ret
def _detect_uninitialized( def _detect_uninitialized(self, contract: Contract) -> List[Tuple[Variable, List[Function]]]:
self, contract: Contract
) -> List[Union[Any, Tuple[StateVariable, List[FunctionContract]]]]:
written_variables = self._written_variables(contract) written_variables = self._written_variables(contract)
written_variables += self._written_variables_in_proxy(contract) written_variables += self._written_variables_in_proxy(contract)
read_variables = self._read_variables(contract) read_variables = self._read_variables(contract)
@ -126,7 +128,7 @@ Initialize all the variables. If a variable is meant to be initialized to zero,
and variable in read_variables and variable in read_variables
] ]
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect uninitialized state variables """Detect uninitialized state variables
Recursively visit the calls Recursively visit the calls

@ -4,10 +4,11 @@
Recursively explore the CFG to only report uninitialized storage variables that are Recursively explore the CFG to only report uninitialized storage variables that are
written before being read written before being read
""" """
from typing import Any, List, Union from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output from slither.utils.output import Output
@ -49,7 +50,7 @@ Bob calls `func`. As a result, `owner` is overridden to `0`.
key = "UNINITIALIZEDSTORAGE" key = "UNINITIALIZEDSTORAGE"
def _detect_uninitialized( def _detect_uninitialized(
self, function: FunctionContract, node: Node, visited: List[Union[Any, Node]] self, function: FunctionContract, node: Node, visited: List[Node]
) -> None: ) -> None:
if node in visited: if node in visited:
return return
@ -86,7 +87,7 @@ Bob calls `func`. As a result, `owner` is overridden to `0`.
for son in node.sons: for son in node.sons:
self._detect_uninitialized(function, son, visited) self._detect_uninitialized(function, son, visited)
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
"""Detect uninitialized storage variables """Detect uninitialized storage variables
Recursively visit the calls Recursively visit the calls

@ -1,15 +1,16 @@
""" """
Module detecting unused state variables Module detecting unused state variables
""" """
from typing import Any, List, Optional, Union from typing import List, Optional
from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.compilation_unit import SlitherCompilationUnit
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.core.declarations.contract import Contract
from slither.core.solidity_types import ArrayType from slither.core.solidity_types import ArrayType
from slither.visitors.expression.export_values import ExportValues
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.formatters.variables.unused_state_variables import custom_format from slither.formatters.variables.unused_state_variables import custom_format
from slither.core.declarations.contract import Contract
from slither.utils.output import Output from slither.utils.output import Output
from slither.visitors.expression.export_values import ExportValues
def detect_unused(contract: Contract) -> Optional[List[StateVariable]]: def detect_unused(contract: Contract) -> Optional[List[StateVariable]]:
@ -57,7 +58,7 @@ class UnusedStateVars(AbstractDetector):
WIKI_EXPLOIT_SCENARIO = "" WIKI_EXPLOIT_SCENARIO = ""
WIKI_RECOMMENDATION = "Remove unused state variables." WIKI_RECOMMENDATION = "Remove unused state variables."
def _detect(self) -> List[Union[Output, Any]]: def _detect(self) -> List[Output]:
"""Detect unused state variables""" """Detect unused state variables"""
results = [] results = []
for c in self.compilation_unit.contracts_derived: for c in self.compilation_unit.contracts_derived:

@ -1,4 +1,4 @@
from typing import Any, Union, List from typing import List
from slither.core.cfg.node import Node from slither.core.cfg.node import Node
from slither.core.declarations import Function, SolidityVariable from slither.core.declarations import Function, SolidityVariable
@ -30,7 +30,7 @@ contract C {
WIKI_RECOMMENDATION = "Read the variable directly from storage instead of calling the contract." WIKI_RECOMMENDATION = "Read the variable directly from storage instead of calling the contract."
def _detect(self) -> List[Union[Any, Output]]: def _detect(self) -> List[Output]:
results = [] results = []
for c in self.contracts: for c in self.contracts:
for func in c.functions: for func in c.functions:

Loading…
Cancel
Save