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.slithir.operations import Binary, BinaryType
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."
def _check_function(self, f: FunctionContract) -> List[Union[Output, Any]]:
def _check_function(self, f: FunctionContract) -> List[Output]:
results = []
for node in f.nodes:
@ -55,7 +55,7 @@ The shift statement will right-shift the constant 8 by `a` bits"""
results.append(json)
return results
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
results = []
for c in self.contracts:
for f in c.functions:

@ -1,7 +1,8 @@
"""
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.formatters.attributes.constant_pragma import custom_format
from slither.utils.output import Output
@ -23,7 +24,7 @@ class ConstantPragma(AbstractDetector):
WIKI_DESCRIPTION = "Detect whether different Solidity versions are used."
WIKI_RECOMMENDATION = "Use one Solidity version."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
results = []
pragma = self.compilation_unit.pragma_directives
versions = [p.version for p in pragma if p.is_solidity_version]

@ -3,12 +3,12 @@
"""
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.formatters.attributes.incorrect_solc import custom_format
from slither.utils.output import Output
# group:
# 0: ^ > >= < <= (optional)
# 1: ' ' (optional)
@ -120,7 +120,7 @@ Consider using the latest version of Solidity for testing."""
return self._check_version(version_left)
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.
:return: Returns the relevant JSON data for the findings.

@ -1,7 +1,9 @@
"""
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.slithir.operations import (
HighLevelCall,
@ -12,7 +14,6 @@ from slither.slithir.operations import (
LibraryCall,
InternalCall,
)
from slither.core.declarations.contract import Contract
from slither.utils.output import Output
@ -75,7 +76,7 @@ Every Ether sent to `Locked` will be lost."""
return True
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
results = []
for contract in self.compilation_unit.contracts_derived:

@ -4,7 +4,7 @@ Module detecting unimplemented interfaces
Collect all the 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.core.declarations.contract import Contract
from slither.utils.output import Output
@ -45,8 +45,8 @@ contract Something {
@staticmethod
def detect_unimplemented_interface(
contract: Contract, interfaces: List[Union[Any, Contract]]
) -> List[Union[Any, Contract]]:
contract: Contract, interfaces: List[Contract]
) -> List[Contract]:
"""
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
@ -54,7 +54,7 @@ contract Something {
: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}
if not sigs_contract:
@ -115,7 +115,7 @@ contract Something {
return intended_interfaces
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detect unimplemented interfaces
Returns:
list: {'contract'}

@ -1,7 +1,7 @@
"""
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.core.solidity_types.array_type import ArrayType
from slither.core.variables.state_variable import StateVariable
@ -93,7 +93,6 @@ As a result, Bob's usage of the contract is incorrect."""
Union[
Tuple[Node, StateVariable, 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))
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.
: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
"""
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 (
AbstractDetector,
DetectorClassification,
@ -9,9 +13,10 @@ from slither.detectors.abstract_detector import (
)
from slither.slithir.operations import TypeConversion
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
Args:
contract (Contract)
@ -61,7 +66,7 @@ Attackers can trigger unexpected behaviour by calling `bug(1)`."""
VULNERABLE_SOLC_VERSIONS = make_solc_versions(4, 0, 4)
def _detect(self):
def _detect(self) -> List[Output]:
"""Detect dangerous conversion to enum"""
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.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>(...)`."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""
Detect multiple constructor schemes in the same contract
: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
"""
from typing import List
from slither.detectors.abstract_detector import (
AbstractDetector,
@ -14,6 +15,7 @@ from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations.assignment import Assignment
from slither.slithir.operations.init_array import InitArray
from slither.utils.output import Output
class StorageSignedIntegerArray(AbstractDetector):
@ -108,7 +110,7 @@ contract A {
# Return the resulting set of tuples
return results
def _detect(self):
def _detect(self) -> List[Output]:
"""
Detect storage signed integer array init/assignment
"""

@ -2,10 +2,11 @@
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)
"""
from typing import Any, List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import List, Tuple
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output
@ -40,9 +41,7 @@ contract Token{
)
@staticmethod
def incorrect_erc20_interface(
signature: Union[Tuple[str, List[str], List[Any]], Tuple[str, List[Any], List[Any]]]
) -> bool:
def incorrect_erc20_interface(signature: Tuple[str, List[str], List[str]]) -> bool:
(name, parameters, returnVars) = signature
if name == "transfer" and parameters == ["address", "uint256"] and returnVars != ["bool"]:
@ -74,7 +73,7 @@ contract Token{
return False
@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
Returns:
@ -99,7 +98,7 @@ contract Token{
return functions
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""Detect incorrect erc20 interface
Returns:

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

@ -75,7 +75,7 @@ Failure to include these keywords will exclude the parameter data in the transac
# Return the results.
return results
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""
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.utils.output import Output
@ -19,7 +20,7 @@ class Backdoor(AbstractDetector):
WIKI_EXPLOIT_SCENARIO = ".."
WIKI_RECOMMENDATION = ".."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
results = []
for contract in self.compilation_unit.contracts_derived:

@ -1,7 +1,7 @@
"""
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.detectors.abstract_detector import AbstractDetector, DetectorClassification
@ -35,7 +35,7 @@ contract Contract{
WIKI_RECOMMENDATION = "Remove unused functions."
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
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
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.core.cfg.node import Node, NodeType
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."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
results = []
for c in self.contracts:
for mod in c.modifiers:

@ -1,7 +1,7 @@
"""
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.solidity_types.elementary_type import ElementaryType
@ -40,7 +40,7 @@ contract Contract{
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()")
for contract in self.compilation_unit.contracts_derived:
if contract.is_erc20():

@ -3,7 +3,7 @@ Module detecting suicidal contract
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.detectors.abstract_detector import AbstractDetector, DetectorClassification
@ -71,7 +71,7 @@ contract Buggy{
results.append(res)
return results
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""Detect the suicidal functions"""
results = []
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
"""
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.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output
@ -64,14 +64,14 @@ Bob calls `kill` and destructs the contract."""
return True
def detect_suicidal(self, contract: Contract) -> List[Union[Any, FunctionContract]]:
def detect_suicidal(self, contract: Contract) -> List[FunctionContract]:
ret = []
for f in contract.functions_declared:
if self.detect_suicidal_func(f):
ret.append(f)
return ret
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detect the suicidal functions"""
results = []
for c in self.contracts:

@ -7,7 +7,7 @@ Check for unimplemented functions that are never implemented
Consider public state variables as implemented functions
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.core.declarations.contract import Contract
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)
return unimplemented
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""Detect unimplemented functions
Recursively visit the calls

@ -1,5 +1,5 @@
import re
from typing import Any, List, Union
from typing import List
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.formatters.naming_convention.naming_convention import custom_format
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
# pylint: disable=too-many-branches,too-many-statements
def _detect(
self,
) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
results = []
for contract in self.contracts:

@ -2,7 +2,7 @@
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.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_RECOMMENDATION = "Avoid relying on `block.timestamp`."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
""""""
results = []

@ -1,7 +1,7 @@
"""
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.slithir.operations import LowLevelCall
from slither.core.cfg.node import Node
@ -37,7 +37,7 @@ class LowLevelCalls(AbstractDetector):
def detect_low_level_calls(
self, contract: Contract
) -> List[Union[Any, Tuple[FunctionContract, List[Node]]]]:
) -> List[Tuple[FunctionContract, List[Node]]]:
ret = []
for f in [f for f in contract.functions if contract == f.contract_declarer]:
nodes = f.nodes
@ -46,7 +46,7 @@ class LowLevelCalls(AbstractDetector):
ret.append((f, assembly_nodes))
return ret
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detect the functions that use low level calls"""
results = []
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
"""
from typing import Any, List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import List, Tuple
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.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
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.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.event_call import EventCall
from slither.utils.output import Output
@ -53,7 +54,7 @@ contract C {
@staticmethod
def _detect_missing_events(
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
:param contract: The contract to check
@ -88,7 +89,7 @@ contract C {
results.append((function, nodes))
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
Returns:
list: {'(function, node)'}

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

@ -3,17 +3,18 @@ Module detecting missing zero address validation
"""
from collections import defaultdict
from typing import Any, DefaultDict, List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import DefaultDict, List, Tuple, Union
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.declarations.contract import Contract
from slither.core.declarations.function import ModifierStatements
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.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
@ -53,7 +54,7 @@ Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownershi
WIKI_RECOMMENDATION = "Check that the address is not zero."
def _zero_address_validation_in_modifier(
self, var: LocalVariable, modifier_exprs: List[Union[ModifierStatements, Any]]
self, var: LocalVariable, modifier_exprs: List[ModifierStatements]
) -> bool:
for mod in modifier_exprs:
for node in mod.nodes:
@ -71,7 +72,7 @@ Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownershi
return False
def _zero_address_validation(
self, var: LocalVariable, node: Node, explored: List[Union[Any, Node]]
self, var: LocalVariable, node: Node, explored: List[Node]
) -> bool:
"""
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(
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.
: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))
return results
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""Detect if addresses are zero address validated before use.
Returns:
list: {'(function, node)'}

@ -1,13 +1,14 @@
"""
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.detectors.abstract_detector import AbstractDetector, DetectorClassification
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.utils.output import Output
@ -56,7 +57,7 @@ contract MyConc{
def detect_unused_return_values(
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
Args:
@ -79,7 +80,7 @@ contract MyConc{
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"""
results = []
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.slithir.operations import Nop
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."""
# endregion wiki_exploit_scenario
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
""""""
results = []
for c in self.contracts:

@ -5,7 +5,7 @@
Iterate over all the nodes of the graph until reaching a fixpoint
"""
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.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
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()

@ -5,12 +5,12 @@
Iterate over all the nodes of the graph until reaching a fixpoint
"""
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.reentrancy.reentrancy import Reentrancy, to_hashable
from slither.utils.output import Output
FindingKey = namedtuple("FindingKey", ["function", "calls", "send_eth"])
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
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()

@ -5,15 +5,16 @@
Iterate over all the nodes of the graph until reaching a fixpoint
"""
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.detectors.abstract_detector import DetectorClassification
from slither.slithir.operations import Send, Transfer, EventCall
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.member import Member
from slither.slithir.operations.return_operation import Return
from slither.utils.output import Output
FindingKey = namedtuple("FindingKey", ["function", "calls", "send_eth"])
FindingValue = namedtuple("FindingValue", ["variable", "node", "nodes"])
@ -63,8 +64,8 @@ Only report reentrancy that is based on `transfer` or `send`."""
STANDARD_JSON = False
def find_reentrancies(self) -> DefaultDict[Any, Any]:
result = defaultdict(set)
def find_reentrancies(self) -> DefaultDict[FindingKey, Set[FindingValue]]:
result: DefaultDict[FindingKey, Set[FindingValue]] = defaultdict(set)
for contract in self.contracts:
for f in contract.functions_and_modifiers_declared:
for node in f.nodes:
@ -101,7 +102,7 @@ Only report reentrancy that is based on `transfer` or `send`."""
result[finding_key] |= finding_vars
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()

@ -6,6 +6,7 @@ from slither.core.cfg.node import Node
from slither.core.declarations import Function, Contract, SolidityVariableComposed
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall, HighLevelCall
from slither.utils.output import Output
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."""
# endregion wiki_recommendation
def _detect(self):
def _detect(self) -> List[Output]:
results = []
for contract in self.compilation_unit.contracts_derived:
vulns = _detect_token_reentrant(contract)

@ -1,12 +1,15 @@
"""
Module detecting reserved keyword shadowing
"""
from typing import Any, List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import List, Tuple, Union, Optional
from slither.core.declarations import Function, Event
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.core.declarations.modifier import Modifier
from slither.core.variables import Variable
from slither.core.variables.local_variable import LocalVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output
@ -119,7 +122,7 @@ contract Bug {
"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.
Returns:
@ -129,7 +132,7 @@ contract Bug {
def detect_builtin_shadowing_locals(
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.
Any such items are returned in a list.
@ -142,14 +145,16 @@ contract Bug {
results.append((self.SHADOWING_LOCAL_VARIABLE, local))
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
symbols. Any such definitions are returned in a list.
Returns:
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.
for function in contract.functions_declared:
@ -171,7 +176,7 @@ contract Bug {
return result
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detect shadowing of built-in symbols
Recursively visit the calls

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

@ -2,16 +2,16 @@
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.variables.state_variable import StateVariable
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.utils.output import Output
def detect_shadowing(contract: Contract) -> List[Union[List[StateVariable], Any]]:
def detect_shadowing(contract: Contract) -> List[List[StateVariable]]:
ret = []
variables_fathers = []
for father in contract.inheritance:
@ -74,7 +74,7 @@ contract DerivedContract is BaseContract{
WIKI_RECOMMENDATION = "Remove the state variable shadowing."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""Detect shadowing
Recursively visit the calls

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

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

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

@ -1,18 +1,19 @@
"""
Module detecting state changes in assert calls
"""
from typing import Any, List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations.internal_call import InternalCall
from typing import List, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract
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
def detect_assert_state_change(
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
: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."""
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""
Detect assert calls that change state from within the invariant
"""

@ -1,16 +1,17 @@
"""
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.slithir.operations import (
Binary,
BinaryType,
)
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
@ -50,10 +51,10 @@ Boolean constants can be used directly and do not need to be compare to `true` o
@staticmethod
def _detect_boolean_equality(
contract: Contract,
) -> List[Union[Tuple[FunctionContract, Set[Any]], Tuple[FunctionContract, Set[Node]], Any]]:
) -> List[Tuple[Function, Set[Node]]]:
# Create our result set.
results = []
results: List[Tuple[Function, Set[Node]]] = []
# Loop for each function and modifier.
# 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 results
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""
Detect Boolean constant misuses
"""

@ -1,8 +1,11 @@
"""
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.declarations import Function
from slither.core.declarations.contract import Contract
from slither.core.solidity_types import ElementaryType
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import (
@ -15,8 +18,6 @@ from slither.slithir.operations import (
Condition,
)
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
@ -65,9 +66,7 @@ Other uses (in complex expressions, as conditionals) indicate either an error or
@staticmethod
def _detect_boolean_constant_misuses(
contract: Contract,
) -> List[
Union[Tuple[FunctionContract, Set[Any]], Tuple[FunctionContract, Set[Node]], Any]
]: # pylint: disable=too-many-branches
) -> List[Tuple[Function, Set[Node]]]: # pylint: disable=too-many-branches
"""
Detects and returns all nodes which misuse a Boolean constant.
: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.
results = []
results: List[Tuple[Function, Set[Node]]] = []
# Loop for each function and modifier.
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 results
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""
Detect Boolean constant misuses
"""

@ -1,13 +1,14 @@
from typing import Any, List, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall
from typing import List
from slither.analyses.data_dependency.data_dependency import is_tainted
from slither.core.cfg.node import Node
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
def controlled_delegatecall(function: FunctionContract) -> List[Union[Node, Any]]:
def controlled_delegatecall(function: FunctionContract) -> List[Node]:
ret = []
for node in function.nodes:
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."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
results = []
for contract in self.compilation_unit.contracts_derived:

@ -1,20 +1,20 @@
"""
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.declarations.contract import Contract
from slither.core.declarations.solidity_variables import (
SolidityVariableComposed,
SolidityFunction,
)
from slither.core.expressions.expression import Expression
from slither.core.variables import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
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.visitors.expression.export_values import ExportValues
# Reference: https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-111
@ -79,8 +79,8 @@ contract ContractWithDeprecatedReferences {
DEPRECATED_LOW_LEVEL_CALLS = [("callcode", "callcode", "delegatecall")]
def detect_deprecation_in_expression(
self, expression: Union[BinaryOperation, MemberAccess, CallExpression]
) -> List[Union[Any, Tuple[str, str, str]]]:
self, expression: Expression
) -> List[Tuple[str, str, str]]:
"""Detects if an expression makes use of any deprecated standards.
Returns:
@ -104,13 +104,13 @@ contract ContractWithDeprecatedReferences {
def detect_deprecated_references_in_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.
Returns:
list of tuple: (detecting_signature, original_text, recommended_text)"""
# 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 node.expression:
@ -127,16 +127,20 @@ contract ContractWithDeprecatedReferences {
self, contract: Contract
) -> List[
Union[
Any,
Tuple[Node, List[Tuple[str, str, str]]],
Tuple[Node, List[Tuple[NodeType, str, str]]],
Tuple[StateVariable, List[Tuple[str, str, str]]],
Tuple[Node, List[Tuple[Union[str, NodeType], str, str]]],
]
]:
"""Detects the usage of any deprecated built-in symbols.
Returns:
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:
if state_variable.expression:
@ -152,22 +156,22 @@ contract ContractWithDeprecatedReferences {
# Loop through each node in this function.
for node in function.nodes:
# 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.
for ir in node.irs:
if isinstance(ir, LowLevelCall):
for dep_llc in self.DEPRECATED_LOW_LEVEL_CALLS:
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 deprecated_results:
results.append((node, deprecated_results))
if deprecated_results_node:
results.append((node, deprecated_results_node))
return results
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detects if an expression makes use of any deprecated standards.
Recursively visit the calls

@ -2,23 +2,18 @@
Module detecting possible loss of precision due to divide before multiple
"""
from collections import defaultdict
from typing import Any, DefaultDict, List, Set, Tuple, Union
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 typing import Any, DefaultDict, List, Set, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.slithir.operations.high_level_call import HighLevelCall
from slither.slithir.operations.member import Member
from slither.slithir.operations.return_operation import Return
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import Binary, Assignment, BinaryType, LibraryCall, Operation
from slither.slithir.variables import Constant
from slither.utils.output import Output
def is_division(
ir: Union[Member, slither.slithir.operations.binary.Binary, HighLevelCall, Return]
) -> bool:
def is_division(ir: Operation) -> bool:
if isinstance(ir, Binary):
if ir.type == BinaryType.DIVISION:
return True
@ -34,9 +29,7 @@ def is_division(
return False
def is_multiplication(
ir: Union[Member, slither.slithir.operations.binary.Binary, HighLevelCall, Return]
) -> bool:
def is_multiplication(ir: Operation) -> bool:
if isinstance(ir, Binary):
if ir.type == BinaryType.MULTIPLICATION:
return True
@ -64,7 +57,9 @@ def is_assert(node: Node) -> bool:
# 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()
while to_explore: # pylint: disable=too-many-nested-blocks
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(
contract: Contract,
) -> List[Union[Tuple[FunctionContract, List[Node]], Any]]:
) -> List[Tuple[FunctionContract, List[Node]]]:
"""
Detects and returns all nodes with multiplications of division results.
: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."""
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""
Detect divisions before multiplications
"""

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

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

@ -1,12 +1,13 @@
"""
Module detecting redundant statements.
"""
from typing import Any, List, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import List
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.identifier import Identifier
from slither.core.declarations.contract import Contract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
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))
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.
Returns:
@ -72,7 +73,7 @@ Each commented line references types/identifiers, but performs no action with th
return results
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detect redundant statements
Recursively visit the calls

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

@ -1,11 +1,12 @@
"""
Module detecting usage of `tx.origin` in a conditional node
"""
from typing import Any, List, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import List, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract
from slither.core.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
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
def detect_tx_origin(
self, contract: Contract
) -> List[Union[Tuple[FunctionContract, List[Node]], Any]]:
def detect_tx_origin(self, contract: Contract) -> List[Tuple[FunctionContract, List[Node]]]:
ret = []
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))
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"""
results = []
for c in self.contracts:

@ -1,14 +1,15 @@
"""
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.slithir.operations import Binary, BinaryType
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
@ -114,9 +115,7 @@ contract A {
BinaryType.LESS_EQUAL: BinaryType.GREATER_EQUAL,
}
def detect_type_based_tautologies(
self, contract: Contract
) -> List[Union[Any, Tuple[FunctionContract, Set[Node]], Tuple[FunctionContract, Set[Any]]]]:
def detect_type_based_tautologies(self, contract: Contract) -> List[Tuple[Function, Set[Node]]]:
"""
Detects and returns all nodes with tautology/contradiction comparisons (based on type alone).
:param contract: Contract to detect assignment within.
@ -124,7 +123,7 @@ contract A {
"""
# Create our result set.
results = []
results: List[Tuple[Function, Set[Node]]] = []
allInts = Int + Uint
# Loop for each function and modifier.
@ -157,7 +156,7 @@ contract A {
# Return the resulting set of nodes with tautologies and contradictions
return results
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""
Detect tautological (or contradictory) comparisons
"""

@ -1,12 +1,13 @@
"""
Module detecting the incorrect use of unary expressions
"""
from typing import Any, List, Union
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 typing import List
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.visitors.expression.expression import ExpressionVisitor
class InvalidUnaryExpressionDetector(ExpressionVisitor):
@ -62,7 +63,7 @@ contract Bug{
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
"""

@ -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.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."""
)
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
results = []
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.solidity_types import ElementaryType
@ -122,7 +122,7 @@ class WriteAfterWrite(AbstractDetector):
WIKI_RECOMMENDATION = """Fix or remove the writes."""
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
results = []
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).
"""
from typing import Any, List, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.visitors.expression.export_values import ExportValues
from typing import List
from slither.core.declarations.contract import Contract
from slither.core.declarations.function import Function
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.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).
: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."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""
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.
"""
from typing import Any, List, Set, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
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.declarations.function_contract import FunctionContract
from slither.core.variables.local_variable import LocalVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
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(
self,
node: Node,
results: List[Union[Tuple[Node, LocalVariable], Any]],
results: List[Tuple[Node, LocalVariable]],
already_declared: Set[LocalVariable],
visited: Set[Node],
) -> None:
@ -100,7 +101,7 @@ Additionally, the for-loop uses the variable `max`, which is declared in a previ
def detect_predeclared_in_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.
: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.
results = []
results: List[Tuple[Function, List[Tuple[Node, LocalVariable]]]] = []
# Loop for each function and modifier's nodes and analyze for predeclared local variable usage.
for function in contract.functions_and_modifiers_declared:
predeclared_usage = []
predeclared_usage: List[Tuple[Node, LocalVariable]] = []
if function.nodes:
self.detect_predeclared_local_usage(
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 results
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""
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
"""
import difflib
from typing import Any, List, Set, Tuple, Union
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import List, Set, Tuple
from slither.core.declarations.contract import Contract
from slither.core.variables.local_variable import LocalVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output
@ -72,7 +73,7 @@ class SimilarVarsDetection(AbstractDetector):
return set(ret)
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detect similar variables name
Returns:

@ -4,11 +4,11 @@
Recursively explore the CFG to only report uninitialized local variables that are
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.declarations.function_contract import FunctionContract
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
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"
def _detect_uninitialized(
self, function: FunctionContract, node: Node, visited: List[Union[Any, Node]]
self, function: FunctionContract, node: Node, visited: List[Node]
) -> None:
if node in visited:
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:
self._detect_uninitialized(function, son, visited)
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""Detect uninitialized local variables
Recursively visit the calls

@ -8,13 +8,15 @@
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.slithir.operations import InternalCall, LibraryCall
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
@ -55,7 +57,7 @@ Initialize all the variables. If a variable is meant to be initialized to zero,
# endregion wiki_recommendation
@staticmethod
def _written_variables(contract: Contract) -> List[Union[Any, StateVariable]]:
def _written_variables(contract: Contract) -> List[StateVariable]:
ret = []
# pylint: disable=too-many-nested-blocks
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})
return self.__variables_written_in_proxy
def _written_variables_in_proxy(self, contract: Contract) -> List[Any]:
variables = []
def _written_variables_in_proxy(self, contract: Contract) -> List[StateVariable]:
variables: List[StateVariable] = []
if contract.is_upgradeable:
variables_name_written_in_proxy = self._variable_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)
for v in variables_name_written_in_proxy
]
variables_in_contract = [v for v in variables_in_contract if v]
variables += variables_in_contract
variables += [v for v in variables_in_contract if v]
return list(set(variables))
@staticmethod
def _read_variables(contract: Contract) -> List[Union[Any, StateVariable]]:
def _read_variables(contract: Contract) -> List[StateVariable]:
ret = []
for f in contract.all_functions_called + contract.modifiers:
ret += f.state_variables_read
for f in contract.all_functions_called:
if isinstance(f, Function):
ret += f.state_variables_read
for m in contract.modifiers:
ret += m.state_variables_read
return ret
def _detect_uninitialized(
self, contract: Contract
) -> List[Union[Any, Tuple[StateVariable, List[FunctionContract]]]]:
def _detect_uninitialized(self, contract: Contract) -> List[Tuple[Variable, List[Function]]]:
written_variables = self._written_variables(contract)
written_variables += self._written_variables_in_proxy(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
]
def _detect(self) -> List[Union[Any, Output]]:
def _detect(self) -> List[Output]:
"""Detect uninitialized state variables
Recursively visit the calls

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

@ -1,15 +1,16 @@
"""
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.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.core.declarations.contract import Contract
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.detectors.abstract_detector import AbstractDetector, DetectorClassification
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.visitors.expression.export_values import ExportValues
def detect_unused(contract: Contract) -> Optional[List[StateVariable]]:
@ -57,7 +58,7 @@ class UnusedStateVars(AbstractDetector):
WIKI_EXPLOIT_SCENARIO = ""
WIKI_RECOMMENDATION = "Remove unused state variables."
def _detect(self) -> List[Union[Output, Any]]:
def _detect(self) -> List[Output]:
"""Detect unused state variables"""
results = []
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.declarations import Function, SolidityVariable
@ -30,7 +30,7 @@ contract C {
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 = []
for c in self.contracts:
for func in c.functions:

Loading…
Cancel
Save