pull/1640/head
Feist Josselin 2 years ago
parent b57be52818
commit d4e2f3681c
  1. 49
      slither/core/cfg/node.py
  2. 2
      slither/core/cfg/scope.py
  3. 4
      slither/core/children/child_contract.py
  4. 2
      slither/core/children/child_event.py
  5. 4
      slither/core/children/child_expression.py
  6. 4
      slither/core/children/child_inheritance.py
  7. 4
      slither/core/children/child_node.py
  8. 4
      slither/core/children/child_structure.py
  9. 16
      slither/core/compilation_unit.py
  10. 26
      slither/core/declarations/contract.py
  11. 8
      slither/core/declarations/custom_error.py
  12. 4
      slither/core/declarations/enum.py
  13. 2
      slither/core/declarations/enum_top_level.py
  14. 2
      slither/core/declarations/event.py
  15. 52
      slither/core/declarations/function.py
  16. 6
      slither/core/declarations/function_contract.py
  17. 6
      slither/core/declarations/function_top_level.py
  18. 2
      slither/core/declarations/import_directive.py
  19. 2
      slither/core/declarations/pragma_directive.py
  20. 9
      slither/core/declarations/solidity_import_placeholder.py
  21. 36
      slither/core/declarations/solidity_variables.py
  22. 2
      slither/core/declarations/structure_top_level.py
  23. 2
      slither/core/declarations/using_for_top_level.py
  24. 12
      slither/core/dominators/utils.py
  25. 2
      slither/core/expressions/assignment_operation.py
  26. 6
      slither/core/expressions/call_expression.py
  27. 11
      slither/core/expressions/conditional_expression.py
  28. 5
      slither/core/expressions/elementary_type_name_expression.py
  29. 8
      slither/core/expressions/index_access.py
  30. 2
      slither/core/expressions/literal.py
  31. 4
      slither/core/expressions/member_access.py
  32. 9
      slither/core/expressions/new_array.py
  33. 4
      slither/core/expressions/new_contract.py
  34. 14
      slither/core/expressions/type_conversion.py
  35. 9
      slither/core/expressions/unary_operation.py
  36. 2
      slither/core/scope/scope.py
  37. 2
      slither/core/slither_core.py
  38. 21
      slither/core/solidity_types/array_type.py
  39. 6
      slither/core/solidity_types/elementary_type.py
  40. 5
      slither/core/solidity_types/function_type.py
  41. 11
      slither/core/solidity_types/mapping_type.py
  42. 12
      slither/core/solidity_types/type_alias.py
  43. 5
      slither/core/solidity_types/type_information.py
  44. 12
      slither/core/solidity_types/user_defined_type.py
  45. 2
      slither/core/variables/event_variable.py
  46. 2
      slither/core/variables/state_variable.py
  47. 2
      slither/core/variables/top_level_variable.py
  48. 2
      slither/core/variables/variable.py
  49. 7
      slither/printers/guidance/echidna.py
  50. 3
      slither/slither.py
  51. 76
      slither/slithir/convert.py
  52. 9
      slither/slithir/operations/assignment.py
  53. 17
      slither/slithir/operations/binary.py
  54. 10
      slither/slithir/operations/condition.py
  55. 11
      slither/slithir/operations/delete.py
  56. 8
      slither/slithir/operations/event_call.py
  57. 20
      slither/slithir/operations/high_level_call.py
  58. 17
      slither/slithir/operations/index.py
  59. 10
      slither/slithir/operations/init_array.py
  60. 21
      slither/slithir/operations/internal_call.py
  61. 15
      slither/slithir/operations/internal_dynamic_call.py
  62. 13
      slither/slithir/operations/length.py
  63. 2
      slither/slithir/operations/library_call.py
  64. 19
      slither/slithir/operations/low_level_call.py
  65. 2
      slither/slithir/operations/lvalue.py
  66. 11
      slither/slithir/operations/member.py
  67. 16
      slither/slithir/operations/new_array.py
  68. 12
      slither/slithir/operations/new_contract.py
  69. 11
      slither/slithir/operations/new_structure.py
  70. 3
      slither/slithir/operations/operation.py
  71. 13
      slither/slithir/operations/phi.py
  72. 14
      slither/slithir/operations/phi_callback.py
  73. 10
      slither/slithir/operations/return_operation.py
  74. 14
      slither/slithir/operations/send.py
  75. 15
      slither/slithir/operations/solidity_call.py
  76. 12
      slither/slithir/operations/transfer.py
  77. 16
      slither/slithir/operations/type_conversion.py
  78. 15
      slither/slithir/operations/unary.py
  79. 6
      slither/slithir/tmp_operations/argument.py
  80. 17
      slither/slithir/tmp_operations/tmp_call.py
  81. 10
      slither/slithir/tmp_operations/tmp_new_array.py
  82. 3
      slither/slithir/tmp_operations/tmp_new_contract.py
  83. 97
      slither/slithir/utils/ssa.py
  84. 5
      slither/slithir/utils/utils.py
  85. 13
      slither/slithir/variables/constant.py
  86. 7
      slither/slithir/variables/local_variable.py
  87. 10
      slither/slithir/variables/reference.py
  88. 2
      slither/slithir/variables/reference_ssa.py
  89. 4
      slither/slithir/variables/state_variable.py
  90. 8
      slither/slithir/variables/temporary.py
  91. 7
      slither/slithir/variables/temporary_ssa.py
  92. 8
      slither/slithir/variables/tuple.py
  93. 2
      slither/slithir/variables/tuple_ssa.py
  94. 2
      slither/slithir/variables/variable.py
  95. 12
      slither/solc_parsing/cfg/node.py
  96. 70
      slither/solc_parsing/declarations/contract.py
  97. 6
      slither/solc_parsing/declarations/custom_error.py
  98. 4
      slither/solc_parsing/declarations/event.py
  99. 23
      slither/solc_parsing/declarations/function.py
  100. 6
      slither/solc_parsing/declarations/modifier.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -42,6 +42,7 @@ from slither.all_exceptions import SlitherException
from slither.core.declarations import Contract, Function
from slither.core.expressions.expression import Expression
import slither.slithir.operations.operation
if TYPE_CHECKING:
from slither.slithir.variables.variable import SlithIRVariable
@ -104,7 +105,7 @@ class NodeType(Enum):
OTHER_ENTRYPOINT = 0x60
# @staticmethod
def __str__(self):
def __str__(self) -> str:
if self == NodeType.ENTRYPOINT:
return "ENTRY_POINT"
if self == NodeType.EXPRESSION:
@ -158,7 +159,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
node_id: int,
scope: Union["Scope", "Function"],
file_scope: "FileScope",
):
) -> None:
super().__init__()
self._node_type = node_type
@ -513,11 +514,11 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
"""
return self._expression
def add_expression(self, expression: Expression, bypass_verif_empty: bool = False):
def add_expression(self, expression: Expression, bypass_verif_empty: bool = False) -> None:
assert self._expression is None or bypass_verif_empty
self._expression = expression
def add_variable_declaration(self, var: LocalVariable):
def add_variable_declaration(self, var: LocalVariable) -> None:
assert self._variable_declaration is None
self._variable_declaration = var
if var.expression:
@ -550,7 +551,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
for c in self.internal_calls
)
def contains_if(self, include_loop=True) -> bool:
def contains_if(self, include_loop: bool=True) -> bool:
"""
Check if the node is a IF node
Returns:
@ -560,7 +561,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
return self.type in [NodeType.IF, NodeType.IFLOOP]
return self.type == NodeType.IF
def is_conditional(self, include_loop=True) -> bool:
def is_conditional(self, include_loop: bool=True) -> bool:
"""
Check if the node is a conditional node
A conditional node is either a IF or a require/assert or a RETURN bool
@ -589,7 +590,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
def inline_asm(self) -> Optional[Union[str, Dict]]:
return self._asm_source_code
def add_inline_asm(self, asm: Union[str, Dict]):
def add_inline_asm(self, asm: Union[str, Dict]) -> None:
self._asm_source_code = asm
# endregion
@ -599,7 +600,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
###################################################################################
###################################################################################
def add_father(self, father: "Node"):
def add_father(self, father: "Node") -> None:
"""Add a father node
Args:
@ -624,7 +625,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
"""
return list(self._fathers)
def remove_father(self, father: "Node"):
def remove_father(self, father: "Node") -> None:
"""Remove the father node. Do nothing if the node is not a father
Args:
@ -632,7 +633,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
"""
self._fathers = [x for x in self._fathers if x.node_id != father.node_id]
def remove_son(self, son: "Node"):
def remove_son(self, son: "Node") -> None:
"""Remove the son node. Do nothing if the node is not a son
Args:
@ -640,7 +641,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
"""
self._sons = [x for x in self._sons if x.node_id != son.node_id]
def add_son(self, son: "Node"):
def add_son(self, son: "Node") -> None:
"""Add a son node
Args:
@ -648,7 +649,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
"""
self._sons.append(son)
def set_sons(self, sons: List["Node"]):
def set_sons(self, sons: List["Node"]) -> None:
"""Set the son nodes
Args:
@ -706,14 +707,14 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
def irs_ssa(self, irs):
self._irs_ssa = irs
def add_ssa_ir(self, ir: Operation):
def add_ssa_ir(self, ir: Operation) -> None:
"""
Use to place phi operation
"""
ir.set_node(self)
self._irs_ssa.append(ir)
def slithir_generation(self):
def slithir_generation(self) -> None:
if self.expression:
expression = self.expression
self._irs = convert_expression(expression, self)
@ -730,11 +731,11 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
return self._all_slithir_operations
@staticmethod
def _is_non_slithir_var(var: Variable):
def _is_non_slithir_var(var: Variable) -> bool:
return not isinstance(var, (Constant, ReferenceVariable, TemporaryVariable, TupleVariable))
@staticmethod
def _is_valid_slithir_var(var: Variable):
def _is_valid_slithir_var(var: Variable) -> bool:
return isinstance(var, (ReferenceVariable, TemporaryVariable, TupleVariable))
# endregion
@ -785,7 +786,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
self._dominance_frontier = doms
@property
def dominator_successors(self):
def dominator_successors(self) -> Set["Node"]:
return self._dom_successors
@property
@ -827,14 +828,14 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
# def phi_origin_member_variables(self) -> Dict[str, Tuple[MemberVariable, Set["Node"]]]:
# return self._phi_origins_member_variables
def add_phi_origin_local_variable(self, variable: LocalVariable, node: "Node"):
def add_phi_origin_local_variable(self, variable: LocalVariable, node: "Node") -> None:
if variable.name not in self._phi_origins_local_variables:
self._phi_origins_local_variables[variable.name] = (variable, set())
(v, nodes) = self._phi_origins_local_variables[variable.name]
assert v == variable
nodes.add(node)
def add_phi_origin_state_variable(self, variable: StateVariable, node: "Node"):
def add_phi_origin_state_variable(self, variable: StateVariable, node: "Node") -> None:
if variable.canonical_name not in self._phi_origins_state_variables:
self._phi_origins_state_variables[variable.canonical_name] = (
variable,
@ -858,7 +859,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
###################################################################################
###################################################################################
def _find_read_write_call(self): # pylint: disable=too-many-statements
def _find_read_write_call(self) -> None: # pylint: disable=too-many-statements
for ir in self.irs:
@ -934,7 +935,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
self._low_level_calls = list(set(self._low_level_calls))
@staticmethod
def _convert_ssa(v: Variable):
def _convert_ssa(v: Variable) -> Optional[Union[StateVariable, LocalVariable]]:
if isinstance(v, StateIRVariable):
contract = v.contract
non_ssa_var = contract.get_state_variable_from_name(v.name)
@ -944,7 +945,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
non_ssa_var = function.get_local_variable_from_name(v.name)
return non_ssa_var
def update_read_write_using_ssa(self):
def update_read_write_using_ssa(self) -> None:
if not self.expression:
return
for ir in self.irs_ssa:
@ -1026,12 +1027,12 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
###################################################################################
def link_nodes(node1: Node, node2: Node):
def link_nodes(node1: Node, node2: Node) -> None:
node1.add_son(node2)
node2.add_father(node1)
def insert_node(origin: Node, node_inserted: Node):
def insert_node(origin: Node, node_inserted: Node) -> None:
sons = origin.sons
link_nodes(origin, node_inserted)
for son in sons:

@ -7,7 +7,7 @@ if TYPE_CHECKING:
# pylint: disable=too-few-public-methods
class Scope:
def __init__(self, is_checked: bool, is_yul: bool, scope: Union["Scope", "Function"]):
def __init__(self, is_checked: bool, is_yul: bool, scope: Union["Scope", "Function"]) -> None:
self.nodes: List["Node"] = []
self.is_checked = is_checked
self.is_yul = is_yul

@ -7,11 +7,11 @@ if TYPE_CHECKING:
class ChildContract(SourceMapping):
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._contract = None
def set_contract(self, contract: "Contract"):
def set_contract(self, contract: "Contract") -> None:
self._contract = contract
@property

@ -5,7 +5,7 @@ if TYPE_CHECKING:
class ChildEvent:
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._event = None

@ -5,11 +5,11 @@ if TYPE_CHECKING:
class ChildExpression:
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._expression = None
def set_expression(self, expression: "Expression"):
def set_expression(self, expression: "Expression") -> None:
self._expression = expression
@property

@ -5,11 +5,11 @@ if TYPE_CHECKING:
class ChildInheritance:
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._contract_declarer = None
def set_contract_declarer(self, contract: "Contract"):
def set_contract_declarer(self, contract: "Contract") -> None:
self._contract_declarer = contract
@property

@ -7,11 +7,11 @@ if TYPE_CHECKING:
class ChildNode:
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._node = None
def set_node(self, node: "Node"):
def set_node(self, node: "Node") -> None:
self._node = node
@property

@ -5,11 +5,11 @@ if TYPE_CHECKING:
class ChildStructure:
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._structure = None
def set_structure(self, structure: "Structure"):
def set_structure(self, structure: "Structure") -> None:
self._structure = structure
@property

@ -24,6 +24,12 @@ from slither.core.variables.state_variable import StateVariable
from slither.core.variables.top_level_variable import TopLevelVariable
from slither.slithir.operations import InternalCall
from slither.slithir.variables import Constant
import crytic_compile.compilation_unit
import slither.core.declarations.contract
import slither.core.declarations.function
import slither.core.declarations.import_directive
import slither.core.declarations.modifier
import slither.core.declarations.pragma_directive
if TYPE_CHECKING:
from slither.core.slither_core import SlitherCore
@ -31,7 +37,7 @@ if TYPE_CHECKING:
# pylint: disable=too-many-instance-attributes,too-many-public-methods
class SlitherCompilationUnit(Context):
def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit):
def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit) -> None:
super().__init__()
self._core = core
@ -150,21 +156,21 @@ class SlitherCompilationUnit(Context):
def functions(self) -> List[Function]:
return list(self._all_functions)
def add_function(self, func: Function):
def add_function(self, func: Function) -> None:
self._all_functions.add(func)
@property
def modifiers(self) -> List[Modifier]:
return list(self._all_modifiers)
def add_modifier(self, modif: Modifier):
def add_modifier(self, modif: Modifier) -> None:
self._all_modifiers.add(modif)
@property
def functions_and_modifiers(self) -> List[Function]:
return self.functions + self.modifiers
def propagate_function_calls(self):
def propagate_function_calls(self) -> None:
for f in self.functions_and_modifiers:
for node in f.nodes:
for ir in node.irs_ssa:
@ -256,7 +262,7 @@ class SlitherCompilationUnit(Context):
###################################################################################
###################################################################################
def compute_storage_layout(self):
def compute_storage_layout(self) -> None:
for contract in self.contracts_derived:
self._storage_layouts[contract.name] = {}

@ -55,7 +55,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
Contract class
"""
def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope"):
def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope") -> None:
super().__init__()
self._name: Optional[str] = None
@ -366,7 +366,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
"""
return list(self._variables_ordered)
def add_variables_ordered(self, new_vars: List["StateVariable"]):
def add_variables_ordered(self, new_vars: List["StateVariable"]) -> None:
self._variables_ordered += new_vars
@property
@ -534,7 +534,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
def add_function(self, func: "FunctionContract"):
self._functions[func.canonical_name] = func
def set_functions(self, functions: Dict[str, "FunctionContract"]):
def set_functions(self, functions: Dict[str, "FunctionContract"]) -> None:
"""
Set the functions
@ -578,7 +578,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
def available_modifiers_as_dict(self) -> Dict[str, "Modifier"]:
return {m.full_name: m for m in self._modifiers.values() if not m.is_shadowed}
def set_modifiers(self, modifiers: Dict[str, "Modifier"]):
def set_modifiers(self, modifiers: Dict[str, "Modifier"]) -> None:
"""
Set the modifiers
@ -688,7 +688,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
inheritance: List["Contract"],
immediate_inheritance: List["Contract"],
called_base_constructor_contracts: List["Contract"],
):
) -> None:
self._inheritance = inheritance
self._immediate_inheritance = immediate_inheritance
self._explicit_base_constructor_calls = called_base_constructor_contracts
@ -1216,7 +1216,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
###################################################################################
###################################################################################
def update_read_write_using_ssa(self):
def update_read_write_using_ssa(self) -> None:
for function in self.functions + self.modifiers:
function.update_read_write_using_ssa()
@ -1311,7 +1311,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
def is_incorrectly_constructed(self, incorrect: bool):
self._is_incorrectly_parsed = incorrect
def add_constructor_variables(self):
def add_constructor_variables(self) -> None:
from slither.core.declarations.function_contract import FunctionContract
if self.state_variables:
@ -1380,7 +1380,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
def _create_node(
self, func: Function, counter: int, variable: "Variable", scope: Union[Scope, Function]
):
) -> "Node":
from slither.core.cfg.node import Node, NodeType
from slither.core.expressions import (
AssignmentOperationType,
@ -1412,7 +1412,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
###################################################################################
###################################################################################
def convert_expression_to_slithir_ssa(self):
def convert_expression_to_slithir_ssa(self) -> None:
"""
Assume generate_slithir_and_analyze was called on all functions
@ -1437,7 +1437,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
for func in self.functions + self.modifiers:
func.generate_slithir_ssa(all_ssa_state_variables_instances)
def fix_phi(self):
def fix_phi(self) -> None:
last_state_variables_instances = {}
initial_state_variables_instances = {}
for v in self._initial_state_variables:
@ -1459,7 +1459,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
###################################################################################
###################################################################################
def __eq__(self, other):
def __eq__(self, other: SourceMapping):
if isinstance(other, str):
return other == self.name
return NotImplemented
@ -1469,10 +1469,10 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
return other != self.name
return NotImplemented
def __str__(self):
def __str__(self) -> str:
return self.name
def __hash__(self):
def __hash__(self) -> int:
return self._id
# endregion

@ -9,7 +9,7 @@ if TYPE_CHECKING:
class CustomError(SourceMapping):
def __init__(self, compilation_unit: "SlitherCompilationUnit"):
def __init__(self, compilation_unit: "SlitherCompilationUnit") -> None:
super().__init__()
self._name: str = ""
self._parameters: List[LocalVariable] = []
@ -30,7 +30,7 @@ class CustomError(SourceMapping):
def parameters(self) -> List[LocalVariable]:
return self._parameters
def add_parameters(self, p: "LocalVariable"):
def add_parameters(self, p: "LocalVariable") -> None:
self._parameters.append(p)
@property
@ -42,7 +42,7 @@ class CustomError(SourceMapping):
###################################################################################
@staticmethod
def _convert_type_for_solidity_signature(t: Optional[Union[Type, List[Type]]]):
def _convert_type_for_solidity_signature(t: Optional[Union[Type, List[Type]]]) -> str:
# pylint: disable=import-outside-toplevel
from slither.core.declarations import Contract
@ -92,5 +92,5 @@ class CustomError(SourceMapping):
###################################################################################
###################################################################################
def __str__(self):
def __str__(self) -> str:
return "revert " + self.solidity_signature

@ -4,7 +4,7 @@ from slither.core.source_mapping.source_mapping import SourceMapping
class Enum(SourceMapping):
def __init__(self, name: str, canonical_name: str, values: List[str]):
def __init__(self, name: str, canonical_name: str, values: List[str]) -> None:
super().__init__()
self._name = name
self._canonical_name = canonical_name
@ -33,5 +33,5 @@ class Enum(SourceMapping):
def max(self) -> int:
return self._max
def __str__(self):
def __str__(self) -> str:
return self.name

@ -8,6 +8,6 @@ if TYPE_CHECKING:
class EnumTopLevel(Enum, TopLevel):
def __init__(self, name: str, canonical_name: str, values: List[str], scope: "FileScope"):
def __init__(self, name: str, canonical_name: str, values: List[str], scope: "FileScope") -> None:
super().__init__(name, canonical_name, values)
self.file_scope: "FileScope" = scope

@ -9,7 +9,7 @@ if TYPE_CHECKING:
class Event(ChildContract, SourceMapping):
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._name = None
self._elems: List[EventVariable] = []

@ -6,7 +6,7 @@ from abc import abstractmethod, ABCMeta
from collections import namedtuple
from enum import Enum
from itertools import groupby
from typing import Dict, TYPE_CHECKING, List, Optional, Set, Union, Callable, Tuple
from typing import Any, Dict, TYPE_CHECKING, List, Optional, Set, Union, Callable, Tuple
from slither.core.cfg.scope import Scope
from slither.core.declarations.solidity_variables import (
@ -27,6 +27,7 @@ from slither.core.variables.state_variable import StateVariable
from slither.utils.type import convert_type_for_solidity_signature_to_string
from slither.utils.utils import unroll
# pylint: disable=import-outside-toplevel,too-many-instance-attributes,too-many-statements,too-many-lines
if TYPE_CHECKING:
@ -45,6 +46,7 @@ if TYPE_CHECKING:
from slither.slithir.operations import Operation
from slither.core.compilation_unit import SlitherCompilationUnit
from slither.core.scope.scope import FileScope
from slither.slithir.variables.state_variable import StateIRVariable
LOGGER = logging.getLogger("Function")
ReacheableNode = namedtuple("ReacheableNode", ["node", "ir"])
@ -56,7 +58,7 @@ class ModifierStatements:
modifier: Union["Contract", "Function"],
entry_point: "Node",
nodes: List["Node"],
):
) -> None:
self._modifier = modifier
self._entry_point = entry_point
self._nodes = nodes
@ -116,7 +118,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
Function class
"""
def __init__(self, compilation_unit: "SlitherCompilationUnit"):
def __init__(self, compilation_unit: "SlitherCompilationUnit") -> None:
super().__init__()
self._internal_scope: List[str] = []
self._name: Optional[str] = None
@ -370,7 +372,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
###################################################################################
###################################################################################
def set_function_type(self, t: FunctionType):
def set_function_type(self, t: FunctionType) -> None:
assert isinstance(t, FunctionType)
self._function_type = t
@ -455,7 +457,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
def visibility(self, v: str):
self._visibility = v
def set_visibility(self, v: str):
def set_visibility(self, v: str) -> None:
self._visibility = v
@property
@ -554,7 +556,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
def entry_point(self, node: "Node"):
self._entry_point = node
def add_node(self, node: "Node"):
def add_node(self, node: "Node") -> None:
if not self._entry_point:
self._entry_point = node
self._nodes.append(node)
@ -598,7 +600,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
"""
return list(self._parameters)
def add_parameters(self, p: "LocalVariable"):
def add_parameters(self, p: "LocalVariable") -> None:
self._parameters.append(p)
@property
@ -608,7 +610,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
"""
return list(self._parameters_ssa)
def add_parameter_ssa(self, var: "LocalIRVariable"):
def add_parameter_ssa(self, var: "LocalIRVariable") -> None:
self._parameters_ssa.append(var)
def parameters_src(self) -> SourceMapping:
@ -651,7 +653,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
"""
return list(self._returns)
def add_return(self, r: "LocalVariable"):
def add_return(self, r: "LocalVariable") -> None:
self._returns.append(r)
@property
@ -661,7 +663,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
"""
return list(self._returns_ssa)
def add_return_ssa(self, var: "LocalIRVariable"):
def add_return_ssa(self, var: "LocalIRVariable") -> None:
self._returns_ssa.append(var)
# endregion
@ -680,7 +682,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
"""
return [c.modifier for c in self._modifiers]
def add_modifier(self, modif: "ModifierStatements"):
def add_modifier(self, modif: "ModifierStatements") -> None:
self._modifiers.append(modif)
@property
@ -714,7 +716,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
# This is a list of contracts internally, so we convert it to a list of constructor functions.
return list(self._explicit_base_constructor_calls)
def add_explicit_base_constructor_calls_statements(self, modif: ModifierStatements):
def add_explicit_base_constructor_calls_statements(self, modif: ModifierStatements) -> None:
self._explicit_base_constructor_calls.append(modif)
# endregion
@ -1057,7 +1059,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
self._all_reachable_from_functions = functions
return self._all_reachable_from_functions
def add_reachable_from_node(self, n: "Node", ir: "Operation"):
def add_reachable_from_node(self, n: "Node", ir: "Operation") -> None:
self._reachable_from_nodes.add(ReacheableNode(n, ir))
self._reachable_from_functions.add(n.function)
@ -1068,7 +1070,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
###################################################################################
###################################################################################
def _explore_functions(self, f_new_values: Callable[["Function"], List]):
def _explore_functions(self, f_new_values: Callable[["Function"], List]) -> List[Any]:
values = f_new_values(self)
explored = [self]
to_explore = [
@ -1218,11 +1220,11 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
func: "Function",
f: Callable[["Node"], List[SolidityVariable]],
include_loop: bool,
):
) -> List[Any]:
ret = [f(n) for n in func.nodes if n.is_conditional(include_loop)]
return [item for sublist in ret for item in sublist]
def all_conditional_solidity_variables_read(self, include_loop=True) -> List[SolidityVariable]:
def all_conditional_solidity_variables_read(self, include_loop: bool=True) -> List[SolidityVariable]:
"""
Return the Soldiity variables directly used in a condtion
@ -1258,7 +1260,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
return [var for var in ret if isinstance(var, SolidityVariable)]
@staticmethod
def _explore_func_nodes(func: "Function", f: Callable[["Node"], List[SolidityVariable]]):
def _explore_func_nodes(func: "Function", f: Callable[["Node"], List[SolidityVariable]]) -> List[Union[Any, SolidityVariableComposed]]:
ret = [f(n) for n in func.nodes]
return [item for sublist in ret for item in sublist]
@ -1367,7 +1369,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
with open(filename, "w", encoding="utf8") as f:
f.write(content)
def slithir_cfg_to_dot_str(self, skip_expressions=False) -> str:
def slithir_cfg_to_dot_str(self, skip_expressions: bool=False) -> str:
"""
Export the CFG to a DOT format. The nodes includes the Solidity expressions and the IRs
:return: the DOT content
@ -1512,7 +1514,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
###################################################################################
###################################################################################
def _analyze_read_write(self):
def _analyze_read_write(self) -> None:
"""Compute variables read/written/..."""
write_var = [x.variables_written_as_expression for x in self.nodes]
write_var = [x for x in write_var if x]
@ -1570,7 +1572,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
slithir_variables = [x for x in slithir_variables if x]
self._slithir_variables = [item for sublist in slithir_variables for item in sublist]
def _analyze_calls(self):
def _analyze_calls(self) -> None:
calls = [x.calls_as_expression for x in self.nodes]
calls = [x for x in calls if x]
calls = [item for sublist in calls for item in sublist]
@ -1702,7 +1704,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
return self._get_last_ssa_variable_instances(target_state=False, target_local=True)
@staticmethod
def _unchange_phi(ir: "Operation"):
def _unchange_phi(ir: "Operation") -> bool:
from slither.slithir.operations import Phi, PhiCallback
if not isinstance(ir, (Phi, PhiCallback)) or len(ir.rvalues) > 1:
@ -1711,7 +1713,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
return True
return ir.rvalues[0] == ir.lvalue
def fix_phi(self, last_state_variables_instances, initial_state_variables_instances):
def fix_phi(self, last_state_variables_instances: Dict[str, Union[List[Any], List[Union[Any, "StateIRVariable"]], List[ "StateIRVariable"]]], initial_state_variables_instances: Dict[str, "StateIRVariable"]) -> None:
from slither.slithir.operations import InternalCall, PhiCallback
from slither.slithir.variables import Constant, StateIRVariable
@ -1745,7 +1747,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
node.irs_ssa = [ir for ir in node.irs_ssa if not self._unchange_phi(ir)]
def generate_slithir_and_analyze(self):
def generate_slithir_and_analyze(self) -> None:
for node in self.nodes:
node.slithir_generation()
@ -1756,7 +1758,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
def generate_slithir_ssa(self, all_ssa_state_variables_instances):
pass
def update_read_write_using_ssa(self):
def update_read_write_using_ssa(self) -> None:
for node in self.nodes:
node.update_read_write_using_ssa()
self._analyze_read_write()
@ -1767,7 +1769,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu
###################################################################################
###################################################################################
def __str__(self):
def __str__(self) -> str:
return self.name
# endregion

@ -1,17 +1,19 @@
"""
Function module
"""
from typing import TYPE_CHECKING, List, Tuple
from typing import Dict, TYPE_CHECKING, List, Tuple
from slither.core.children.child_contract import ChildContract
from slither.core.children.child_inheritance import ChildInheritance
from slither.core.declarations import Function
# pylint: disable=import-outside-toplevel,too-many-instance-attributes,too-many-statements,too-many-lines
if TYPE_CHECKING:
from slither.core.declarations import Contract
from slither.core.scope.scope import FileScope
from slither.slithir.variables.state_variable import StateIRVariable
class FunctionContract(Function, ChildContract, ChildInheritance):
@ -96,7 +98,7 @@ class FunctionContract(Function, ChildContract, ChildInheritance):
###################################################################################
###################################################################################
def generate_slithir_ssa(self, all_ssa_state_variables_instances):
def generate_slithir_ssa(self, all_ssa_state_variables_instances: Dict[str, "StateIRVariable"]) -> None:
from slither.slithir.utils.ssa import add_ssa_ir, transform_slithir_vars_to_ssa
from slither.core.dominators.utils import (
compute_dominance_frontier,

@ -1,7 +1,7 @@
"""
Function module
"""
from typing import List, Tuple, TYPE_CHECKING
from typing import Any, Dict, List, Tuple, TYPE_CHECKING
from slither.core.declarations import Function
from slither.core.declarations.top_level import TopLevel
@ -12,7 +12,7 @@ if TYPE_CHECKING:
class FunctionTopLevel(Function, TopLevel):
def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope"):
def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope") -> None:
super().__init__(compilation_unit)
self._scope: "FileScope" = scope
@ -78,7 +78,7 @@ class FunctionTopLevel(Function, TopLevel):
###################################################################################
###################################################################################
def generate_slithir_ssa(self, all_ssa_state_variables_instances):
def generate_slithir_ssa(self, all_ssa_state_variables_instances: Dict[Any, Any]) -> None:
# pylint: disable=import-outside-toplevel
from slither.slithir.utils.ssa import add_ssa_ir, transform_slithir_vars_to_ssa
from slither.core.dominators.utils import (

@ -8,7 +8,7 @@ if TYPE_CHECKING:
class Import(SourceMapping):
def __init__(self, filename: Path, scope: "FileScope"):
def __init__(self, filename: Path, scope: "FileScope") -> None:
super().__init__()
self._filename: Path = filename
self._alias: Optional[str] = None

@ -7,7 +7,7 @@ if TYPE_CHECKING:
class Pragma(SourceMapping):
def __init__(self, directive: List[str], scope: "FileScope"):
def __init__(self, directive: List[str], scope: "FileScope") -> None:
super().__init__()
self._directive = directive
self.scope: "FileScope" = scope

@ -4,6 +4,11 @@ Special variable to model import with renaming
from slither.core.declarations import Import
from slither.core.solidity_types import ElementaryType
from slither.core.variables.variable import Variable
import slither.core.declarations.import_directive
import slither.core.solidity_types.elementary_type
from slither.core.declarations.contract import Contract
from slither.core.declarations.solidity_variables import SolidityVariable
from typing import Union
class SolidityImportPlaceHolder(Variable):
@ -13,7 +18,7 @@ class SolidityImportPlaceHolder(Variable):
In the long term we should remove this and better integrate import aliases
"""
def __init__(self, import_directive: Import):
def __init__(self, import_directive: Import) -> None:
super().__init__()
assert import_directive.alias is not None
self._import_directive = import_directive
@ -27,7 +32,7 @@ class SolidityImportPlaceHolder(Variable):
def type(self) -> ElementaryType:
return ElementaryType("string")
def __eq__(self, other):
def __eq__(self, other: Union[Contract, SolidityVariable]) -> bool:
return (
self.__class__ == other.__class__
and self._import_directive.filename == self._import_directive.filename

@ -1,13 +1,11 @@
# https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html
from typing import List, Dict, Union, TYPE_CHECKING
from typing import List, Dict, Union, Any
from slither.core.declarations.custom_error import CustomError
from slither.core.solidity_types import ElementaryType, TypeInformation
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.exceptions import SlitherException
if TYPE_CHECKING:
pass
SOLIDITY_VARIABLES = {
"now": "uint256",
@ -98,13 +96,13 @@ def solidity_function_signature(name):
class SolidityVariable(SourceMapping):
def __init__(self, name: str):
def __init__(self, name: str) -> None:
super().__init__()
self._check_name(name)
self._name = name
# dev function, will be removed once the code is stable
def _check_name(self, name: str): # pylint: disable=no-self-use
def _check_name(self, name: str) -> None: # pylint: disable=no-self-use
assert name in SOLIDITY_VARIABLES or name.endswith(("_slot", "_offset"))
@property
@ -124,18 +122,18 @@ class SolidityVariable(SourceMapping):
def type(self) -> ElementaryType:
return ElementaryType(SOLIDITY_VARIABLES[self.name])
def __str__(self):
def __str__(self) -> str:
return self._name
def __eq__(self, other):
def __eq__(self, other: SourceMapping) -> bool:
return self.__class__ == other.__class__ and self.name == other.name
def __hash__(self):
def __hash__(self) -> int:
return hash(self.name)
class SolidityVariableComposed(SolidityVariable):
def _check_name(self, name: str):
def _check_name(self, name: str) -> None:
assert name in SOLIDITY_VARIABLES_COMPOSED
@property
@ -146,13 +144,13 @@ class SolidityVariableComposed(SolidityVariable):
def type(self) -> ElementaryType:
return ElementaryType(SOLIDITY_VARIABLES_COMPOSED[self.name])
def __str__(self):
def __str__(self) -> str:
return self._name
def __eq__(self, other):
def __eq__(self, other: Any) -> bool:
return self.__class__ == other.__class__ and self.name == other.name
def __hash__(self):
def __hash__(self) -> int:
return hash(self.name)
@ -162,7 +160,7 @@ class SolidityFunction(SourceMapping):
# https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#type-information
# As a result, we set return_type during the Ir conversion
def __init__(self, name: str):
def __init__(self, name: str) -> None:
super().__init__()
assert name in SOLIDITY_FUNCTIONS
self._name = name
@ -187,28 +185,28 @@ class SolidityFunction(SourceMapping):
def return_type(self, r: List[Union[TypeInformation, ElementaryType]]):
self._return_type = r
def __str__(self):
def __str__(self) -> str:
return self._name
def __eq__(self, other):
def __eq__(self, other: "SolidityFunction") -> bool:
return self.__class__ == other.__class__ and self.name == other.name
def __hash__(self):
def __hash__(self) -> int:
return hash(self.name)
class SolidityCustomRevert(SolidityFunction):
def __init__(self, custom_error: CustomError): # pylint: disable=super-init-not-called
def __init__(self, custom_error: CustomError) -> None: # pylint: disable=super-init-not-called
self._name = "revert " + custom_error.solidity_signature
self._custom_error = custom_error
self._return_type: List[Union[TypeInformation, ElementaryType]] = []
def __eq__(self, other):
def __eq__(self, other: Union["SolidityCustomRevert", SolidityFunction]) -> bool:
return (
self.__class__ == other.__class__
and self.name == other.name
and self._custom_error == other._custom_error
)
def __hash__(self):
def __hash__(self) -> int:
return hash(hash(self.name) + hash(self._custom_error))

@ -9,6 +9,6 @@ if TYPE_CHECKING:
class StructureTopLevel(Structure, TopLevel):
def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope"):
def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope") -> None:
super().__init__(compilation_unit)
self.file_scope: "FileScope" = scope

@ -8,7 +8,7 @@ if TYPE_CHECKING:
class UsingForTopLevel(TopLevel):
def __init__(self, scope: "FileScope"):
def __init__(self, scope: "FileScope") -> None:
super().__init__()
self._using_for: Dict[Union[str, Type], List[Type]] = {}
self.file_scope: "FileScope" = scope

@ -1,4 +1,4 @@
from typing import List, TYPE_CHECKING
from typing import Set, List, TYPE_CHECKING
from slither.core.cfg.node import NodeType
@ -6,7 +6,7 @@ if TYPE_CHECKING:
from slither.core.cfg.node import Node
def intersection_predecessor(node: "Node"):
def intersection_predecessor(node: "Node") -> Set[Node]:
if not node.fathers:
return set()
ret = node.fathers[0].dominators
@ -15,7 +15,7 @@ def intersection_predecessor(node: "Node"):
return ret
def _compute_dominators(nodes: List["Node"]):
def _compute_dominators(nodes: List["Node"]) -> None:
changed = True
while changed:
@ -28,7 +28,7 @@ def _compute_dominators(nodes: List["Node"]):
changed = True
def _compute_immediate_dominators(nodes: List["Node"]):
def _compute_immediate_dominators(nodes: List["Node"]) -> None:
for node in nodes:
idom_candidates = set(node.dominators)
idom_candidates.remove(node)
@ -58,7 +58,7 @@ def _compute_immediate_dominators(nodes: List["Node"]):
idom.dominator_successors.add(node)
def compute_dominators(nodes: List["Node"]):
def compute_dominators(nodes: List["Node"]) -> None:
"""
Naive implementation of Cooper, Harvey, Kennedy algo
See 'A Simple,Fast Dominance Algorithm'
@ -74,7 +74,7 @@ def compute_dominators(nodes: List["Node"]):
_compute_immediate_dominators(nodes)
def compute_dominance_frontier(nodes: List["Node"]):
def compute_dominance_frontier(nodes: List["Node"]) -> None:
"""
Naive implementation of Cooper, Harvey, Kennedy algo
See 'A Simple,Fast Dominance Algorithm'

@ -85,7 +85,7 @@ class AssignmentOperation(ExpressionTyped):
right_expression: Expression,
expression_type: AssignmentOperationType,
expression_return_type: Optional["Type"],
):
) -> None:
assert isinstance(left_expression, Expression)
assert isinstance(right_expression, Expression)
super().__init__()

@ -1,10 +1,10 @@
from typing import Optional, List
from typing import Any, Optional, List
from slither.core.expressions.expression import Expression
class CallExpression(Expression): # pylint: disable=too-many-instance-attributes
def __init__(self, called, arguments, type_call):
def __init__(self, called: Expression, arguments: List[Any], type_call: str) -> None:
assert isinstance(called, Expression)
super().__init__()
self._called: Expression = called
@ -53,7 +53,7 @@ class CallExpression(Expression): # pylint: disable=too-many-instance-attribute
def type_call(self) -> str:
return self._type_call
def __str__(self):
def __str__(self) -> str:
txt = str(self._called)
if self.call_gas or self.call_value:
gas = f"gas: {self.call_gas}" if self.call_gas else ""

@ -1,10 +1,17 @@
from typing import List
from typing import Union, List
from .expression import Expression
from slither.core.expressions.binary_operation import BinaryOperation
from slither.core.expressions.expression import Expression
from slither.core.expressions.identifier import Identifier
from slither.core.expressions.literal import Literal
from slither.core.expressions.tuple_expression import TupleExpression
from slither.core.expressions.type_conversion import TypeConversion
from slither.core.expressions.unary_operation import UnaryOperation
class ConditionalExpression(Expression):
def __init__(self, if_expression, then_expression, else_expression):
def __init__(self, if_expression: Union[BinaryOperation, Identifier, Literal], then_expression: Union["ConditionalExpression", TypeConversion, Literal, TupleExpression, Identifier], else_expression: Union[TupleExpression, UnaryOperation, Identifier, Literal]) -> None:
assert isinstance(if_expression, Expression)
assert isinstance(then_expression, Expression)
assert isinstance(else_expression, Expression)

@ -3,10 +3,11 @@
"""
from slither.core.expressions.expression import Expression
from slither.core.solidity_types.type import Type
from slither.core.solidity_types.elementary_type import ElementaryType
class ElementaryTypeNameExpression(Expression):
def __init__(self, t):
def __init__(self, t: ElementaryType) -> None:
assert isinstance(t, Type)
super().__init__()
self._type = t
@ -20,5 +21,5 @@ class ElementaryTypeNameExpression(Expression):
assert isinstance(new_type, Type)
self._type = new_type
def __str__(self):
def __str__(self) -> str:
return str(self._type)

@ -1,6 +1,8 @@
from typing import List, TYPE_CHECKING
from typing import Union, List, TYPE_CHECKING
from slither.core.expressions.expression_typed import ExpressionTyped
from slither.core.expressions.identifier import Identifier
from slither.core.expressions.literal import Literal
if TYPE_CHECKING:
@ -9,7 +11,7 @@ if TYPE_CHECKING:
class IndexAccess(ExpressionTyped):
def __init__(self, left_expression, right_expression, index_type):
def __init__(self, left_expression: Union["IndexAccess", Identifier], right_expression: Union[Literal, Identifier], index_type: str) -> None:
super().__init__()
self._expressions = [left_expression, right_expression]
# TODO type of undexAccess is not always a Type
@ -32,5 +34,5 @@ class IndexAccess(ExpressionTyped):
def type(self) -> "Type":
return self._type
def __str__(self):
def __str__(self) -> str:
return str(self.expression_left) + "[" + str(self.expression_right) + "]"

@ -12,7 +12,7 @@ if TYPE_CHECKING:
class Literal(Expression):
def __init__(
self, value: Union[int, str], custom_type: "Type", subdenomination: Optional[str] = None
):
) -> None:
super().__init__()
self._value = value
self._type = custom_type

@ -5,7 +5,7 @@ from slither.core.solidity_types.type import Type
class MemberAccess(ExpressionTyped):
def __init__(self, member_name, member_type, expression):
def __init__(self, member_name: str, member_type: str, expression: Expression) -> None:
# assert isinstance(member_type, Type)
# TODO member_type is not always a Type
assert isinstance(expression, Expression)
@ -26,5 +26,5 @@ class MemberAccess(ExpressionTyped):
def type(self) -> Type:
return self._type
def __str__(self):
def __str__(self) -> str:
return str(self.expression) + "." + self.member_name

@ -1,11 +1,18 @@
from typing import Union, TYPE_CHECKING
from slither.core.expressions.expression import Expression
from slither.core.solidity_types.type import Type
if TYPE_CHECKING:
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.solidity_types.type_alias import TypeAliasTopLevel
class NewArray(Expression):
# note: dont conserve the size of the array if provided
def __init__(self, depth, array_type):
def __init__(self, depth: int, array_type: Union["TypeAliasTopLevel", "ElementaryType"]) -> None:
super().__init__()
assert isinstance(array_type, Type)
self._depth: int = depth

@ -2,7 +2,7 @@ from slither.core.expressions.expression import Expression
class NewContract(Expression):
def __init__(self, contract_name):
def __init__(self, contract_name: str) -> None:
super().__init__()
self._contract_name: str = contract_name
self._gas = None
@ -29,5 +29,5 @@ class NewContract(Expression):
def call_salt(self, salt):
self._salt = salt
def __str__(self):
def __str__(self) -> str:
return "new " + str(self._contract_name)

@ -1,10 +1,20 @@
from typing import Union, TYPE_CHECKING
from slither.core.expressions.expression_typed import ExpressionTyped
from slither.core.expressions.expression import Expression
from slither.core.solidity_types.type import Type
if TYPE_CHECKING:
from slither.core.expressions.call_expression import CallExpression
from slither.core.expressions.identifier import Identifier
from slither.core.expressions.literal import Literal
from slither.core.expressions.member_access import MemberAccess
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.solidity_types.type_alias import TypeAliasContract
from slither.core.solidity_types.user_defined_type import UserDefinedType
class TypeConversion(ExpressionTyped):
def __init__(self, expression, expression_type):
def __init__(self, expression: Union["MemberAccess", "Literal", "CallExpression", "TypeConversion", "Identifier"], expression_type: Union["ElementaryType", "UserDefinedType", "TypeAliasContract"]) -> None:
super().__init__()
assert isinstance(expression, Expression)
assert isinstance(expression_type, Type)
@ -15,5 +25,5 @@ class TypeConversion(ExpressionTyped):
def expression(self) -> Expression:
return self._expression
def __str__(self):
def __str__(self) -> str:
return str(self.type) + "(" + str(self.expression) + ")"

@ -4,6 +4,11 @@ from enum import Enum
from slither.core.expressions.expression_typed import ExpressionTyped
from slither.core.expressions.expression import Expression
from slither.core.exceptions import SlitherCoreError
from slither.core.expressions.identifier import Identifier
from slither.core.expressions.index_access import IndexAccess
from slither.core.expressions.literal import Literal
from slither.core.expressions.tuple_expression import TupleExpression
from typing import Union
logger = logging.getLogger("UnaryOperation")
@ -20,7 +25,7 @@ class UnaryOperationType(Enum):
MINUS_PRE = 8 # for stuff like uint(-1)
@staticmethod
def get_type(operation_type, isprefix):
def get_type(operation_type: str, isprefix: bool) -> "UnaryOperationType":
if isprefix:
if operation_type == "!":
return UnaryOperationType.BANG
@ -86,7 +91,7 @@ class UnaryOperationType(Enum):
class UnaryOperation(ExpressionTyped):
def __init__(self, expression, expression_type):
def __init__(self, expression: Union[Literal, Identifier, IndexAccess, TupleExpression], expression_type: UnaryOperationType) -> None:
assert isinstance(expression, Expression)
super().__init__()
self._expression: Expression = expression

@ -25,7 +25,7 @@ def _dict_contain(d1: Dict, d2: Dict) -> bool:
# pylint: disable=too-many-instance-attributes
class FileScope:
def __init__(self, filename: Filename):
def __init__(self, filename: Filename) -> None:
self.filename = filename
self.accessible_scopes: List[FileScope] = []

@ -40,7 +40,7 @@ class SlitherCore(Context):
Slither static analyzer
"""
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._filename: Optional[str] = None

@ -1,13 +1,20 @@
from typing import Optional, Tuple
from typing import Union, Optional, Tuple, Any, TYPE_CHECKING
from slither.core.expressions import Literal
from slither.core.expressions.expression import Expression
from slither.core.solidity_types.type import Type
from slither.visitors.expression.constants_folding import ConstantFolding
if TYPE_CHECKING:
from slither.core.expressions.literal import Literal
from slither.core.expressions.binary_operation import BinaryOperation
from slither.core.expressions.identifier import Identifier
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.solidity_types.function_type import FunctionType
from slither.core.solidity_types.type_alias import TypeAliasTopLevel
class ArrayType(Type):
def __init__(self, t, length):
def __init__(self, t: Union["TypeAliasTopLevel", "ArrayType", "FunctionType", "ElementaryType"], length: Optional[Union["Identifier", "Literal", "BinaryOperation"]]) -> None:
assert isinstance(t, Type)
if length:
if isinstance(length, int):
@ -38,7 +45,7 @@ class ArrayType(Type):
return self._length
@property
def length_value(self) -> Optional[Literal]:
def length_value(self) -> Optional["Literal"]:
return self._length_value
@property
@ -56,15 +63,15 @@ class ArrayType(Type):
return elem_size * int(str(self._length_value)), True
return 32, True
def __str__(self):
def __str__(self) -> str:
if self._length:
return str(self._type) + f"[{str(self._length_value)}]"
return str(self._type) + "[]"
def __eq__(self, other):
def __eq__(self, other: Any) -> bool:
if not isinstance(other, ArrayType):
return False
return self._type == other.type and self.length == other.length
def __hash__(self):
def __hash__(self) -> int:
return hash(str(self))

@ -216,13 +216,13 @@ class ElementaryType(Type):
return MaxValues[self.name]
raise SlitherException(f"{self.name} does not have a max value")
def __str__(self):
def __str__(self) -> str:
return self._type
def __eq__(self, other):
def __eq__(self, other) -> bool:
if not isinstance(other, ElementaryType):
return False
return self.type == other.type
def __hash__(self):
def __hash__(self) -> int:
return hash(str(self))

@ -2,6 +2,7 @@ from typing import List, Tuple
from slither.core.solidity_types.type import Type
from slither.core.variables.function_type_variable import FunctionTypeVariable
from slither.core.solidity_types.elementary_type import ElementaryType
class FunctionType(Type):
@ -9,7 +10,7 @@ class FunctionType(Type):
self,
params: List[FunctionTypeVariable],
return_values: List[FunctionTypeVariable],
):
) -> None:
assert all(isinstance(x, FunctionTypeVariable) for x in params)
assert all(isinstance(x, FunctionTypeVariable) for x in return_values)
super().__init__()
@ -68,7 +69,7 @@ class FunctionType(Type):
return f"({params}) returns({return_values})"
return f"({params})"
def __eq__(self, other):
def __eq__(self, other: ElementaryType) -> bool:
if not isinstance(other, FunctionType):
return False
return self.params == other.params and self.return_values == other.return_values

@ -1,10 +1,13 @@
from typing import Tuple
from typing import Union, Tuple, TYPE_CHECKING
from slither.core.solidity_types.type import Type
if TYPE_CHECKING:
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.solidity_types.type_alias import TypeAliasTopLevel
class MappingType(Type):
def __init__(self, type_from, type_to):
def __init__(self, type_from: "ElementaryType", type_to: Union["MappingType", "TypeAliasTopLevel", "ElementaryType"]) -> None:
assert isinstance(type_from, Type)
assert isinstance(type_to, Type)
super().__init__()
@ -27,7 +30,7 @@ class MappingType(Type):
def is_dynamic(self) -> bool:
return True
def __str__(self):
def __str__(self) -> str:
return f"mapping({str(self._from)} => {str(self._to)})"
def __eq__(self, other):
@ -35,5 +38,5 @@ class MappingType(Type):
return False
return self.type_from == other.type_from and self.type_to == other.type_to
def __hash__(self):
def __hash__(self) -> int:
return hash(str(self))

@ -10,7 +10,7 @@ if TYPE_CHECKING:
class TypeAlias(Type):
def __init__(self, underlying_type: Type, name: str):
def __init__(self, underlying_type: Type, name: str) -> None:
super().__init__()
self.name = name
self.underlying_type = underlying_type
@ -31,7 +31,7 @@ class TypeAlias(Type):
def storage_size(self) -> Tuple[int, bool]:
return self.underlying_type.storage_size
def __hash__(self):
def __hash__(self) -> int:
return hash(str(self))
@property
@ -40,18 +40,18 @@ class TypeAlias(Type):
class TypeAliasTopLevel(TypeAlias, TopLevel):
def __init__(self, underlying_type: Type, name: str, scope: "FileScope"):
def __init__(self, underlying_type: Type, name: str, scope: "FileScope") -> None:
super().__init__(underlying_type, name)
self.file_scope: "FileScope" = scope
def __str__(self):
def __str__(self) -> str:
return self.name
class TypeAliasContract(TypeAlias, ChildContract):
def __init__(self, underlying_type: Type, name: str, contract: "Contract"):
def __init__(self, underlying_type: Type, name: str, contract: "Contract") -> None:
super().__init__(underlying_type, name)
self._contract: "Contract" = contract
def __str__(self):
def __str__(self) -> str:
return self.contract.name + "." + self.name

@ -1,16 +1,17 @@
from typing import TYPE_CHECKING, Tuple
from typing import Union, TYPE_CHECKING, Tuple
from slither.core.solidity_types import ElementaryType
from slither.core.solidity_types.type import Type
if TYPE_CHECKING:
from slither.core.declarations.contract import Contract
from slither.core.declarations.enum_top_level import EnumTopLevel
# Use to model the Type(X) function, which returns an undefined type
# https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#type-information
class TypeInformation(Type):
def __init__(self, c):
def __init__(self, c: Union[ElementaryType, "Contract", "EnumTopLevel"]) -> None:
# pylint: disable=import-outside-toplevel
from slither.core.declarations.contract import Contract
from slither.core.declarations.enum import Enum

@ -1,4 +1,4 @@
from typing import Union, TYPE_CHECKING, Tuple
from typing import Union, TYPE_CHECKING, Tuple, Any
import math
from slither.core.solidity_types.type import Type
@ -8,10 +8,12 @@ if TYPE_CHECKING:
from slither.core.declarations.structure import Structure
from slither.core.declarations.enum import Enum
from slither.core.declarations.contract import Contract
from slither.core.declarations import EnumContract
from slither.core.declarations.structure_top_level import StructureTopLevel
# pylint: disable=import-outside-toplevel
class UserDefinedType(Type):
def __init__(self, t):
def __init__(self, t: Union["EnumContract", "StructureTopLevel", "Contract", "StructureContract"]) -> None:
from slither.core.declarations.structure import Structure
from slither.core.declarations.enum import Enum
from slither.core.declarations.contract import Contract
@ -62,7 +64,7 @@ class UserDefinedType(Type):
to_log = f"{self} does not have storage size"
raise SlitherException(to_log)
def __str__(self):
def __str__(self) -> str:
from slither.core.declarations.structure_contract import StructureContract
from slither.core.declarations.enum_contract import EnumContract
@ -71,10 +73,10 @@ class UserDefinedType(Type):
return str(type_used.contract) + "." + str(type_used.name)
return str(type_used.name)
def __eq__(self, other):
def __eq__(self, other: Any) -> bool:
if not isinstance(other, UserDefinedType):
return False
return self.type == other.type
def __hash__(self):
def __hash__(self) -> int:
return hash(str(self))

@ -3,7 +3,7 @@ from slither.core.children.child_event import ChildEvent
class EventVariable(ChildEvent, Variable):
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._indexed = False

@ -9,7 +9,7 @@ if TYPE_CHECKING:
class StateVariable(ChildContract, Variable):
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._node_initialization: Optional["Node"] = None

@ -9,7 +9,7 @@ if TYPE_CHECKING:
class TopLevelVariable(TopLevel, Variable):
def __init__(self, scope: "FileScope"):
def __init__(self, scope: "FileScope") -> None:
super().__init__()
self._node_initialization: Optional["Node"] = None
self.file_scope = scope

@ -12,7 +12,7 @@ if TYPE_CHECKING:
# pylint: disable=too-many-instance-attributes
class Variable(SourceMapping):
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._name: Optional[str] = None
self._initial_expression: Optional["Expression"] = None

@ -31,6 +31,9 @@ from slither.slithir.operations import (
from slither.slithir.operations.binary import Binary
from slither.slithir.variables import Constant
from slither.visitors.expression.constants_folding import ConstantFolding
import slither.core.declarations.function
import slither.slithir.operations.operation
from slither.utils.output import Output
def _get_name(f: Union[Function, Variable]) -> str:
@ -168,7 +171,7 @@ def _extract_constants_from_irs( # pylint: disable=too-many-branches,too-many-n
all_cst_used: List[ConstantValue],
all_cst_used_in_binary: Dict[str, List[ConstantValue]],
context_explored: Set[Node],
):
) -> None:
for ir in irs:
if isinstance(ir, Binary):
for r in ir.read:
@ -364,7 +367,7 @@ class Echidna(AbstractPrinter):
WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#echidna"
def output(self, filename): # pylint: disable=too-many-locals
def output(self, filename: str) -> Output: # pylint: disable=too-many-locals
"""
Output the inheritance relation

@ -12,6 +12,7 @@ from slither.exceptions import SlitherError
from slither.printers.abstract_printer import AbstractPrinter
from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc
from slither.utils.output import Output
import crytic_compile.crytic_compile
logger = logging.getLogger("Slither")
logging.basicConfig()
@ -49,7 +50,7 @@ def _update_file_scopes(candidates: ValuesView[FileScope]):
class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes
def __init__(self, target: Union[str, CryticCompile], **kwargs):
def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None:
"""
Args:
target (str | CryticCompile)

@ -1,6 +1,6 @@
import logging
from pathlib import Path
from typing import List, TYPE_CHECKING, Union, Optional
from typing import Any, List, TYPE_CHECKING, Union, Optional
# pylint: disable= too-many-lines,import-outside-toplevel,too-many-branches,too-many-statements,too-many-nested-blocks
from slither.core.declarations import (
@ -34,7 +34,7 @@ from slither.core.solidity_types.elementary_type import (
MaxValues,
)
from slither.core.solidity_types.type import Type
from slither.core.solidity_types.type_alias import TypeAlias
from slither.core.solidity_types.type_alias import TypeAliasTopLevel, TypeAlias
from slither.core.variables.function_type_variable import FunctionTypeVariable
from slither.core.variables.state_variable import StateVariable
from slither.core.variables.variable import Variable
@ -83,6 +83,28 @@ from slither.slithir.variables import TupleVariable
from slither.utils.function import get_function_id
from slither.utils.type import export_nested_types_from_variable
from slither.visitors.slithir.expression_to_slithir import ExpressionToSlithIR
import slither.core.declarations.contract
import slither.core.declarations.function
import slither.core.solidity_types.elementary_type
import slither.core.solidity_types.function_type
import slither.core.solidity_types.user_defined_type
import slither.slithir.operations.assignment
import slither.slithir.operations.binary
import slither.slithir.operations.call
import slither.slithir.operations.high_level_call
import slither.slithir.operations.index
import slither.slithir.operations.init_array
import slither.slithir.operations.internal_call
import slither.slithir.operations.length
import slither.slithir.operations.library_call
import slither.slithir.operations.low_level_call
import slither.slithir.operations.member
import slither.slithir.operations.operation
import slither.slithir.operations.send
import slither.slithir.operations.solidity_call
import slither.slithir.operations.transfer
import slither.slithir.variables.temporary
from slither.core.expressions.expression import Expression
if TYPE_CHECKING:
from slither.core.cfg.node import Node
@ -91,7 +113,7 @@ if TYPE_CHECKING:
logger = logging.getLogger("ConvertToIR")
def convert_expression(expression, node):
def convert_expression(expression: Expression, node: "Node") -> List[Any]:
# handle standlone expression
# such as return true;
from slither.core.cfg.node import NodeType
@ -143,7 +165,7 @@ def convert_expression(expression, node):
###################################################################################
def is_value(ins):
def is_value(ins: slither.slithir.operations.operation.Operation) -> bool:
if isinstance(ins, TmpCall):
if isinstance(ins.ori, Member):
if ins.ori.variable_right == "value":
@ -151,7 +173,7 @@ def is_value(ins):
return False
def is_gas(ins):
def is_gas(ins: slither.slithir.operations.operation.Operation) -> bool:
if isinstance(ins, TmpCall):
if isinstance(ins.ori, Member):
if ins.ori.variable_right == "gas":
@ -159,7 +181,7 @@ def is_gas(ins):
return False
def _fits_under_integer(val: int, can_be_int: bool, can_be_uint) -> List[str]:
def _fits_under_integer(val: int, can_be_int: bool, can_be_uint: bool) -> List[str]:
"""
Return the list of uint/int that can contain val
@ -271,7 +293,7 @@ def _find_function_from_parameter(
return None
def is_temporary(ins):
def is_temporary(ins: slither.slithir.operations.operation.Operation) -> bool:
return isinstance(
ins,
(Argument, TmpNewElementaryType, TmpNewContract, TmpNewArray, TmpNewStructure),
@ -300,7 +322,7 @@ def _make_function_type(func: Function) -> FunctionType:
###################################################################################
def integrate_value_gas(result):
def integrate_value_gas(result: List[Any]) -> List[Any]:
"""
Integrate value and gas temporary arguments to call instruction
"""
@ -504,7 +526,7 @@ def _convert_type_contract(ir: Member) -> Assignment:
raise SlithIRError(f"type({contract.name}).{ir.variable_right} is unknown")
def propagate_types(ir, node: "Node"): # pylint: disable=too-many-locals
def propagate_types(ir: slither.slithir.operations.operation.Operation, node: "Node"): # pylint: disable=too-many-locals
# propagate the type
node_function = node.function
using_for = (
@ -813,7 +835,7 @@ def propagate_types(ir, node: "Node"): # pylint: disable=too-many-locals
return None
def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]): # pylint: disable=too-many-locals
def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> slither.slithir.operations.call.Call: # pylint: disable=too-many-locals
assert isinstance(ins, TmpCall)
if isinstance(ins.called, Variable) and isinstance(ins.called.type, FunctionType):
# If the call is made to a variable member, where the member is this
@ -1114,7 +1136,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]): # pylint: dis
###################################################################################
def can_be_low_level(ir):
def can_be_low_level(ir: slither.slithir.operations.high_level_call.HighLevelCall) -> bool:
return ir.function_name in [
"transfer",
"send",
@ -1125,7 +1147,7 @@ def can_be_low_level(ir):
]
def convert_to_low_level(ir):
def convert_to_low_level(ir: slither.slithir.operations.high_level_call.HighLevelCall) -> Union[slither.slithir.operations.send.Send, slither.slithir.operations.low_level_call.LowLevelCall, slither.slithir.operations.transfer.Transfer]:
"""
Convert to a transfer/send/or low level call
The funciton assume to receive a correct IR
@ -1165,7 +1187,7 @@ def convert_to_low_level(ir):
raise SlithIRError(f"Incorrect conversion to low level {ir}")
def can_be_solidity_func(ir) -> bool:
def can_be_solidity_func(ir: slither.slithir.operations.high_level_call.HighLevelCall) -> bool:
if not isinstance(ir, HighLevelCall):
return False
return ir.destination.name == "abi" and ir.function_name in [
@ -1178,7 +1200,7 @@ def can_be_solidity_func(ir) -> bool:
]
def convert_to_solidity_func(ir):
def convert_to_solidity_func(ir: slither.slithir.operations.high_level_call.HighLevelCall) -> slither.slithir.operations.solidity_call.SolidityCall:
"""
Must be called after can_be_solidity_func
:param ir:
@ -1214,7 +1236,7 @@ def convert_to_solidity_func(ir):
return new_ir
def convert_to_push_expand_arr(ir, node, ret):
def convert_to_push_expand_arr(ir: slither.slithir.operations.high_level_call.HighLevelCall, node: "Node", ret: List[Any]) -> slither.slithir.variables.temporary.TemporaryVariable:
arr = ir.destination
length = ReferenceVariable(node)
@ -1249,7 +1271,7 @@ def convert_to_push_expand_arr(ir, node, ret):
return length_val
def convert_to_push_set_val(ir, node, length_val, ret):
def convert_to_push_set_val(ir: slither.slithir.operations.high_level_call.HighLevelCall, node: "Node", length_val: slither.slithir.variables.temporary.TemporaryVariable, ret: List[Union[slither.slithir.operations.length.Length, slither.slithir.operations.assignment.Assignment, slither.slithir.operations.binary.Binary]]) -> None:
arr = ir.destination
new_type = ir.destination.type.type
@ -1284,7 +1306,7 @@ def convert_to_push_set_val(ir, node, length_val, ret):
ret.append(ir_assign_value)
def convert_to_push(ir, node):
def convert_to_push(ir: slither.slithir.operations.high_level_call.HighLevelCall, node: "Node") -> List[Union[slither.slithir.operations.length.Length, slither.slithir.operations.assignment.Assignment, slither.slithir.operations.binary.Binary, slither.slithir.operations.index.Index, slither.slithir.operations.init_array.InitArray]]:
"""
Convert a call to a series of operations to push a new value onto the array
@ -1358,7 +1380,7 @@ def convert_to_pop(ir, node):
return ret
def look_for_library_or_top_level(contract, ir, using_for, t):
def look_for_library_or_top_level(contract: slither.core.declarations.contract.Contract, ir: slither.slithir.operations.high_level_call.HighLevelCall, using_for, t: Union[slither.core.solidity_types.user_defined_type.UserDefinedType, slither.core.solidity_types.elementary_type.ElementaryType, str, TypeAliasTopLevel]) -> Optional[Union[slither.slithir.operations.library_call.LibraryCall, slither.slithir.operations.internal_call.InternalCall]]:
for destination in using_for[t]:
if isinstance(destination, FunctionTopLevel) and destination.name == ir.function_name:
arguments = [ir.destination] + ir.arguments
@ -1403,7 +1425,7 @@ def look_for_library_or_top_level(contract, ir, using_for, t):
return None
def convert_to_library_or_top_level(ir, node, using_for):
def convert_to_library_or_top_level(ir: slither.slithir.operations.high_level_call.HighLevelCall, node: "Node", using_for) -> Optional[Union[slither.slithir.operations.library_call.LibraryCall, slither.slithir.operations.internal_call.InternalCall]]:
# We use contract_declarer, because Solidity resolve the library
# before resolving the inheritance.
# Though we could use .contract as libraries cannot be shadowed
@ -1422,7 +1444,7 @@ def convert_to_library_or_top_level(ir, node, using_for):
return None
def get_type(t):
def get_type(t: Union[slither.core.solidity_types.user_defined_type.UserDefinedType, slither.core.solidity_types.elementary_type.ElementaryType]) -> str:
"""
Convert a type to a str
If the instance is a Contract, return 'address' instead
@ -1441,7 +1463,7 @@ def _can_be_implicitly_converted(source: str, target: str) -> bool:
return source == target
def convert_type_library_call(ir: HighLevelCall, lib_contract: Contract):
def convert_type_library_call(ir: HighLevelCall, lib_contract: Contract) -> Optional[slither.slithir.operations.library_call.LibraryCall]:
func = None
candidates = [
f
@ -1652,7 +1674,7 @@ def convert_type_of_high_and_internal_level_call(
###################################################################################
def find_references_origin(irs):
def find_references_origin(irs: List[Any]) -> None:
"""
Make lvalue of each Index, Member operation
points to the left variable
@ -1689,7 +1711,7 @@ def remove_temporary(result):
return result
def remove_unused(result):
def remove_unused(result: List[Any]) -> List[Any]:
removed = True
if not result:
@ -1736,7 +1758,7 @@ def remove_unused(result):
###################################################################################
def convert_constant_types(irs):
def convert_constant_types(irs: List[Any]) -> None:
"""
late conversion of uint -> type for constant (Literal)
:param irs:
@ -1812,7 +1834,7 @@ def convert_constant_types(irs):
###################################################################################
def convert_delete(irs):
def convert_delete(irs: List[Any]) -> None:
"""
Convert the lvalue of the Delete to point to the variable removed
This can only be done after find_references_origin is called
@ -1833,7 +1855,7 @@ def convert_delete(irs):
###################################################################################
def _find_source_mapping_references(irs: List[Operation]):
def _find_source_mapping_references(irs: List[Operation]) -> None:
for ir in irs:
if isinstance(ir, NewContract):
@ -1848,7 +1870,7 @@ def _find_source_mapping_references(irs: List[Operation]):
###################################################################################
def apply_ir_heuristics(irs: List[Operation], node: "Node"):
def apply_ir_heuristics(irs: List[Operation], node: "Node") -> List[Any]:
"""
Apply a set of heuristic to improve slithIR
"""

@ -4,12 +4,15 @@ from slither.core.declarations.function import Function
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
from slither.slithir.variables import TupleVariable, ReferenceVariable
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.variable import Variable
from typing import List
logger = logging.getLogger("AssignmentOperationIR")
class Assignment(OperationWithLValue):
def __init__(self, left_variable, right_variable, variable_return_type):
def __init__(self, left_variable: Variable, right_variable: SourceMapping, variable_return_type) -> None:
assert is_valid_lvalue(left_variable)
assert is_valid_rvalue(right_variable) or isinstance(
right_variable, (Function, TupleVariable)
@ -25,7 +28,7 @@ class Assignment(OperationWithLValue):
return list(self._variables)
@property
def read(self):
def read(self) -> List[SourceMapping]:
return [self.rvalue]
@property
@ -33,7 +36,7 @@ class Assignment(OperationWithLValue):
return self._variable_return_type
@property
def rvalue(self):
def rvalue(self) -> SourceMapping:
return self._rvalue
def __str__(self):

@ -7,6 +7,9 @@ from slither.slithir.exceptions import SlithIRError
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
from slither.slithir.variables import ReferenceVariable
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.variable import Variable
from typing import List
logger = logging.getLogger("BinaryOperationIR")
@ -33,7 +36,7 @@ class BinaryType(Enum):
OROR = 18 # ||
@staticmethod
def return_bool(operation_type):
def return_bool(operation_type: "BinaryType") -> bool:
return operation_type in [
BinaryType.OROR,
BinaryType.ANDAND,
@ -98,7 +101,7 @@ class BinaryType(Enum):
BinaryType.DIVISION,
]
def __str__(self): # pylint: disable=too-many-branches
def __str__(self) -> str: # pylint: disable=too-many-branches
if self == BinaryType.POWER:
return "**"
if self == BinaryType.MULTIPLICATION:
@ -141,7 +144,7 @@ class BinaryType(Enum):
class Binary(OperationWithLValue):
def __init__(self, result, left_variable, right_variable, operation_type: BinaryType):
def __init__(self, result: Variable, left_variable: SourceMapping, right_variable: Variable, operation_type: BinaryType) -> None:
assert is_valid_rvalue(left_variable) or isinstance(left_variable, Function)
assert is_valid_rvalue(right_variable) or isinstance(right_variable, Function)
assert is_valid_lvalue(result)
@ -156,7 +159,7 @@ class Binary(OperationWithLValue):
result.set_type(left_variable.type)
@property
def read(self):
def read(self) -> List[SourceMapping]:
return [self.variable_left, self.variable_right]
@property
@ -164,15 +167,15 @@ class Binary(OperationWithLValue):
return self._variables
@property
def variable_left(self):
def variable_left(self) -> SourceMapping:
return self._variables[0]
@property
def variable_right(self):
def variable_right(self) -> Variable:
return self._variables[1]
@property
def type(self):
def type(self) -> BinaryType:
return self._type
@property

@ -1,6 +1,12 @@
from slither.slithir.operations.operation import Operation
from slither.slithir.utils.utils import is_valid_rvalue
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import List, Union
class Condition(Operation):
@ -9,13 +15,13 @@ class Condition(Operation):
Only present as last operation in conditional node
"""
def __init__(self, value):
def __init__(self, value: Union[LocalVariable, TemporaryVariableSSA, TemporaryVariable, Constant, LocalIRVariable]) -> None:
assert is_valid_rvalue(value)
super().__init__()
self._value = value
@property
def read(self):
def read(self) -> List[Union[LocalIRVariable, Constant, LocalVariable, TemporaryVariableSSA, TemporaryVariable]]:
return [self.value]
@property

@ -1,6 +1,11 @@
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue
from slither.core.variables.state_variable import StateVariable
from slither.slithir.variables.reference import ReferenceVariable
from slither.slithir.variables.reference_ssa import ReferenceVariableSSA
from slither.slithir.variables.state_variable import StateIRVariable
from typing import List, Union
class Delete(OperationWithLValue):
@ -9,18 +14,18 @@ class Delete(OperationWithLValue):
of its operand
"""
def __init__(self, lvalue, variable):
def __init__(self, lvalue: Union[StateIRVariable, StateVariable, ReferenceVariable], variable: Union[StateIRVariable, StateVariable, ReferenceVariable, ReferenceVariableSSA]) -> None:
assert is_valid_lvalue(variable)
super().__init__()
self._variable = variable
self._lvalue = lvalue
@property
def read(self):
def read(self) -> List[Union[StateIRVariable, ReferenceVariable, ReferenceVariableSSA, StateVariable]]:
return [self.variable]
@property
def variable(self):
def variable(self) -> Union[StateIRVariable, StateVariable, ReferenceVariable, ReferenceVariableSSA]:
return self._variable
def __str__(self):

@ -1,18 +1,20 @@
from slither.slithir.operations.call import Call
from slither.slithir.variables.constant import Constant
from typing import Any, List, Union
class EventCall(Call):
def __init__(self, name):
def __init__(self, name: Union[str, Constant]) -> None:
super().__init__()
self._name = name
# todo add instance of the Event
@property
def name(self):
def name(self) -> Union[str, Constant]:
return self._name
@property
def read(self):
def read(self) -> List[Any]:
return self._unroll(self.arguments)
def __str__(self):

@ -1,4 +1,4 @@
from typing import Union
from typing import List, Optional, Union
from slither.slithir.operations.call import Call
from slither.slithir.operations.lvalue import OperationWithLValue
@ -8,6 +8,10 @@ from slither.core.declarations.function import Function
from slither.slithir.utils.utils import is_valid_lvalue
from slither.slithir.variables.constant import Constant
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from slither.slithir.variables.tuple import TupleVariable
class HighLevelCall(Call, OperationWithLValue):
@ -16,7 +20,7 @@ class HighLevelCall(Call, OperationWithLValue):
"""
# pylint: disable=too-many-arguments,too-many-instance-attributes
def __init__(self, destination, function_name, nbr_arguments, result, type_call):
def __init__(self, destination: SourceMapping, function_name: Constant, nbr_arguments: int, result: Optional[Union[TemporaryVariable, TupleVariable, TemporaryVariableSSA]], type_call: str) -> None:
assert isinstance(function_name, Constant)
assert is_valid_lvalue(result) or result is None
self._check_destination(destination)
@ -34,7 +38,7 @@ class HighLevelCall(Call, OperationWithLValue):
# Development function, to be removed once the code is stable
# It is ovveride by LbraryCall
def _check_destination(self, destination): # pylint: disable=no-self-use
def _check_destination(self, destination: SourceMapping) -> None: # pylint: disable=no-self-use
assert isinstance(destination, (Variable, SolidityVariable))
@property
@ -62,17 +66,17 @@ class HighLevelCall(Call, OperationWithLValue):
self._call_gas = v
@property
def read(self):
def read(self) -> List[SourceMapping]:
all_read = [self.destination, self.call_gas, self.call_value] + self._unroll(self.arguments)
# remove None
return [x for x in all_read if x] + [self.destination]
@property
def destination(self):
def destination(self) -> SourceMapping:
return self._destination
@property
def function_name(self):
def function_name(self) -> Constant:
return self._function_name
@property
@ -84,11 +88,11 @@ class HighLevelCall(Call, OperationWithLValue):
self._function_instance = function
@property
def nbr_arguments(self):
def nbr_arguments(self) -> int:
return self._nbr_arguments
@property
def type_call(self):
def type_call(self) -> str:
return self._type_call
###################################################################################

@ -2,10 +2,15 @@ from slither.core.declarations import SolidityVariableComposed
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
from slither.slithir.variables.reference import ReferenceVariable
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.variables.variable import Variable
from slither.slithir.variables.reference_ssa import ReferenceVariableSSA
from typing import List, Union
class Index(OperationWithLValue):
def __init__(self, result, left_variable, right_variable, index_type):
def __init__(self, result: Union[ReferenceVariable, ReferenceVariableSSA], left_variable: Variable, right_variable: SourceMapping, index_type: Union[ElementaryType, str]) -> None:
super().__init__()
assert is_valid_lvalue(left_variable) or left_variable == SolidityVariableComposed(
"msg.data"
@ -17,23 +22,23 @@ class Index(OperationWithLValue):
self._lvalue = result
@property
def read(self):
def read(self) -> List[SourceMapping]:
return list(self.variables)
@property
def variables(self):
def variables(self) -> List[SourceMapping]:
return self._variables
@property
def variable_left(self):
def variable_left(self) -> Variable:
return self._variables[0]
@property
def variable_right(self):
def variable_right(self) -> SourceMapping:
return self._variables[1]
@property
def index_type(self):
def index_type(self) -> Union[ElementaryType, str]:
return self._type
def __str__(self):

@ -1,9 +1,13 @@
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_rvalue
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import List, Union
class InitArray(OperationWithLValue):
def __init__(self, init_values, lvalue):
def __init__(self, init_values: List[Constant], lvalue: Union[TemporaryVariableSSA, TemporaryVariable]) -> None:
# init_values can be an array of n dimension
# reduce was removed in py3
super().__init__()
@ -24,11 +28,11 @@ class InitArray(OperationWithLValue):
self._lvalue = lvalue
@property
def read(self):
def read(self) -> List[Constant]:
return self._unroll(self.init_values)
@property
def init_values(self):
def init_values(self) -> List[Constant]:
return list(self._init_values)
def __str__(self):

@ -1,15 +1,20 @@
from typing import Union, Tuple, List, Optional
from typing import Any, Union, Tuple, List, Optional
from slither.core.declarations import Modifier
from slither.core.declarations.function import Function
from slither.core.declarations.function_contract import FunctionContract
from slither.slithir.operations.call import Call
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from slither.slithir.variables.tuple import TupleVariable
from slither.slithir.variables.tuple_ssa import TupleVariableSSA
class InternalCall(Call, OperationWithLValue): # pylint: disable=too-many-instance-attributes
def __init__(
self, function: Union[Function, Tuple[str, str]], nbr_arguments, result, type_call
):
self, function: Union[Function, Tuple[str, str]], nbr_arguments: int, result: Optional[Union[TupleVariableSSA, TemporaryVariableSSA, TupleVariable, TemporaryVariable]], type_call: str
) -> None:
super().__init__()
self._contract_name = ""
if isinstance(function, Function):
@ -30,7 +35,7 @@ class InternalCall(Call, OperationWithLValue): # pylint: disable=too-many-insta
self.function_candidates: Optional[List[Function]] = None
@property
def read(self):
def read(self) -> List[Any]:
return list(self._unroll(self.arguments))
@property
@ -42,19 +47,19 @@ class InternalCall(Call, OperationWithLValue): # pylint: disable=too-many-insta
self._function = f
@property
def function_name(self):
def function_name(self) -> Constant:
return self._function_name
@property
def contract_name(self):
def contract_name(self) -> str:
return self._contract_name
@property
def nbr_arguments(self):
def nbr_arguments(self) -> int:
return self._nbr_arguments
@property
def type_call(self):
def type_call(self) -> str:
return self._type_call
@property

@ -3,12 +3,19 @@ from slither.core.variables.variable import Variable
from slither.slithir.operations.call import Call
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue
import slither.core.solidity_types.function_type
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import List, Optional, Union
class InternalDynamicCall(
Call, OperationWithLValue
): # pylint: disable=too-many-instance-attributes
def __init__(self, lvalue, function, function_type):
def __init__(self, lvalue: Optional[Union[TemporaryVariableSSA, TemporaryVariable]], function: Union[LocalVariable, LocalIRVariable], function_type: slither.core.solidity_types.function_type.FunctionType) -> None:
assert isinstance(function_type, FunctionType)
assert isinstance(function, Variable)
assert is_valid_lvalue(lvalue) or lvalue is None
@ -22,15 +29,15 @@ class InternalDynamicCall(
self._call_gas = None
@property
def read(self):
def read(self) -> List[Union[Constant, LocalIRVariable, LocalVariable]]:
return self._unroll(self.arguments) + [self.function]
@property
def function(self):
def function(self) -> Union[LocalVariable, LocalIRVariable]:
return self._function
@property
def function_type(self):
def function_type(self) -> slither.core.solidity_types.function_type.FunctionType:
return self._function_type
@property

@ -1,10 +1,17 @@
from slither.core.solidity_types import ElementaryType
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable
from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.variables.reference import ReferenceVariable
from slither.slithir.variables.reference_ssa import ReferenceVariableSSA
from slither.slithir.variables.state_variable import StateIRVariable
from typing import List, Union
class Length(OperationWithLValue):
def __init__(self, value, lvalue):
def __init__(self, value: Union[StateVariable, LocalIRVariable, LocalVariable, StateIRVariable], lvalue: Union[ReferenceVariable, ReferenceVariableSSA]) -> None:
super().__init__()
assert is_valid_rvalue(value)
assert is_valid_lvalue(lvalue)
@ -13,11 +20,11 @@ class Length(OperationWithLValue):
lvalue.set_type(ElementaryType("uint256"))
@property
def read(self):
def read(self) -> List[Union[LocalVariable, StateVariable, LocalIRVariable, StateIRVariable]]:
return [self._value]
@property
def value(self):
def value(self) -> Union[StateVariable, LocalVariable]:
return self._value
def __str__(self):

@ -9,7 +9,7 @@ class LibraryCall(HighLevelCall):
"""
# Development function, to be removed once the code is stable
def _check_destination(self, destination):
def _check_destination(self, destination: Contract) -> None:
assert isinstance(destination, Contract)
def can_reenter(self, callstack=None):

@ -4,6 +4,13 @@ from slither.core.variables.variable import Variable
from slither.core.declarations.solidity_variables import SolidityVariable
from slither.slithir.variables.constant import Constant
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from slither.slithir.variables.tuple import TupleVariable
from slither.slithir.variables.tuple_ssa import TupleVariableSSA
from typing import List, Union
class LowLevelCall(Call, OperationWithLValue): # pylint: disable=too-many-instance-attributes
@ -11,7 +18,7 @@ class LowLevelCall(Call, OperationWithLValue): # pylint: disable=too-many-insta
High level message call
"""
def __init__(self, destination, function_name, nbr_arguments, result, type_call):
def __init__(self, destination: Union[LocalVariable, LocalIRVariable, TemporaryVariableSSA, TemporaryVariable], function_name: Constant, nbr_arguments: int, result: Union[TupleVariable, TupleVariableSSA], type_call: str) -> None:
# pylint: disable=too-many-arguments
assert isinstance(destination, (Variable, SolidityVariable))
assert isinstance(function_name, Constant)
@ -51,7 +58,7 @@ class LowLevelCall(Call, OperationWithLValue): # pylint: disable=too-many-insta
self._call_gas = v
@property
def read(self):
def read(self) -> List[Union[LocalIRVariable, Constant, LocalVariable, TemporaryVariableSSA, TemporaryVariable]]:
all_read = [self.destination, self.call_gas, self.call_value] + self.arguments
# remove None
return self._unroll([x for x in all_read if x])
@ -73,19 +80,19 @@ class LowLevelCall(Call, OperationWithLValue): # pylint: disable=too-many-insta
return self._call_value is not None
@property
def destination(self):
def destination(self) -> Union[LocalVariable, LocalIRVariable, TemporaryVariableSSA, TemporaryVariable]:
return self._destination
@property
def function_name(self):
def function_name(self) -> Constant:
return self._function_name
@property
def nbr_arguments(self):
def nbr_arguments(self) -> int:
return self._nbr_arguments
@property
def type_call(self):
def type_call(self) -> str:
return self._type_call
def __str__(self):

@ -6,7 +6,7 @@ class OperationWithLValue(Operation):
Operation with a lvalue
"""
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._lvalue = None

@ -7,10 +7,13 @@ from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_rvalue
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.reference import ReferenceVariable
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.slithir.variables.reference_ssa import ReferenceVariableSSA
from typing import List, Union
class Member(OperationWithLValue):
def __init__(self, variable_left, variable_right, result):
def __init__(self, variable_left: SourceMapping, variable_right: Constant, result: Union[ReferenceVariable, ReferenceVariableSSA]) -> None:
# Function can happen for something like
# library FunctionExtensions {
# function h(function() internal _t, uint8) internal { }
@ -38,15 +41,15 @@ class Member(OperationWithLValue):
self._value = None
@property
def read(self):
def read(self) -> List[SourceMapping]:
return [self.variable_left, self.variable_right]
@property
def variable_left(self):
def variable_left(self) -> SourceMapping:
return self._variable_left
@property
def variable_right(self):
def variable_right(self) -> Constant:
return self._variable_right
@property

@ -1,10 +1,18 @@
from typing import List, Union, TYPE_CHECKING
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.operations.call import Call
from slither.core.solidity_types.type import Type
if TYPE_CHECKING:
from slither.core.solidity_types.type_alias import TypeAliasTopLevel
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
class NewArray(Call, OperationWithLValue):
def __init__(self, depth, array_type, lvalue):
def __init__(self, depth: int, array_type: "TypeAliasTopLevel",
lvalue: Union["TemporaryVariableSSA", "TemporaryVariable"]) -> None:
super().__init__()
assert isinstance(array_type, Type)
self._depth = depth
@ -13,15 +21,15 @@ class NewArray(Call, OperationWithLValue):
self._lvalue = lvalue
@property
def array_type(self):
def array_type(self) -> "TypeAliasTopLevel":
return self._array_type
@property
def read(self):
def read(self) -> List["Constant"]:
return self._unroll(self.arguments)
@property
def depth(self):
def depth(self) -> int:
return self._depth
def __str__(self):

@ -1,10 +1,14 @@
from slither.slithir.operations import Call, OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue
from slither.slithir.variables.constant import Constant
from slither.core.declarations.contract import Contract
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import Any, List, Union
class NewContract(Call, OperationWithLValue): # pylint: disable=too-many-instance-attributes
def __init__(self, contract_name, lvalue):
def __init__(self, contract_name: Constant, lvalue: Union[TemporaryVariableSSA, TemporaryVariable]) -> None:
assert isinstance(contract_name, Constant)
assert is_valid_lvalue(lvalue)
super().__init__()
@ -40,15 +44,15 @@ class NewContract(Call, OperationWithLValue): # pylint: disable=too-many-instan
self._call_salt = s
@property
def contract_name(self):
def contract_name(self) -> Constant:
return self._contract_name
@property
def read(self):
def read(self) -> List[Any]:
return self._unroll(self.arguments)
@property
def contract_created(self):
def contract_created(self) -> Contract:
contract_name = self.contract_name
contract_instance = self.node.file_scope.get_contract_from_name(contract_name)
return contract_instance

@ -4,10 +4,15 @@ from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue
from slither.core.declarations.structure import Structure
from slither.core.declarations.structure_contract import StructureContract
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import List, Union
class NewStructure(Call, OperationWithLValue):
def __init__(self, structure, lvalue):
def __init__(self, structure: StructureContract, lvalue: Union[TemporaryVariableSSA, TemporaryVariable]) -> None:
super().__init__()
assert isinstance(structure, Structure)
assert is_valid_lvalue(lvalue)
@ -16,11 +21,11 @@ class NewStructure(Call, OperationWithLValue):
self._lvalue = lvalue
@property
def read(self):
def read(self) -> List[Union[TemporaryVariableSSA, TemporaryVariable, Constant]]:
return self._unroll(self.arguments)
@property
def structure(self):
def structure(self) -> StructureContract:
return self._structure
@property

@ -3,6 +3,7 @@ from slither.core.context.context import Context
from slither.core.children.child_expression import ChildExpression
from slither.core.children.child_node import ChildNode
from slither.utils.utils import unroll
from typing import Any, List
class AbstractOperation(abc.ABC):
@ -33,5 +34,5 @@ class Operation(Context, ChildExpression, ChildNode, AbstractOperation):
# if array inside the parameters
@staticmethod
def _unroll(l):
def _unroll(l: List[Any]) -> List[Any]:
return unroll(l)

@ -1,9 +1,16 @@
from typing import List, Set, Union, TYPE_CHECKING
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue
from slither.core.declarations.solidity_variables import SolidityVariableComposed
from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.variables.state_variable import StateIRVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
if TYPE_CHECKING:
from slither.core.cfg.node import Node
class Phi(OperationWithLValue):
def __init__(self, left_variable, nodes):
def __init__(self, left_variable: Union[LocalIRVariable, StateIRVariable], nodes: Set["Node" ]) -> None:
# When Phi operations are created the
# correct indexes of the variables are not yet computed
# We store the nodes where the variables are written
@ -17,7 +24,7 @@ class Phi(OperationWithLValue):
self._nodes = nodes
@property
def read(self):
def read(self) -> List[Union[SolidityVariableComposed, LocalIRVariable, TemporaryVariableSSA, StateIRVariable]]:
return self.rvalues
@property
@ -29,7 +36,7 @@ class Phi(OperationWithLValue):
self._rvalues = vals
@property
def nodes(self):
def nodes(self) -> Set["Node"]:
return self._nodes
def __str__(self):

@ -1,9 +1,17 @@
from typing import List, Set, Union, TYPE_CHECKING
from slither.slithir.utils.utils import is_valid_lvalue
from slither.slithir.operations.phi import Phi
from slither.slithir.operations.high_level_call import HighLevelCall
from slither.slithir.operations.internal_call import InternalCall
from slither.slithir.variables.state_variable import StateIRVariable
if TYPE_CHECKING:
from slither.core.cfg.node import Node
class PhiCallback(Phi):
def __init__(self, left_variable, nodes, call_ir, rvalue):
def __init__(self, left_variable: StateIRVariable, nodes: Set["Node"], call_ir: Union[InternalCall, HighLevelCall], rvalue: StateIRVariable) -> None:
assert is_valid_lvalue(left_variable)
assert isinstance(nodes, set)
super().__init__(left_variable, nodes)
@ -12,11 +20,11 @@ class PhiCallback(Phi):
self._rvalue_no_callback = rvalue
@property
def callee_ir(self):
def callee_ir(self) -> Union[InternalCall, HighLevelCall]:
return self._call_ir
@property
def read(self):
def read(self) -> List[StateIRVariable]:
return self.rvalues
@property

@ -3,6 +3,8 @@ from slither.slithir.operations.operation import Operation
from slither.slithir.variables.tuple import TupleVariable
from slither.slithir.utils.utils import is_valid_rvalue
from slither.core.variables.variable import Variable
from typing import List
class Return(Operation):
@ -11,7 +13,7 @@ class Return(Operation):
Only present as last operation in RETURN node
"""
def __init__(self, values):
def __init__(self, values) -> None:
# Note: Can return None
# ex: return call()
# where call() dont return
@ -35,7 +37,7 @@ class Return(Operation):
super().__init__()
self._values = values
def _valid_value(self, value):
def _valid_value(self, value) -> bool:
if isinstance(value, list):
assert all(self._valid_value(v) for v in value)
else:
@ -43,11 +45,11 @@ class Return(Operation):
return True
@property
def read(self):
def read(self) -> List[Variable]:
return self._unroll(self.values)
@property
def values(self):
def values(self) -> List[Variable]:
return self._unroll(self._values)
def __str__(self):

@ -3,10 +3,16 @@ from slither.core.variables.variable import Variable
from slither.slithir.operations.call import Call
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import List, Union
class Send(Call, OperationWithLValue):
def __init__(self, destination, value, result):
def __init__(self, destination: Union[LocalVariable, LocalIRVariable], value: Constant, result: Union[TemporaryVariable, TemporaryVariableSSA]) -> None:
assert is_valid_lvalue(result)
assert isinstance(destination, (Variable, SolidityVariable))
super().__init__()
@ -19,15 +25,15 @@ class Send(Call, OperationWithLValue):
return True
@property
def call_value(self):
def call_value(self) -> Constant:
return self._call_value
@property
def read(self):
def read(self) -> List[Union[Constant, LocalIRVariable, LocalVariable]]:
return [self.destination, self.call_value]
@property
def destination(self):
def destination(self) -> Union[LocalVariable, LocalIRVariable]:
return self._destination
def __str__(self):

@ -1,10 +1,13 @@
from slither.core.declarations.solidity_variables import SolidityFunction
from slither.core.declarations.solidity_variables import SolidityCustomRevert, SolidityFunction
from slither.slithir.operations.call import Call
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.core.children.child_node import ChildNode
from slither.core.solidity_types.elementary_type import ElementaryType
from typing import Any, List, Union
class SolidityCall(Call, OperationWithLValue):
def __init__(self, function, nbr_arguments, result, type_call):
def __init__(self, function: Union[SolidityCustomRevert, SolidityFunction], nbr_arguments: int, result: ChildNode, type_call: Union[str, List[ElementaryType]]) -> None:
assert isinstance(function, SolidityFunction)
super().__init__()
self._function = function
@ -13,19 +16,19 @@ class SolidityCall(Call, OperationWithLValue):
self._lvalue = result
@property
def read(self):
def read(self) -> List[Any]:
return self._unroll(self.arguments)
@property
def function(self):
def function(self) -> Union[SolidityCustomRevert, SolidityFunction]:
return self._function
@property
def nbr_arguments(self):
def nbr_arguments(self) -> int:
return self._nbr_arguments
@property
def type_call(self):
def type_call(self) -> Union[str, List[ElementaryType]]:
return self._type_call
def __str__(self):

@ -1,10 +1,14 @@
from slither.slithir.operations.call import Call
from slither.core.variables.variable import Variable
from slither.core.declarations.solidity_variables import SolidityVariable
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.local_variable import LocalIRVariable
from typing import List, Union
class Transfer(Call):
def __init__(self, destination, value):
def __init__(self, destination: Union[LocalVariable, LocalIRVariable], value: Constant) -> None:
assert isinstance(destination, (Variable, SolidityVariable))
self._destination = destination
super().__init__()
@ -15,15 +19,15 @@ class Transfer(Call):
return True
@property
def call_value(self):
def call_value(self) -> Constant:
return self._call_value
@property
def read(self):
def read(self) -> List[Union[Constant, LocalIRVariable, LocalVariable]]:
return [self.destination, self.call_value]
@property
def destination(self):
def destination(self) -> Union[LocalVariable, LocalIRVariable]:
return self._destination
def __str__(self):

@ -2,10 +2,18 @@ from slither.core.declarations import Contract
from slither.core.solidity_types.type import Type
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
import slither.core.declarations.contract
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.solidity_types.type_alias import TypeAliasContract, TypeAliasTopLevel
from slither.core.solidity_types.user_defined_type import UserDefinedType
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import List, Union
class TypeConversion(OperationWithLValue):
def __init__(self, result, variable, variable_type):
def __init__(self, result: Union[TemporaryVariableSSA, TemporaryVariable], variable: SourceMapping, variable_type: Union[TypeAliasContract, UserDefinedType, ElementaryType, TypeAliasTopLevel]) -> None:
super().__init__()
assert is_valid_rvalue(variable) or isinstance(variable, Contract)
assert is_valid_lvalue(result)
@ -16,15 +24,15 @@ class TypeConversion(OperationWithLValue):
self._lvalue = result
@property
def variable(self):
def variable(self) -> SourceMapping:
return self._variable
@property
def type(self):
def type(self) -> Union[TypeAliasContract, TypeAliasTopLevel, slither.core.declarations.contract.Contract, UserDefinedType, ElementaryType]:
return self._type
@property
def read(self):
def read(self) -> List[SourceMapping]:
return [self.variable]
def __str__(self):

@ -4,6 +4,13 @@ from enum import Enum
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
from slither.slithir.exceptions import SlithIRError
from slither.core.expressions.unary_operation import UnaryOperationType
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.local_variable import LocalIRVariable
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA
from typing import List, Union
logger = logging.getLogger("BinaryOperationIR")
@ -31,7 +38,7 @@ class UnaryType(Enum):
class Unary(OperationWithLValue):
def __init__(self, result, variable, operation_type):
def __init__(self, result: Union[TemporaryVariableSSA, TemporaryVariable], variable: Union[Constant, LocalIRVariable, LocalVariable], operation_type: UnaryOperationType) -> None:
assert is_valid_rvalue(variable)
assert is_valid_lvalue(result)
super().__init__()
@ -40,15 +47,15 @@ class Unary(OperationWithLValue):
self._lvalue = result
@property
def read(self):
def read(self) -> List[Union[Constant, LocalIRVariable, LocalVariable]]:
return [self._variable]
@property
def rvalue(self):
def rvalue(self) -> Union[Constant, LocalVariable]:
return self._variable
@property
def type(self):
def type(self) -> UnaryOperationType:
return self._type
@property

@ -10,7 +10,7 @@ class ArgumentType(Enum):
class Argument(Operation):
def __init__(self, argument):
def __init__(self, argument) -> None:
super().__init__()
self._argument = argument
self._type = ArgumentType.CALL
@ -32,11 +32,11 @@ class Argument(Operation):
def read(self):
return [self.argument]
def set_type(self, t):
def set_type(self, t: ArgumentType) -> None:
assert isinstance(t, ArgumentType)
self._type = t
def get_type(self):
def get_type(self) -> ArgumentType:
return self._type
def __str__(self):

@ -8,10 +8,17 @@ from slither.core.declarations import (
from slither.core.declarations.custom_error import CustomError
from slither.core.variables.variable import Variable
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.slithir.operations.member import Member
from slither.slithir.tmp_operations.tmp_new_array import TmpNewArray
from slither.slithir.tmp_operations.tmp_new_contract import TmpNewContract
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.tuple import TupleVariable
from typing import Optional, Union
class TmpCall(OperationWithLValue): # pylint: disable=too-many-instance-attributes
def __init__(self, called, nbr_arguments, result, type_call):
def __init__(self, called: SourceMapping, nbr_arguments: int, result: Union[TupleVariable, TemporaryVariable], type_call: str) -> None:
assert isinstance(
called,
(
@ -80,18 +87,18 @@ class TmpCall(OperationWithLValue): # pylint: disable=too-many-instance-attribu
self._called = c
@property
def nbr_arguments(self):
def nbr_arguments(self) -> int:
return self._nbr_arguments
@property
def type_call(self):
def type_call(self) -> str:
return self._type_call
@property
def ori(self):
def ori(self) -> Optional[Union[TmpNewContract, TmpNewArray, "TmpCall", Member]]:
return self._ori
def set_ori(self, ori):
def set_ori(self, ori: Union["TmpCall", TmpNewContract, TmpNewArray, Member]) -> None:
self._ori = ori
def __str__(self):

@ -1,9 +1,13 @@
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.core.solidity_types.type import Type
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.solidity_types.type_alias import TypeAliasTopLevel
from slither.slithir.variables.temporary import TemporaryVariable
from typing import Union
class TmpNewArray(OperationWithLValue):
def __init__(self, depth, array_type, lvalue):
def __init__(self, depth: int, array_type: Union[TypeAliasTopLevel, ElementaryType], lvalue: TemporaryVariable) -> None:
super().__init__()
assert isinstance(array_type, Type)
self._depth = depth
@ -11,7 +15,7 @@ class TmpNewArray(OperationWithLValue):
self._lvalue = lvalue
@property
def array_type(self):
def array_type(self) -> TypeAliasTopLevel:
return self._array_type
@property
@ -19,7 +23,7 @@ class TmpNewArray(OperationWithLValue):
return []
@property
def depth(self):
def depth(self) -> int:
return self._depth
def __str__(self):

@ -1,8 +1,9 @@
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.variables.temporary import TemporaryVariable
class TmpNewContract(OperationWithLValue):
def __init__(self, contract_name, lvalue):
def __init__(self, contract_name: str, lvalue: TemporaryVariable) -> None:
super().__init__()
self._contract_name = contract_name
self._lvalue = lvalue

@ -1,6 +1,6 @@
import logging
from slither.core.cfg.node import NodeType
from slither.core.cfg.node import Node, NodeType
from slither.core.declarations import (
Contract,
Enum,
@ -58,6 +58,21 @@ from slither.slithir.variables import (
TupleVariableSSA,
)
from slither.slithir.exceptions import SlithIRError
import slither.slithir.operations.init_array
import slither.slithir.operations.new_array
import slither.slithir.operations.return_operation
import slither.slithir.variables.local_variable
import slither.slithir.variables.reference_ssa
import slither.slithir.variables.state_variable
import slither.slithir.variables.temporary_ssa
import slither.slithir.variables.tuple_ssa
from slither.core.declarations.function_contract import FunctionContract
from slither.core.declarations.function_top_level import FunctionTopLevel
from slither.core.declarations.modifier import Modifier
from slither.core.variables.variable import Variable
from slither.slithir.operations.call import Call
from slither.slithir.operations.operation import Operation
from typing import Any, Callable, Dict, List, Tuple, Union
logger = logging.getLogger("SSA_Conversion")
@ -68,7 +83,7 @@ logger = logging.getLogger("SSA_Conversion")
###################################################################################
def transform_slithir_vars_to_ssa(function):
def transform_slithir_vars_to_ssa(function: Union[FunctionContract, Modifier, FunctionTopLevel]) -> None:
"""
Transform slithIR vars to SSA (TemporaryVariable, ReferenceVariable, TupleVariable)
"""
@ -98,7 +113,7 @@ def transform_slithir_vars_to_ssa(function):
# pylint: disable=too-many-arguments,too-many-locals,too-many-nested-blocks,too-many-statements,too-many-branches
def add_ssa_ir(function, all_state_variables_instances):
def add_ssa_ir(function: Union[FunctionContract, Modifier, FunctionTopLevel], all_state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable]) -> None:
"""
Add SSA version of the IR
Args:
@ -199,14 +214,14 @@ def add_ssa_ir(function, all_state_variables_instances):
def generate_ssa_irs(
node,
local_variables_instances,
all_local_variables_instances,
state_variables_instances,
all_state_variables_instances,
init_local_variables_instances,
visited,
):
node: Node,
local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
all_local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable],
all_state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable],
init_local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
visited: List[Union[Node, Any]],
) -> None:
if node in visited:
return
@ -323,7 +338,7 @@ def generate_ssa_irs(
###################################################################################
def last_name(n, var, init_vars):
def last_name(n: Node, var: Union[slither.slithir.variables.state_variable.StateIRVariable, slither.slithir.variables.local_variable.LocalIRVariable], init_vars: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable]) -> Union[slither.slithir.variables.state_variable.StateIRVariable, slither.slithir.variables.local_variable.LocalIRVariable]:
candidates = []
# Todo optimize by creating a variables_ssa_written attribute
for ir_ssa in n.irs_ssa:
@ -342,7 +357,7 @@ def last_name(n, var, init_vars):
return max(candidates, key=lambda v: v.index)
def is_used_later(initial_node, variable):
def is_used_later(initial_node: Node, variable: Union[slither.slithir.variables.state_variable.StateIRVariable, LocalVariable]) -> bool:
# TODO: does not handle the case where its read and written in the declaration node
# It can be problematic if this happens in a loop/if structure
# Ex:
@ -389,13 +404,13 @@ def is_used_later(initial_node, variable):
def update_lvalue(
new_ir,
node,
local_variables_instances,
all_local_variables_instances,
state_variables_instances,
all_state_variables_instances,
):
new_ir: Operation,
node: Node,
local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
all_local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable],
all_state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable],
) -> None:
if isinstance(new_ir, OperationWithLValue):
lvalue = new_ir.lvalue
update_through_ref = False
@ -437,8 +452,8 @@ def update_lvalue(
def initiate_all_local_variables_instances(
nodes, local_variables_instances, all_local_variables_instances
):
nodes: List[Node], local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable], all_local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable]
) -> None:
for node in nodes:
if node.variable_declaration:
new_var = LocalIRVariable(node.variable_declaration)
@ -457,13 +472,13 @@ def initiate_all_local_variables_instances(
def fix_phi_rvalues_and_storage_ref(
node,
local_variables_instances,
all_local_variables_instances,
state_variables_instances,
all_state_variables_instances,
init_local_variables_instances,
):
node: Node,
local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
all_local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable],
all_state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable],
init_local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
) -> None:
for ir in node.irs_ssa:
if isinstance(ir, (Phi)) and not ir.rvalues:
variables = [
@ -506,7 +521,7 @@ def fix_phi_rvalues_and_storage_ref(
)
def add_phi_origins(node, local_variables_definition, state_variables_definition):
def add_phi_origins(node: Node, local_variables_definition: Dict[str, Tuple[LocalVariable, Node]], state_variables_definition: Dict[str, Tuple[StateVariable, Node]]) -> None:
# Add new key to local_variables_definition
# The key is the variable_name
@ -557,12 +572,12 @@ def add_phi_origins(node, local_variables_definition, state_variables_definition
def get(
variable,
local_variables_instances,
state_variables_instances,
temporary_variables_instances,
reference_variables_instances,
tuple_variables_instances,
all_local_variables_instances,
local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
state_variables_instances: Dict[str, slither.slithir.variables.state_variable.StateIRVariable],
temporary_variables_instances: Dict[int, slither.slithir.variables.temporary_ssa.TemporaryVariableSSA],
reference_variables_instances: Dict[int, slither.slithir.variables.reference_ssa.ReferenceVariableSSA],
tuple_variables_instances: Dict[int, slither.slithir.variables.tuple_ssa.TupleVariableSSA],
all_local_variables_instances: Dict[str, slither.slithir.variables.local_variable.LocalIRVariable],
):
# variable can be None
# for example, on LowLevelCall, ir.lvalue can be none
@ -623,14 +638,14 @@ def get(
return variable
def get_variable(ir, f, *instances):
def get_variable(ir: Operation, f: Callable, *instances):
# pylint: disable=no-value-for-parameter
variable = f(ir)
variable = get(variable, *instances)
return variable
def _get_traversal(values, *instances):
def _get_traversal(values: List[Any], *instances) -> List[Any]:
ret = []
# pylint: disable=no-value-for-parameter
for v in values:
@ -642,11 +657,11 @@ def _get_traversal(values, *instances):
return ret
def get_arguments(ir, *instances):
def get_arguments(ir: Call, *instances) -> List[Any]:
return _get_traversal(ir.arguments, *instances)
def get_rec_values(ir, f, *instances):
def get_rec_values(ir: Union[slither.slithir.operations.init_array.InitArray, slither.slithir.operations.return_operation.Return, slither.slithir.operations.new_array.NewArray], f: Callable, *instances) -> List[Variable]:
# Use by InitArray and NewArray
# Potential recursive array(s)
ori_init_values = f(ir)
@ -654,7 +669,7 @@ def get_rec_values(ir, f, *instances):
return _get_traversal(ori_init_values, *instances)
def copy_ir(ir, *instances):
def copy_ir(ir: Operation, *instances) -> Operation:
"""
Args:
ir (Operation)

@ -8,9 +8,10 @@ from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.constant import Constant
from slither.slithir.variables.reference import ReferenceVariable
from slither.slithir.variables.tuple import TupleVariable
from slither.core.source_mapping.source_mapping import SourceMapping
def is_valid_rvalue(v):
def is_valid_rvalue(v: SourceMapping) -> bool:
return isinstance(
v,
(
@ -25,7 +26,7 @@ def is_valid_rvalue(v):
)
def is_valid_lvalue(v):
def is_valid_lvalue(v) -> bool:
return isinstance(
v,
(

@ -4,13 +4,14 @@ from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uin
from slither.slithir.variables.variable import SlithIRVariable
from slither.utils.arithmetic import convert_subdenomination
from slither.utils.integer_conversion import convert_string_to_int
from typing import Optional, Union
@total_ordering
class Constant(SlithIRVariable):
def __init__(
self, val, constant_type=None, subdenomination=None
): # pylint: disable=too-many-branches
self, val: str, constant_type: Optional[ElementaryType]=None, subdenomination: Optional[str]=None
) -> None: # pylint: disable=too-many-branches
super().__init__()
assert isinstance(val, str)
@ -38,7 +39,7 @@ class Constant(SlithIRVariable):
self._val = val
@property
def value(self):
def value(self) -> Union[bool, int, str]:
"""
Return the value.
If the expression was an hexadecimal delcared as hex'...'
@ -56,14 +57,14 @@ class Constant(SlithIRVariable):
"""
return self._original_value
def __str__(self):
def __str__(self) -> str:
return str(self.value)
@property
def name(self):
def name(self) -> str:
return str(self)
def __eq__(self, other):
def __eq__(self, other: Union["Constant", str]) -> bool:
return self.value == other
def __ne__(self, other):

@ -1,12 +1,13 @@
from slither.core.variables.local_variable import LocalVariable
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.variable import SlithIRVariable
from slither.slithir.variables.state_variable import StateIRVariable
class LocalIRVariable(
LocalVariable, SlithIRVariable
): # pylint: disable=too-many-instance-attributes
def __init__(self, local_variable):
def __init__(self, local_variable: LocalVariable) -> None:
assert isinstance(local_variable, LocalVariable)
super().__init__()
@ -57,10 +58,10 @@ class LocalIRVariable(
self._refers_to = variables
@property
def non_ssa_version(self):
def non_ssa_version(self) -> LocalVariable:
return self._non_ssa_version
def add_refers_to(self, variable):
def add_refers_to(self, variable: StateIRVariable) -> None:
# It is a temporaryVariable if its the return of a new ..
# ex: string[] memory dynargs = new string[](1);
assert isinstance(variable, (SlithIRVariable, TemporaryVariable))

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_node import ChildNode
from slither.core.declarations import Contract, Enum, SolidityVariable, Function
@ -9,7 +9,7 @@ if TYPE_CHECKING:
class ReferenceVariable(ChildNode, Variable):
def __init__(self, node: "Node", index=None):
def __init__(self, node: "Node", index: Optional[int]=None) -> None:
super().__init__()
if index is None:
self._index = node.compilation_unit.counter_slithir_reference
@ -56,17 +56,17 @@ class ReferenceVariable(ChildNode, Variable):
self._points_to = points_to
@property
def name(self):
def name(self) -> str:
return f"REF_{self.index}"
# overide of core.variables.variables
# reference can have Function has a type
# to handle the function selector
def set_type(self, t):
def set_type(self, t) -> None:
if not isinstance(t, Function):
super().set_type(t)
else:
self._type = t
def __str__(self):
def __str__(self) -> str:
return self.name

@ -7,7 +7,7 @@ from slither.slithir.variables.reference import ReferenceVariable
class ReferenceVariableSSA(ReferenceVariable): # pylint: disable=too-few-public-methods
def __init__(self, reference):
def __init__(self, reference: ReferenceVariable) -> None:
super().__init__(reference.node, reference.index)
self._non_ssa_version = reference

@ -5,7 +5,7 @@ from slither.slithir.variables.variable import SlithIRVariable
class StateIRVariable(
StateVariable, SlithIRVariable
): # pylint: disable=too-many-instance-attributes
def __init__(self, state_variable):
def __init__(self, state_variable: StateVariable) -> None:
assert isinstance(state_variable, StateVariable)
super().__init__()
@ -38,7 +38,7 @@ class StateIRVariable(
self._index = idx
@property
def non_ssa_version(self):
def non_ssa_version(self) -> StateVariable:
return self._non_ssa_version
@property

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_node import ChildNode
from slither.core.variables.variable import Variable
@ -8,7 +8,7 @@ if TYPE_CHECKING:
class TemporaryVariable(ChildNode, Variable):
def __init__(self, node: "Node", index=None):
def __init__(self, node: "Node", index: Optional[int]=None) -> None:
super().__init__()
if index is None:
self._index = node.compilation_unit.counter_slithir_temporary
@ -26,8 +26,8 @@ class TemporaryVariable(ChildNode, Variable):
self._index = idx
@property
def name(self):
def name(self) -> str:
return f"TMP_{self.index}"
def __str__(self):
def __str__(self) -> str:
return self.name

@ -4,14 +4,17 @@
as the TemporaryVariable are in SSA form in both version
"""
from slither.slithir.variables.temporary import TemporaryVariable
from slither.slithir.variables.reference import ReferenceVariable
from slither.slithir.variables.tuple import TupleVariable
from typing import Union
class TemporaryVariableSSA(TemporaryVariable): # pylint: disable=too-few-public-methods
def __init__(self, temporary):
def __init__(self, temporary: TemporaryVariable) -> None:
super().__init__(temporary.node, temporary.index)
self._non_ssa_version = temporary
@property
def non_ssa_version(self):
def non_ssa_version(self) -> Union[TemporaryVariable, TupleVariable, ReferenceVariable]:
return self._non_ssa_version

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_node import ChildNode
from slither.slithir.variables.variable import SlithIRVariable
@ -8,7 +8,7 @@ if TYPE_CHECKING:
class TupleVariable(ChildNode, SlithIRVariable):
def __init__(self, node: "Node", index=None):
def __init__(self, node: "Node", index: Optional[int]=None) -> None:
super().__init__()
if index is None:
self._index = node.compilation_unit.counter_slithir_tuple
@ -27,8 +27,8 @@ class TupleVariable(ChildNode, SlithIRVariable):
self._index = idx
@property
def name(self):
def name(self) -> str:
return f"TUPLE_{self.index}"
def __str__(self):
def __str__(self) -> str:
return self.name

@ -7,7 +7,7 @@ from slither.slithir.variables.tuple import TupleVariable
class TupleVariableSSA(TupleVariable): # pylint: disable=too-few-public-methods
def __init__(self, t):
def __init__(self, t: TupleVariable) -> None:
super().__init__(t.node, t.index)
self._non_ssa_version = t

@ -2,7 +2,7 @@ from slither.core.variables.variable import Variable
class SlithIRVariable(Variable):
def __init__(self):
def __init__(self) -> None:
super().__init__()
self._index = 0

@ -1,4 +1,4 @@
from typing import Optional, Dict
from typing import Union, Optional, Dict, TYPE_CHECKING
from slither.core.cfg.node import Node
from slither.core.cfg.node import NodeType
@ -12,9 +12,13 @@ from slither.visitors.expression.find_calls import FindCalls
from slither.visitors.expression.read_var import ReadVar
from slither.visitors.expression.write_var import WriteVar
if TYPE_CHECKING:
from slither.solc_parsing.declarations.function import FunctionSolc
from slither.solc_parsing.declarations.modifier import ModifierSolc
class NodeSolc:
def __init__(self, node: Node):
def __init__(self, node: Node) -> None:
self._unparsed_expression: Optional[Dict] = None
self._node = node
@ -22,11 +26,11 @@ class NodeSolc:
def underlying_node(self) -> Node:
return self._node
def add_unparsed_expression(self, expression: Dict):
def add_unparsed_expression(self, expression: Dict) -> None:
assert self._unparsed_expression is None
self._unparsed_expression = expression
def analyze_expressions(self, caller_context):
def analyze_expressions(self, caller_context: Union["FunctionSolc", "ModifierSolc"]) -> None:
if self._node.type == NodeType.VARIABLE and not self._node.expression:
self._node.add_expression(self._node.variable_declaration.expression)
if self._unparsed_expression:

@ -1,6 +1,6 @@
import logging
import re
from typing import List, Dict, Callable, TYPE_CHECKING, Union, Set
from typing import Any, List, Dict, Callable, TYPE_CHECKING, Union, Set
from slither.core.declarations import Modifier, Event, EnumContract, StructureContract, Function
from slither.core.declarations.contract import Contract
@ -17,19 +17,21 @@ from slither.solc_parsing.declarations.structure_contract import StructureContra
from slither.solc_parsing.exceptions import ParsingError, VariableNotFound
from slither.solc_parsing.solidity_types.type_parsing import parse_type
from slither.solc_parsing.variables.state_variable import StateVariableSolc
import slither.core.declarations.function
import slither.core.declarations.modifier
import slither.core.solidity_types.type
LOGGER = logging.getLogger("ContractSolcParsing")
if TYPE_CHECKING:
from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc
from slither.core.slither_core import SlitherCore
from slither.core.compilation_unit import SlitherCompilationUnit
# pylint: disable=too-many-instance-attributes,import-outside-toplevel,too-many-nested-blocks,too-many-public-methods
class ContractSolc(CallerContextExpression):
def __init__(self, slither_parser: "SlitherCompilationUnitSolc", contract: Contract, data):
def __init__(self, slither_parser: "SlitherCompilationUnitSolc", contract: Contract, data: Dict[str, Any]) -> None:
# assert slitherSolc.solc_version.startswith('0.4')
self._contract = contract
@ -86,7 +88,7 @@ class ContractSolc(CallerContextExpression):
def is_analyzed(self) -> bool:
return self._is_analyzed
def set_is_analyzed(self, is_analyzed: bool):
def set_is_analyzed(self, is_analyzed: bool) -> None:
self._is_analyzed = is_analyzed
@property
@ -130,7 +132,7 @@ class ContractSolc(CallerContextExpression):
def get_key(self) -> str:
return self._slither_parser.get_key()
def get_children(self, key="nodes") -> str:
def get_children(self, key: str="nodes") -> str:
if self.is_compact_ast:
return key
return "children"
@ -150,7 +152,7 @@ class ContractSolc(CallerContextExpression):
###################################################################################
###################################################################################
def _parse_contract_info(self):
def _parse_contract_info(self) -> None:
if self.is_compact_ast:
attributes = self._data
else:
@ -178,7 +180,7 @@ class ContractSolc(CallerContextExpression):
"name"
]
def _parse_base_contract_info(self): # pylint: disable=too-many-branches
def _parse_base_contract_info(self) -> None: # pylint: disable=too-many-branches
# Parse base contracts (immediate, non-linearized)
if self.is_compact_ast:
# Parse base contracts + constructors in compact-ast
@ -236,7 +238,7 @@ class ContractSolc(CallerContextExpression):
):
self.baseConstructorContractsCalled.append(referencedDeclaration)
def _parse_contract_items(self):
def _parse_contract_items(self) -> None:
# pylint: disable=too-many-branches
if not self.get_children() in self._data: # empty contract
return
@ -289,7 +291,7 @@ class ContractSolc(CallerContextExpression):
self._contract.file_scope.user_defined_types[alias] = user_defined_type
self._contract.file_scope.user_defined_types[alias_canonical] = user_defined_type
def _parse_struct(self, struct: Dict):
def _parse_struct(self, struct: Dict) -> None:
st = StructureContract(self._contract.compilation_unit)
st.set_contract(self._contract)
@ -299,7 +301,7 @@ class ContractSolc(CallerContextExpression):
self._contract.structures_as_dict[st.name] = st
self._structures_parser.append(st_parser)
def parse_structs(self):
def parse_structs(self) -> None:
for father in self._contract.inheritance_reverse:
self._contract.structures_as_dict.update(father.structures_as_dict)
@ -307,7 +309,7 @@ class ContractSolc(CallerContextExpression):
self._parse_struct(struct)
self._structuresNotParsed = None
def _parse_custom_error(self, custom_error: Dict):
def _parse_custom_error(self, custom_error: Dict) -> None:
ce = CustomErrorContract(self.compilation_unit)
ce.set_contract(self._contract)
ce.set_offset(custom_error["src"], self.compilation_unit)
@ -316,7 +318,7 @@ class ContractSolc(CallerContextExpression):
self._contract.custom_errors_as_dict[ce.name] = ce
self._custom_errors_parser.append(ce_parser)
def parse_custom_errors(self):
def parse_custom_errors(self) -> None:
for father in self._contract.inheritance_reverse:
self._contract.custom_errors_as_dict.update(father.custom_errors_as_dict)
@ -324,7 +326,7 @@ class ContractSolc(CallerContextExpression):
self._parse_custom_error(custom_error)
self._customErrorParsed = None
def parse_state_variables(self):
def parse_state_variables(self) -> None:
for father in self._contract.inheritance_reverse:
self._contract.variables_as_dict.update(
{
@ -352,7 +354,7 @@ class ContractSolc(CallerContextExpression):
self._contract.variables_as_dict[var.name] = var
self._contract.add_variables_ordered([var])
def _parse_modifier(self, modifier_data: Dict):
def _parse_modifier(self, modifier_data: Dict) -> None:
modif = Modifier(self._contract.compilation_unit)
modif.set_offset(modifier_data["src"], self._contract.compilation_unit)
modif.set_contract(self._contract)
@ -365,12 +367,12 @@ class ContractSolc(CallerContextExpression):
self._slither_parser.add_function_or_modifier_parser(modif_parser)
def parse_modifiers(self):
def parse_modifiers(self) -> None:
for modifier in self._modifiersNotParsed:
self._parse_modifier(modifier)
self._modifiersNotParsed = None
def _parse_function(self, function_data: Dict):
def _parse_function(self, function_data: Dict) -> None:
func = FunctionContract(self._contract.compilation_unit)
func.set_offset(function_data["src"], self._contract.compilation_unit)
func.set_contract(self._contract)
@ -383,7 +385,7 @@ class ContractSolc(CallerContextExpression):
self._slither_parser.add_function_or_modifier_parser(func_parser)
def parse_functions(self):
def parse_functions(self) -> None:
for function in self._functionsNotParsed:
self._parse_function(function)
@ -403,21 +405,21 @@ class ContractSolc(CallerContextExpression):
LOGGER.error(error)
self._contract.is_incorrectly_constructed = True
def analyze_content_modifiers(self):
def analyze_content_modifiers(self) -> None:
try:
for modifier_parser in self._modifiers_parser:
modifier_parser.analyze_content()
except (VariableNotFound, KeyError) as e:
self.log_incorrect_parsing(f"Missing modifier {e}")
def analyze_content_functions(self):
def analyze_content_functions(self) -> None:
try:
for function_parser in self._functions_parser:
function_parser.analyze_content()
except (VariableNotFound, KeyError, ParsingError) as e:
self.log_incorrect_parsing(f"Missing function {e}")
def analyze_params_modifiers(self):
def analyze_params_modifiers(self) -> None:
try:
elements_no_params = self._modifiers_no_params
getter = lambda c: c.modifiers_parser
@ -437,7 +439,7 @@ class ContractSolc(CallerContextExpression):
self.log_incorrect_parsing(f"Missing params {e}")
self._modifiers_no_params = []
def analyze_params_functions(self):
def analyze_params_functions(self) -> None:
try:
elements_no_params = self._functions_no_params
getter = lambda c: c.functions_parser
@ -465,7 +467,7 @@ class ContractSolc(CallerContextExpression):
explored_reference_id: Set[str],
parser: List[FunctionSolc],
all_elements: Dict[str, Function],
):
) -> None:
elem = Cls(self._contract.compilation_unit)
elem.set_contract(self._contract)
underlying_function = element_parser.underlying_function
@ -566,7 +568,7 @@ class ContractSolc(CallerContextExpression):
self.log_incorrect_parsing(f"Missing params {e}")
return all_elements
def analyze_constant_state_variables(self):
def analyze_constant_state_variables(self) -> None:
for var_parser in self._variables_parser:
if var_parser.underlying_variable.is_constant:
# cant parse constant expression based on function calls
@ -575,7 +577,7 @@ class ContractSolc(CallerContextExpression):
except (VariableNotFound, KeyError) as e:
LOGGER.error(e)
def analyze_state_variables(self):
def analyze_state_variables(self) -> None:
try:
for var_parser in self._variables_parser:
var_parser.analyze(self)
@ -583,7 +585,7 @@ class ContractSolc(CallerContextExpression):
except (VariableNotFound, KeyError) as e:
self.log_incorrect_parsing(f"Missing state variable {e}")
def analyze_using_for(self): # pylint: disable=too-many-branches
def analyze_using_for(self) -> None: # pylint: disable=too-many-branches
try:
for father in self._contract.inheritance:
self._contract.using_for.update(father.using_for)
@ -620,7 +622,7 @@ class ContractSolc(CallerContextExpression):
except (VariableNotFound, KeyError) as e:
self.log_incorrect_parsing(f"Missing using for {e}")
def _analyze_function_list(self, function_list: List, type_name: Type):
def _analyze_function_list(self, function_list: List, type_name: Type) -> None:
for f in function_list:
full_name_split = f["function"]["name"].split(".")
if len(full_name_split) == 1:
@ -639,7 +641,7 @@ class ContractSolc(CallerContextExpression):
function_name = full_name_split[2]
self._analyze_library_function(library_name, function_name, type_name)
def _check_aliased_import(self, first_part: str, function_name: str, type_name: Type):
def _check_aliased_import(self, first_part: str, function_name: str, type_name: Type) -> None:
# We check if the first part appear as alias for an import
# if it is then function_name must be a top level function
# otherwise it's a library function
@ -649,7 +651,7 @@ class ContractSolc(CallerContextExpression):
return
self._analyze_library_function(first_part, function_name, type_name)
def _analyze_top_level_function(self, function_name: str, type_name: Type):
def _analyze_top_level_function(self, function_name: str, type_name: Type) -> None:
for tl_function in self.compilation_unit.functions_top_level:
if tl_function.name == function_name:
self._contract.using_for[type_name].append(tl_function)
@ -673,7 +675,7 @@ class ContractSolc(CallerContextExpression):
f"Contract level using for: Library {library_name} - function {function_name} not found"
)
def analyze_enums(self):
def analyze_enums(self) -> None:
try:
for father in self._contract.inheritance:
self._contract.enums_as_dict.update(father.enums_as_dict)
@ -686,7 +688,7 @@ class ContractSolc(CallerContextExpression):
except (VariableNotFound, KeyError) as e:
self.log_incorrect_parsing(f"Missing enum {e}")
def _analyze_enum(self, enum):
def _analyze_enum(self, enum: Dict[str, Union[str, int, List[Dict[str, Union[int, str]]], Dict[str, str], List[Dict[str, Union[Dict[str, str], int, str]]]]]) -> None:
# Enum can be parsed in one pass
if self.is_compact_ast:
name = enum["name"]
@ -710,21 +712,21 @@ class ContractSolc(CallerContextExpression):
new_enum.set_offset(enum["src"], self._contract.compilation_unit)
self._contract.enums_as_dict[canonicalName] = new_enum
def _analyze_struct(self, struct: StructureContractSolc): # pylint: disable=no-self-use
def _analyze_struct(self, struct: StructureContractSolc) -> None: # pylint: disable=no-self-use
struct.analyze()
def analyze_structs(self):
def analyze_structs(self) -> None:
try:
for struct in self._structures_parser:
self._analyze_struct(struct)
except (VariableNotFound, KeyError) as e:
self.log_incorrect_parsing(f"Missing struct {e}")
def analyze_custom_errors(self):
def analyze_custom_errors(self) -> None:
for custom_error in self._custom_errors_parser:
custom_error.analyze_params()
def analyze_events(self):
def analyze_events(self) -> None:
try:
for father in self._contract.inheritance_reverse:
self._contract.events_as_dict.update(father.events_as_dict)

@ -22,7 +22,7 @@ class CustomErrorSolc(CallerContextExpression):
custom_error: CustomError,
custom_error_data: dict,
slither_parser: "SlitherCompilationUnitSolc",
):
) -> None:
self._slither_parser: "SlitherCompilationUnitSolc" = slither_parser
self._custom_error = custom_error
custom_error.name = custom_error_data["name"]
@ -32,7 +32,7 @@ class CustomErrorSolc(CallerContextExpression):
custom_error_data = custom_error_data["attributes"]
self._custom_error_data = custom_error_data
def analyze_params(self):
def analyze_params(self) -> None:
# Can be re-analyzed due to inheritance
if self._params_was_analyzed:
return
@ -68,7 +68,7 @@ class CustomErrorSolc(CallerContextExpression):
return key
return "children"
def _parse_params(self, params: Dict):
def _parse_params(self, params: Dict) -> None:
assert params[self.get_key()] == "ParameterList"
if self._slither_parser.is_compact_ast:

@ -16,7 +16,7 @@ class EventSolc:
Event class
"""
def __init__(self, event: Event, event_data: Dict, contract_parser: "ContractSolc"):
def __init__(self, event: Event, event_data: Dict, contract_parser: "ContractSolc") -> None:
self._event = event
event.set_contract(contract_parser.underlying_contract)
@ -43,7 +43,7 @@ class EventSolc:
def is_compact_ast(self) -> bool:
return self._parser_contract.is_compact_ast
def analyze(self, contract: "ContractSolc"):
def analyze(self, contract: "ContractSolc") -> None:
for elem_to_parse in self._elemsNotParsed:
elem = EventVariable()
# Todo: check if the source offset is always here

@ -23,10 +23,10 @@ from slither.solc_parsing.variables.local_variable_init_from_tuple import (
LocalVariableInitFromTupleSolc,
)
from slither.solc_parsing.variables.variable_declaration import MultipleVariablesDeclaration
from slither.solc_parsing.yul.parse_yul import YulBlock
from slither.utils.expression_manipulations import SplitTernaryExpression
from slither.visitors.expression.export_values import ExportValues
from slither.visitors.expression.has_conditional import HasConditional
from slither.solc_parsing.yul.parse_yul import YulBlock
if TYPE_CHECKING:
from slither.core.expressions.expression import Expression
@ -35,6 +35,7 @@ if TYPE_CHECKING:
from slither.core.compilation_unit import SlitherCompilationUnit
LOGGER = logging.getLogger("FunctionSolc")
@ -55,7 +56,7 @@ class FunctionSolc(CallerContextExpression):
function_data: Dict,
contract_parser: Optional["ContractSolc"],
slither_parser: "SlitherCompilationUnitSolc",
):
) -> None:
self._slither_parser: "SlitherCompilationUnitSolc" = slither_parser
self._contract_parser = contract_parser
self._function = function
@ -143,7 +144,7 @@ class FunctionSolc(CallerContextExpression):
def _add_local_variable(
self, local_var_parser: Union[LocalVariableSolc, LocalVariableInitFromTupleSolc]
):
) -> None:
# If two local variables have the same name
# We add a suffix to the new variable
# This is done to prevent collision during SSA translation
@ -175,7 +176,7 @@ class FunctionSolc(CallerContextExpression):
def function_not_parsed(self) -> Dict:
return self._functionNotParsed
def _analyze_type(self):
def _analyze_type(self) -> None:
"""
Analyz the type of the function
Myst be called in the constructor as the name might change according to the function's type
@ -201,7 +202,7 @@ class FunctionSolc(CallerContextExpression):
if self._function.name == self._function.contract_declarer.name:
self._function.function_type = FunctionType.CONSTRUCTOR
def _analyze_attributes(self):
def _analyze_attributes(self) -> None:
if self.is_compact_ast:
attributes = self._functionNotParsed
else:
@ -1018,7 +1019,7 @@ class FunctionSolc(CallerContextExpression):
return node
def _parse_block(self, block: Dict, node: NodeSolc, check_arithmetic: bool = False):
def _parse_block(self, block: Dict, node: NodeSolc, check_arithmetic: bool = False) -> NodeSolc:
"""
Return:
Node
@ -1053,7 +1054,7 @@ class FunctionSolc(CallerContextExpression):
node = self._parse_statement(statement, node, new_scope)
return node
def _parse_cfg(self, cfg: Dict):
def _parse_cfg(self, cfg: Dict) -> None:
assert cfg[self.get_key()] == "Block"
@ -1118,7 +1119,7 @@ class FunctionSolc(CallerContextExpression):
return None
def _fix_break_node(self, node: Node):
def _fix_break_node(self, node: Node) -> None:
end_node = self._find_end_loop(node, [], 0)
if not end_node:
@ -1134,7 +1135,7 @@ class FunctionSolc(CallerContextExpression):
node.set_sons([end_node])
end_node.add_father(node)
def _fix_continue_node(self, node: Node):
def _fix_continue_node(self, node: Node) -> None:
start_node = self._find_start_loop(node, [])
if not start_node:
@ -1145,14 +1146,14 @@ class FunctionSolc(CallerContextExpression):
node.set_sons([start_node])
start_node.add_father(node)
def _fix_try(self, node: Node):
def _fix_try(self, node: Node) -> None:
end_node = next((son for son in node.sons if son.type != NodeType.CATCH), None)
if end_node:
for son in node.sons:
if son.type == NodeType.CATCH:
self._fix_catch(son, end_node)
def _fix_catch(self, node: Node, end_node: Node):
def _fix_catch(self, node: Node, end_node: Node) -> None:
if not node.sons:
link_nodes(node, end_node)
else:

@ -23,7 +23,7 @@ class ModifierSolc(FunctionSolc):
function_data: Dict,
contract_parser: "ContractSolc",
slither_parser: "SlitherCompilationUnitSolc",
):
) -> None:
super().__init__(modifier, function_data, contract_parser, slither_parser)
# _modifier is equal to _function, but keep it here to prevent
# confusion for mypy in underlying_function
@ -33,7 +33,7 @@ class ModifierSolc(FunctionSolc):
def underlying_function(self) -> Modifier:
return self._modifier
def analyze_params(self):
def analyze_params(self) -> None:
# Can be re-analyzed due to inheritance
if self._params_was_analyzed:
return
@ -55,7 +55,7 @@ class ModifierSolc(FunctionSolc):
if params:
self._parse_params(params)
def analyze_content(self):
def analyze_content(self) -> None:
if self._content_was_analyzed:
return

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save