Run black 20.08b1

pull/620/head
Josselin 4 years ago
parent fed26b69b6
commit cfc98baf7a
  1. 4
      plugin_example/setup.py
  2. 10
      slither/__main__.py
  3. 19
      slither/analyses/data_dependency/data_dependency.py
  4. 5
      slither/analyses/write/are_variables_written.py
  5. 104
      slither/core/cfg/node.py
  6. 104
      slither/core/declarations/contract.py
  7. 6
      slither/core/declarations/event.py
  8. 206
      slither/core/declarations/function.py
  9. 2
      slither/core/declarations/pragma_directive.py
  10. 12
      slither/core/dominators/utils.py
  11. 18
      slither/core/slither_core.py
  12. 8
      slither/core/solidity_types/function_type.py
  13. 6
      slither/core/source_mapping/source_mapping.py
  14. 8
      slither/core/variables/local_variable_init_from_tuple.py
  15. 14
      slither/core/variables/state_variable.py
  16. 24
      slither/core/variables/variable.py
  17. 2
      slither/detectors/attributes/const_functions_asm.py
  18. 2
      slither/detectors/attributes/const_functions_state.py
  19. 3
      slither/detectors/attributes/locked_ether.py
  20. 4
      slither/detectors/erc/incorrect_erc20_interface.py
  21. 4
      slither/detectors/erc/incorrect_erc721_interface.py
  22. 11
      slither/detectors/functions/arbitrary_send.py
  23. 2
      slither/detectors/functions/external_function.py
  24. 5
      slither/detectors/functions/suicidal.py
  25. 18
      slither/detectors/naming_convention/naming_convention.py
  26. 7
      slither/detectors/operations/block_timestamp.py
  27. 3
      slither/detectors/operations/low_level_calls.py
  28. 3
      slither/detectors/operations/unused_return_values.py
  29. 3
      slither/detectors/operations/void_constructor.py
  30. 46
      slither/detectors/reentrancy/reentrancy.py
  31. 15
      slither/detectors/reentrancy/reentrancy_benign.py
  32. 13
      slither/detectors/reentrancy/reentrancy_eth.py
  33. 15
      slither/detectors/reentrancy/reentrancy_events.py
  34. 21
      slither/detectors/reentrancy/reentrancy_no_gas.py
  35. 10
      slither/detectors/reentrancy/reentrancy_read_before_write.py
  36. 2
      slither/detectors/shadowing/abstract.py
  37. 8
      slither/detectors/shadowing/builtin_symbols.py
  38. 4
      slither/detectors/shadowing/local.py
  39. 2
      slither/detectors/shadowing/state.py
  40. 3
      slither/detectors/statements/assembly.py
  41. 3
      slither/detectors/statements/calls_in_loop.py
  42. 8
      slither/detectors/statements/deprecated_calls.py
  43. 3
      slither/detectors/statements/tx_origin.py
  44. 3
      slither/detectors/variables/possible_const_state_variables.py
  45. 2
      slither/detectors/variables/uninitialized_local_variables.py
  46. 2
      slither/detectors/variables/uninitialized_state_variables.py
  47. 2
      slither/detectors/variables/uninitialized_storage_variables.py
  48. 3
      slither/detectors/variables/unused_state_variables.py
  49. 7
      slither/formatters/attributes/constant_pragma.py
  50. 7
      slither/formatters/naming_convention/naming_convention.py
  51. 64
      slither/printers/call/call_graph.py
  52. 12
      slither/printers/functions/authorization.py
  53. 6
      slither/printers/functions/cfg.py
  54. 8
      slither/printers/guidance/echidna.py
  55. 8
      slither/printers/inheritance/inheritance.py
  56. 8
      slither/printers/inheritance/inheritance_graph.py
  57. 6
      slither/printers/summary/contract.py
  58. 6
      slither/printers/summary/data_depenency.py
  59. 12
      slither/printers/summary/evm.py
  60. 25
      slither/printers/summary/function.py
  61. 6
      slither/printers/summary/function_ids.py
  62. 9
      slither/printers/summary/human_summary.py
  63. 6
      slither/printers/summary/modifier_calls.py
  64. 11
      slither/printers/summary/require_calls.py
  65. 6
      slither/printers/summary/slithir.py
  66. 6
      slither/printers/summary/slithir_ssa.py
  67. 6
      slither/printers/summary/variable_order.py
  68. 40
      slither/slither.py
  69. 48
      slither/slithir/convert.py
  70. 6
      slither/slithir/operations/binary.py
  71. 4
      slither/slithir/operations/condition.py
  72. 4
      slither/slithir/operations/delete.py
  73. 2
      slither/slithir/operations/high_level_call.py
  74. 8
      slither/slithir/operations/library_call.py
  75. 2
      slither/slithir/operations/low_level_call.py
  76. 2
      slither/slithir/operations/lvalue.py
  77. 6
      slither/slithir/operations/operation.py
  78. 2
      slither/slithir/operations/phi_callback.py
  79. 4
      slither/slithir/operations/return_operation.py
  80. 9
      slither/slithir/tmp_operations/tmp_call.py
  81. 20
      slither/slithir/utils/ssa.py
  82. 9
      slither/slithir/utils/utils.py
  83. 4
      slither/slithir/variables/reference.py
  84. 9
      slither/solc_parsing/declarations/contract.py
  85. 42
      slither/solc_parsing/declarations/function.py
  86. 9
      slither/solc_parsing/expressions/expression_parsing.py
  87. 12
      slither/solc_parsing/slitherSolc.py
  88. 9
      slither/solc_parsing/solidity_types/type_parsing.py
  89. 4
      slither/solc_parsing/variables/local_variable.py
  90. 14
      slither/solc_parsing/variables/variable_declaration.py
  91. 14
      slither/solc_parsing/yul/parse_yul.py
  92. 3
      slither/tools/erc_conformance/__main__.py
  93. 13
      slither/tools/flattening/__main__.py
  94. 4
      slither/tools/flattening/export/export.py
  95. 15
      slither/tools/flattening/flattening.py
  96. 11
      slither/tools/kspec_coverage/__main__.py
  97. 3
      slither/tools/possible_paths/__main__.py
  98. 3
      slither/tools/possible_paths/possible_paths.py
  99. 4
      slither/tools/properties/__main__.py
  100. 6
      slither/tools/properties/properties/erc20.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -9,5 +9,7 @@ setup(
packages=find_packages(),
python_requires=">=3.6",
install_requires=["slither-analyzer==0.1"],
entry_points={"slither_analyzer.plugin": "slither my-plugin=slither_my_plugin:make_plugin",},
entry_points={
"slither_analyzer.plugin": "slither my-plugin=slither_my_plugin:make_plugin",
},
)

@ -402,7 +402,10 @@ def parse_args(detector_classes, printer_classes):
)
group_misc.add_argument(
"--markdown-root", help="URL for markdown generation", action="store", default="",
"--markdown-root",
help="URL for markdown generation",
action="store",
default="",
)
group_misc.add_argument(
@ -437,7 +440,10 @@ def parse_args(detector_classes, printer_classes):
)
group_misc.add_argument(
"--solc-ast", help="Provide the contract as a json AST", action="store_true", default=False,
"--solc-ast",
help="Provide the contract as a json AST",
action="store_true",
default=False,
)
group_misc.add_argument(

@ -135,7 +135,9 @@ def is_tainted_ssa(variable, context, only_unprotected=False, ignore_generic_tai
def get_dependencies(
variable: Variable, context: Union[Contract, Function], only_unprotected: bool = False,
variable: Variable,
context: Union[Contract, Function],
only_unprotected: bool = False,
) -> Set[Variable]:
"""
Return the variables for which `variable` depends on.
@ -170,7 +172,9 @@ def get_all_dependencies(
def get_dependencies_ssa(
variable: Variable, context: Union[Contract, Function], only_unprotected: bool = False,
variable: Variable,
context: Union[Contract, Function],
only_unprotected: bool = False,
) -> Set[Variable]:
"""
Return the variables for which `variable` depends on (SSA version).
@ -376,7 +380,16 @@ def convert_variable_to_non_ssa(v):
return v.non_ssa_version
assert isinstance(
v,
(Constant, SolidityVariable, Contract, Enum, SolidityFunction, Structure, Function, Type,),
(
Constant,
SolidityVariable,
Contract,
Enum,
SolidityFunction,
Structure,
Function,
Type,
),
)
return v

@ -35,7 +35,10 @@ class State: # pylint: disable=too-few-public-methods
# pylint: disable=too-many-branches
def _visit(
node: Node, state: State, variables_written: Set[Variable], variables_to_write: List[Variable],
node: Node,
state: State,
variables_written: Set[Variable],
variables_to_write: List[Variable],
):
"""
Explore all the nodes to look for values not written when the node's function return

@ -236,7 +236,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def type(self) -> NodeType:
"""
NodeType: type of the node
NodeType: type of the node
"""
return self._node_type
@ -262,49 +262,49 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def variables_read(self) -> List[Variable]:
"""
list(Variable): Variables read (local/state/solidity)
list(Variable): Variables read (local/state/solidity)
"""
return list(self._vars_read)
@property
def state_variables_read(self) -> List[StateVariable]:
"""
list(StateVariable): State variables read
list(StateVariable): State variables read
"""
return list(self._state_vars_read)
@property
def local_variables_read(self) -> List[LocalVariable]:
"""
list(LocalVariable): Local variables read
list(LocalVariable): Local variables read
"""
return list(self._local_vars_read)
@property
def solidity_variables_read(self) -> List[SolidityVariable]:
"""
list(SolidityVariable): State variables read
list(SolidityVariable): State variables read
"""
return list(self._solidity_vars_read)
@property
def ssa_variables_read(self) -> List["SlithIRVariable"]:
"""
list(Variable): Variables read (local/state/solidity)
list(Variable): Variables read (local/state/solidity)
"""
return list(self._ssa_vars_read)
@property
def ssa_state_variables_read(self) -> List[StateIRVariable]:
"""
list(StateVariable): State variables read
list(StateVariable): State variables read
"""
return list(self._ssa_state_vars_read)
@property
def ssa_local_variables_read(self) -> List[LocalIRVariable]:
"""
list(LocalVariable): Local variables read
list(LocalVariable): Local variables read
"""
return list(self._ssa_local_vars_read)
@ -323,42 +323,42 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def variables_written(self) -> List[Variable]:
"""
list(Variable): Variables written (local/state/solidity)
list(Variable): Variables written (local/state/solidity)
"""
return list(self._vars_written)
@property
def state_variables_written(self) -> List[StateVariable]:
"""
list(StateVariable): State variables written
list(StateVariable): State variables written
"""
return list(self._state_vars_written)
@property
def local_variables_written(self) -> List[LocalVariable]:
"""
list(LocalVariable): Local variables written
list(LocalVariable): Local variables written
"""
return list(self._local_vars_written)
@property
def ssa_variables_written(self) -> List["SlithIRVariable"]:
"""
list(Variable): Variables written (local/state/solidity)
list(Variable): Variables written (local/state/solidity)
"""
return list(self._ssa_vars_written)
@property
def ssa_state_variables_written(self) -> List[StateIRVariable]:
"""
list(StateVariable): State variables written
list(StateVariable): State variables written
"""
return list(self._ssa_state_vars_written)
@property
def ssa_local_variables_written(self) -> List[LocalIRVariable]:
"""
list(LocalVariable): Local variables written
list(LocalVariable): Local variables written
"""
return list(self._ssa_local_vars_written)
@ -380,49 +380,49 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def internal_calls(self) -> List["InternalCallType"]:
"""
list(Function or SolidityFunction): List of internal/soldiity function calls
list(Function or SolidityFunction): List of internal/soldiity function calls
"""
return list(self._internal_calls)
@property
def solidity_calls(self) -> List[SolidityFunction]:
"""
list(SolidityFunction): List of Soldity calls
list(SolidityFunction): List of Soldity calls
"""
return list(self._solidity_calls)
@property
def high_level_calls(self) -> List["HighLevelCallType"]:
"""
list((Contract, Function|Variable)):
List of high level calls (external calls).
A variable is called in case of call to a public state variable
Include library calls
list((Contract, Function|Variable)):
List of high level calls (external calls).
A variable is called in case of call to a public state variable
Include library calls
"""
return list(self._high_level_calls)
@property
def library_calls(self) -> List["LibraryCallType"]:
"""
list((Contract, Function)):
Include library calls
list((Contract, Function)):
Include library calls
"""
return list(self._library_calls)
@property
def low_level_calls(self) -> List["LowLevelCallType"]:
"""
list((Variable|SolidityVariable, str)): List of low_level call
A low level call is defined by
- the variable called
- the name of the function (call/delegatecall/codecall)
list((Variable|SolidityVariable, str)): List of low_level call
A low level call is defined by
- the variable called
- the name of the function (call/delegatecall/codecall)
"""
return list(self._low_level_calls)
@property
def external_calls_as_expressions(self) -> List[Expression]:
"""
list(CallExpression): List of message calls (that creates a transaction)
list(CallExpression): List of message calls (that creates a transaction)
"""
return self._external_calls_as_expressions
@ -433,7 +433,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def internal_calls_as_expressions(self) -> List[Expression]:
"""
list(CallExpression): List of internal calls (that dont create a transaction)
list(CallExpression): List of internal calls (that dont create a transaction)
"""
return self._internal_calls_as_expressions
@ -497,7 +497,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def expression(self) -> Optional[Expression]:
"""
Expression: Expression of the node
Expression: Expression of the node
"""
return self._expression
@ -588,7 +588,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
###################################################################################
def add_father(self, father: "Node"):
""" Add a father node
"""Add a father node
Args:
father: father to add
@ -596,7 +596,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
self._fathers.append(father)
def set_fathers(self, fathers: List["Node"]):
""" Set the father nodes
"""Set the father nodes
Args:
fathers: list of fathers to add
@ -605,7 +605,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def fathers(self) -> List["Node"]:
""" Returns the father nodes
"""Returns the father nodes
Returns:
list(Node): list of fathers
@ -613,7 +613,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
return list(self._fathers)
def remove_father(self, father: "Node"):
""" Remove the father node. Do nothing if the node is not a father
"""Remove the father node. Do nothing if the node is not a father
Args:
:param father:
@ -621,7 +621,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"):
""" Remove the son node. Do nothing if the node is not a son
"""Remove the son node. Do nothing if the node is not a son
Args:
:param son:
@ -629,7 +629,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"):
""" Add a son node
"""Add a son node
Args:
son: son to add
@ -637,7 +637,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
self._sons.append(son)
def set_sons(self, sons: List["Node"]):
""" Set the son nodes
"""Set the son nodes
Args:
sons: list of fathers to add
@ -646,7 +646,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def sons(self) -> List["Node"]:
""" Returns the son nodes
"""Returns the son nodes
Returns:
list(Node): list of sons
@ -674,7 +674,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def irs(self) -> List[Operation]:
""" Returns the slithIR representation
"""Returns the slithIR representation
return
list(slithIR.Operation)
@ -683,7 +683,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def irs_ssa(self) -> List[Operation]:
""" Returns the slithIR representation with SSA
"""Returns the slithIR representation with SSA
return
list(slithIR.Operation)
@ -696,7 +696,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
def add_ssa_ir(self, ir: Operation):
"""
Use to place phi operation
Use to place phi operation
"""
ir.set_node(self)
self._irs_ssa.append(ir)
@ -733,8 +733,8 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def dominators(self) -> Set["Node"]:
"""
Returns:
set(Node)
Returns:
set(Node)
"""
return self._dominators
@ -745,8 +745,8 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def immediate_dominator(self) -> Optional["Node"]:
"""
Returns:
Node or None
Returns:
Node or None
"""
return self._immediate_dominator
@ -757,16 +757,16 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
@property
def dominance_frontier(self) -> Set["Node"]:
"""
Returns:
set(Node)
Returns:
set(Node)
"""
return self._dominance_frontier
@dominance_frontier.setter
def dominance_frontier(self, doms: Set["Node"]):
"""
Returns:
set(Node)
Returns:
set(Node)
"""
self._dominance_frontier = doms
@ -798,11 +798,15 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
###################################################################################
@property
def phi_origins_local_variables(self,) -> Dict[str, Tuple[LocalVariable, Set["Node"]]]:
def phi_origins_local_variables(
self,
) -> Dict[str, Tuple[LocalVariable, Set["Node"]]]:
return self._phi_origins_local_variables
@property
def phi_origins_state_variables(self,) -> Dict[str, Tuple[StateVariable, Set["Node"]]]:
def phi_origins_state_variables(
self,
) -> Dict[str, Tuple[StateVariable, Set["Node"]]]:
return self._phi_origins_state_variables
# @property

@ -134,21 +134,21 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def structures(self) -> List["Structure"]:
"""
list(Structure): List of the structures
list(Structure): List of the structures
"""
return list(self._structures.values())
@property
def structures_inherited(self) -> List["Structure"]:
"""
list(Structure): List of the inherited structures
list(Structure): List of the inherited structures
"""
return [s for s in self.structures if s.contract != self]
@property
def structures_declared(self) -> List["Structure"]:
"""
list(Structues): List of the structures declared within the contract (not inherited)
list(Structues): List of the structures declared within the contract (not inherited)
"""
return [s for s in self.structures if s.contract == self]
@ -170,14 +170,14 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def enums_inherited(self) -> List["Enum"]:
"""
list(Enum): List of the inherited enums
list(Enum): List of the inherited enums
"""
return [e for e in self.enums if e.contract != self]
@property
def enums_declared(self) -> List["Enum"]:
"""
list(Enum): List of the enums declared within the contract (not inherited)
list(Enum): List of the enums declared within the contract (not inherited)
"""
return [e for e in self.enums if e.contract == self]
@ -195,21 +195,21 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def events(self) -> List["Event"]:
"""
list(Event): List of the events
list(Event): List of the events
"""
return list(self._events.values())
@property
def events_inherited(self) -> List["Event"]:
"""
list(Event): List of the inherited events
list(Event): List of the inherited events
"""
return [e for e in self.events if e.contract != self]
@property
def events_declared(self) -> List["Event"]:
"""
list(Event): List of the events declared within the contract (not inherited)
list(Event): List of the events declared within the contract (not inherited)
"""
return [e for e in self.events if e.contract == self]
@ -238,7 +238,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def variables(self) -> List["StateVariable"]:
"""
list(StateVariable): List of the state variables. Alias to self.state_variables
list(StateVariable): List of the state variables. Alias to self.state_variables
"""
return list(self.state_variables)
@ -249,14 +249,14 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def state_variables(self) -> List["StateVariable"]:
"""
list(StateVariable): List of the state variables.
list(StateVariable): List of the state variables.
"""
return list(self._variables.values())
@property
def state_variables_ordered(self) -> List["StateVariable"]:
"""
list(StateVariable): List of the state variables by order of declaration.
list(StateVariable): List of the state variables by order of declaration.
"""
return list(self._variables_ordered)
@ -266,21 +266,21 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def state_variables_inherited(self) -> List["StateVariable"]:
"""
list(StateVariable): List of the inherited state variables
list(StateVariable): List of the inherited state variables
"""
return [s for s in self.state_variables if s.contract != self]
@property
def state_variables_declared(self) -> List["StateVariable"]:
"""
list(StateVariable): List of the state variables declared within the contract (not inherited)
list(StateVariable): List of the state variables declared within the contract (not inherited)
"""
return [s for s in self.state_variables if s.contract == self]
@property
def slithir_variables(self) -> List["SlithIRVariable"]:
"""
List all of the slithir variables (non SSA)
List all of the slithir variables (non SSA)
"""
slithir_variables = [f.slithir_variables for f in self.functions + self.modifiers] # type: ignore
slithir_variables = [item for sublist in slithir_variables for item in sublist]
@ -296,10 +296,10 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def constructor(self) -> Optional["Function"]:
"""
Return the contract's immediate constructor.
If there is no immediate constructor, returns the first constructor
executed, following the c3 linearization
Return None if there is no constructor.
Return the contract's immediate constructor.
If there is no immediate constructor, returns the first constructor
executed, following the c3 linearization
Return None if there is no constructor.
"""
cst = self.constructors_declared
if cst:
@ -324,20 +324,20 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def constructors(self) -> List["Function"]:
"""
Return the list of constructors (including inherited)
Return the list of constructors (including inherited)
"""
return [func for func in self.functions if func.is_constructor]
@property
def explicit_base_constructor_calls(self) -> List["Function"]:
"""
list(Function): List of the base constructors called explicitly by this contract definition.
list(Function): List of the base constructors called explicitly by this contract definition.
Base constructors called by any constructor definition will not be included.
Base constructors implicitly called by the contract definition (without
parenthesis) will not be included.
Base constructors called by any constructor definition will not be included.
Base constructors implicitly called by the contract definition (without
parenthesis) will not be included.
On "contract B is A(){..}" it returns the constructor of A
On "contract B is A(){..}" it returns the constructor of A
"""
return [c.constructor for c in self._explicit_base_constructor_calls if c.constructor]
@ -387,7 +387,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def functions(self) -> List["Function"]:
"""
list(Function): List of the functions
list(Function): List of the functions
"""
return list(self._functions.values())
@ -409,21 +409,21 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def functions_inherited(self) -> List["Function"]:
"""
list(Function): List of the inherited functions
list(Function): List of the inherited functions
"""
return [f for f in self.functions if f.contract_declarer != self]
@property
def functions_declared(self) -> List["Function"]:
"""
list(Function): List of the functions defined within the contract (not inherited)
list(Function): List of the functions defined within the contract (not inherited)
"""
return [f for f in self.functions if f.contract_declarer == self]
@property
def functions_entry_points(self) -> List["Function"]:
"""
list(Functions): List of public and external functions
list(Functions): List of public and external functions
"""
return [
f
@ -434,7 +434,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def modifiers(self) -> List["Modifier"]:
"""
list(Modifier): List of the modifiers
list(Modifier): List of the modifiers
"""
return list(self._modifiers.values())
@ -453,35 +453,35 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def modifiers_inherited(self) -> List["Modifier"]:
"""
list(Modifier): List of the inherited modifiers
list(Modifier): List of the inherited modifiers
"""
return [m for m in self.modifiers if m.contract_declarer != self]
@property
def modifiers_declared(self) -> List["Modifier"]:
"""
list(Modifier): List of the modifiers defined within the contract (not inherited)
list(Modifier): List of the modifiers defined within the contract (not inherited)
"""
return [m for m in self.modifiers if m.contract_declarer == self]
@property
def functions_and_modifiers(self) -> List["Function"]:
"""
list(Function|Modifier): List of the functions and modifiers
list(Function|Modifier): List of the functions and modifiers
"""
return self.functions + self.modifiers # type: ignore
@property
def functions_and_modifiers_inherited(self) -> List["Function"]:
"""
list(Function|Modifier): List of the inherited functions and modifiers
list(Function|Modifier): List of the inherited functions and modifiers
"""
return self.functions_inherited + self.modifiers_inherited # type: ignore
@property
def functions_and_modifiers_declared(self) -> List["Function"]:
"""
list(Function|Modifier): List of the functions and modifiers defined within the contract (not inherited)
list(Function|Modifier): List of the functions and modifiers defined within the contract (not inherited)
"""
return self.functions_declared + self.modifiers_declared # type: ignore
@ -526,21 +526,21 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def inheritance(self) -> List["Contract"]:
"""
list(Contract): Inheritance list. Order: the first elem is the first father to be executed
list(Contract): Inheritance list. Order: the first elem is the first father to be executed
"""
return list(self._inheritance)
@property
def immediate_inheritance(self) -> List["Contract"]:
"""
list(Contract): List of contracts immediately inherited from (fathers). Order: order of declaration.
list(Contract): List of contracts immediately inherited from (fathers). Order: order of declaration.
"""
return list(self._immediate_inheritance)
@property
def inheritance_reverse(self) -> List["Contract"]:
"""
list(Contract): Inheritance list. Order: the last elem is the first father to be executed
list(Contract): Inheritance list. Order: the last elem is the first father to be executed
"""
return list(reversed(self._inheritance))
@ -557,7 +557,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def derived_contracts(self) -> List["Contract"]:
"""
list(Contract): Return the list of contracts derived from self
list(Contract): Return the list of contracts derived from self
"""
candidates = self.slither.contracts
return [c for c in candidates if self in c.inheritance]
@ -571,13 +571,13 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
def get_functions_reading_from_variable(self, variable: "Variable") -> List["Function"]:
"""
Return the functions reading the variable
Return the functions reading the variable
"""
return [f for f in self.functions if f.is_reading(variable)]
def get_functions_writing_to_variable(self, variable: "Variable") -> List["Function"]:
"""
Return the functions writting the variable
Return the functions writting the variable
"""
return [f for f in self.functions if f.is_writing(variable)]
@ -596,9 +596,9 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
def get_modifier_from_signature(self, modifier_signature: str) -> Optional["Modifier"]:
"""
Return a modifier from a signature
Return a modifier from a signature
:param modifier_signature:
:param modifier_signature:
"""
return next(
(m for m in self.modifiers if m.full_name == modifier_signature and not m.is_shadowed),
@ -627,9 +627,9 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
def get_state_variable_from_name(self, variable_name: str) -> Optional["StateVariable"]:
"""
Return a state variable from a name
Return a state variable from a name
:param variable_name:
:param variable_name:
"""
return next((v for v in self.state_variables if v.name == variable_name), None)
@ -728,8 +728,8 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def all_functions_called(self) -> List["Function"]:
"""
list(Function): List of functions reachable from the contract
Includes super, and private/internal functions not shadowed
list(Function): List of functions reachable from the contract
Includes super, and private/internal functions not shadowed
"""
all_calls = [f for f in self.functions + self.modifiers if not f.is_shadowed] # type: ignore
all_callss = [f.all_internal_calls() for f in all_calls] + [all_calls]
@ -746,7 +746,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def all_state_variables_written(self) -> List["StateVariable"]:
"""
list(StateVariable): List all of the state variables written
list(StateVariable): List all of the state variables written
"""
all_state_variables_written = [
f.all_state_variables_written() for f in self.functions + self.modifiers # type: ignore
@ -759,7 +759,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def all_state_variables_read(self) -> List["StateVariable"]:
"""
list(StateVariable): List all of the state variables read
list(StateVariable): List all of the state variables read
"""
all_state_variables_read = [
f.all_state_variables_read() for f in self.functions + self.modifiers # type: ignore
@ -772,7 +772,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def all_library_calls(self) -> List["LibraryCallType"]:
"""
list((Contract, Function): List all of the libraries func called
list((Contract, Function): List all of the libraries func called
"""
all_high_level_calls = [f.all_library_calls() for f in self.functions + self.modifiers] # type: ignore
all_high_level_calls = [item for sublist in all_high_level_calls for item in sublist]
@ -781,7 +781,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
@property
def all_high_level_calls(self) -> List["HighLevelCallType"]:
"""
list((Contract, Function|Variable)): List all of the external high level calls
list((Contract, Function|Variable)): List all of the external high level calls
"""
all_high_level_calls = [f.all_high_level_calls() for f in self.functions + self.modifiers] # type: ignore
all_high_level_calls = [item for sublist in all_high_level_calls for item in sublist]
@ -797,7 +797,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
def get_summary(
self, include_shadowed=True
) -> Tuple[str, List[str], List[str], List[str], List[str]]:
""" Return the function summary
"""Return the function summary
:param include_shadowed: boolean to indicate if shadowed functions should be included (default True)
Returns:
@ -818,7 +818,7 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
)
def is_signature_only(self) -> bool:
""" Detect if the contract has only abstract functions
"""Detect if the contract has only abstract functions
Returns:
bool: true if the function are abstract functions

@ -24,7 +24,7 @@ class Event(ChildContract, SourceMapping):
@property
def signature(self) -> Tuple[str, List[str]]:
""" Return the function signature
"""Return the function signature
Returns:
(str, list(str)): name, list parameters type
"""
@ -32,7 +32,7 @@ class Event(ChildContract, SourceMapping):
@property
def full_name(self) -> str:
""" Return the function signature as a str
"""Return the function signature as a str
Returns:
str: func_name(type1,type2)
"""
@ -41,7 +41,7 @@ class Event(ChildContract, SourceMapping):
@property
def canonical_name(self) -> str:
""" Return the function signature as a str
"""Return the function signature as a str
Returns:
str: contract.func_name(type1,type2)
"""

@ -53,7 +53,10 @@ ReacheableNode = namedtuple("ReacheableNode", ["node", "ir"])
class ModifierStatements:
def __init__(
self, modifier: Union["Contract", "Function"], entry_point: "Node", nodes: List["Node"],
self,
modifier: Union["Contract", "Function"],
entry_point: "Node",
nodes: List["Node"],
):
self._modifier = modifier
self._entry_point = entry_point
@ -107,7 +110,7 @@ class Function(
ChildContract, ChildInheritance, SourceMapping
): # pylint: disable=too-many-public-methods
"""
Function class
Function class
"""
def __init__(self):
@ -206,7 +209,7 @@ class Function(
@property
def name(self) -> str:
"""
str: function name
str: function name
"""
if self._name == "" and self._function_type == FunctionType.CONSTRUCTOR:
return "constructor"
@ -241,8 +244,8 @@ class Function(
@property
def full_name(self) -> str:
"""
str: func_name(type1,type2)
Return the function signature without the return values
str: func_name(type1,type2)
Return the function signature without the return values
"""
name, parameters, _ = self.signature
return ".".join(self._scope + [name]) + "(" + ",".join(parameters) + ")"
@ -250,8 +253,8 @@ class Function(
@property
def canonical_name(self) -> str:
"""
str: contract.func_name(type1,type2)
Return the function signature without the return values
str: contract.func_name(type1,type2)
Return the function signature without the return values
"""
name, parameters, _ = self.signature
return (
@ -339,15 +342,15 @@ class Function(
@property
def is_constructor(self) -> bool:
"""
bool: True if the function is the constructor
bool: True if the function is the constructor
"""
return self._function_type == FunctionType.CONSTRUCTOR
@property
def is_constructor_variables(self) -> bool:
"""
bool: True if the function is the constructor of the variables
Slither has inbuilt functions to hold the state variables initialization
bool: True if the function is the constructor of the variables
Slither has inbuilt functions to hold the state variables initialization
"""
return self._function_type in [
FunctionType.CONSTRUCTOR_VARIABLES,
@ -382,7 +385,7 @@ class Function(
@property
def payable(self) -> bool:
"""
bool: True if the function is payable
bool: True if the function is payable
"""
return self._payable
@ -400,7 +403,7 @@ class Function(
@property
def visibility(self) -> str:
"""
str: Function visibility
str: Function visibility
"""
assert self._visibility is not None
return self._visibility
@ -415,7 +418,7 @@ class Function(
@property
def view(self) -> bool:
"""
bool: True if the function is declared as view
bool: True if the function is declared as view
"""
return self._view
@ -426,7 +429,7 @@ class Function(
@property
def pure(self) -> bool:
"""
bool: True if the function is declared as pure
bool: True if the function is declared as pure
"""
return self._pure
@ -460,7 +463,7 @@ class Function(
@property
def is_implemented(self) -> bool:
"""
bool: True if the function is implemented
bool: True if the function is implemented
"""
return self._is_implemented
@ -471,7 +474,7 @@ class Function(
@property
def is_empty(self) -> bool:
"""
bool: True if the function is empty, None if the function is an interface
bool: True if the function is empty, None if the function is an interface
"""
return self._is_empty
@ -489,7 +492,7 @@ class Function(
@property
def nodes(self) -> List["Node"]:
"""
list(Node): List of the nodes
list(Node): List of the nodes
"""
return list(self._nodes)
@ -500,7 +503,7 @@ class Function(
@property
def entry_point(self) -> "Node":
"""
Node: Entry point of the function
Node: Entry point of the function
"""
return self._entry_point
@ -548,7 +551,7 @@ class Function(
@property
def parameters(self) -> List["LocalVariable"]:
"""
list(LocalVariable): List of the parameters
list(LocalVariable): List of the parameters
"""
return list(self._parameters)
@ -558,7 +561,7 @@ class Function(
@property
def parameters_ssa(self) -> List["LocalIRVariable"]:
"""
list(LocalIRVariable): List of the parameters (SSA form)
list(LocalIRVariable): List of the parameters (SSA form)
"""
return list(self._parameters_ssa)
@ -575,8 +578,8 @@ class Function(
@property
def return_type(self) -> Optional[List[Type]]:
"""
Return the list of return type
If no return, return None
Return the list of return type
If no return, return None
"""
returns = self.returns
if returns:
@ -586,16 +589,16 @@ class Function(
@property
def type(self) -> Optional[List[Type]]:
"""
Return the list of return type
If no return, return None
Alias of return_type
Return the list of return type
If no return, return None
Alias of return_type
"""
return self.return_type
@property
def returns(self) -> List["LocalVariable"]:
"""
list(LocalVariable): List of the return variables
list(LocalVariable): List of the return variables
"""
return list(self._returns)
@ -605,7 +608,7 @@ class Function(
@property
def returns_ssa(self) -> List["LocalIRVariable"]:
"""
list(LocalIRVariable): List of the return variables (SSA form)
list(LocalIRVariable): List of the return variables (SSA form)
"""
return list(self._returns_ssa)
@ -622,8 +625,8 @@ class Function(
@property
def modifiers(self) -> List[Union["Contract", "Function"]]:
"""
list(Modifier): List of the modifiers
Can be contract for constructor's calls
list(Modifier): List of the modifiers
Can be contract for constructor's calls
"""
return [c.modifier for c in self._modifiers]
@ -634,17 +637,17 @@ class Function(
@property
def modifiers_statements(self) -> List[ModifierStatements]:
"""
list(ModifierCall): List of the modifiers call (include expression and irs)
list(ModifierCall): List of the modifiers call (include expression and irs)
"""
return list(self._modifiers)
@property
def explicit_base_constructor_calls(self) -> List["Function"]:
"""
list(Function): List of the base constructors called explicitly by this presumed constructor definition.
list(Function): List of the base constructors called explicitly by this presumed constructor definition.
Base constructors implicitly or explicitly called by the contract definition will not be
included.
Base constructors implicitly or explicitly called by the contract definition will not be
included.
"""
# This is a list of contracts internally, so we convert it to a list of constructor functions.
return [
@ -656,7 +659,7 @@ class Function(
@property
def explicit_base_constructor_calls_statements(self) -> List[ModifierStatements]:
"""
list(ModifierCall): List of the base constructors called explicitly by this presumed constructor definition.
list(ModifierCall): List of the base constructors called explicitly by this presumed constructor definition.
"""
# This is a list of contracts internally, so we convert it to a list of constructor functions.
@ -675,15 +678,15 @@ class Function(
@property
def variables(self) -> List[LocalVariable]:
"""
Return all local variables
Include paramters and return values
Return all local variables
Include paramters and return values
"""
return list(self._variables.values())
@property
def local_variables(self) -> List[LocalVariable]:
"""
Return all local variables (dont include paramters and return values)
Return all local variables (dont include paramters and return values)
"""
return list(set(self.variables) - set(self.returns) - set(self.parameters))
@ -694,42 +697,42 @@ class Function(
@property
def variables_read(self) -> List["Variable"]:
"""
list(Variable): Variables read (local/state/solidity)
list(Variable): Variables read (local/state/solidity)
"""
return list(self._vars_read)
@property
def variables_written(self) -> List["Variable"]:
"""
list(Variable): Variables written (local/state/solidity)
list(Variable): Variables written (local/state/solidity)
"""
return list(self._vars_written)
@property
def state_variables_read(self) -> List["StateVariable"]:
"""
list(StateVariable): State variables read
list(StateVariable): State variables read
"""
return list(self._state_vars_read)
@property
def solidity_variables_read(self) -> List["SolidityVariable"]:
"""
list(SolidityVariable): Solidity variables read
list(SolidityVariable): Solidity variables read
"""
return list(self._solidity_vars_read)
@property
def state_variables_written(self) -> List["StateVariable"]:
"""
list(StateVariable): State variables written
list(StateVariable): State variables written
"""
return list(self._state_vars_written)
@property
def variables_read_or_written(self) -> List["Variable"]:
"""
list(Variable): Variables read or written (local/state/solidity)
list(Variable): Variables read or written (local/state/solidity)
"""
return list(self._vars_read_or_written)
@ -744,7 +747,7 @@ class Function(
@property
def slithir_variables(self) -> List["SlithIRVariable"]:
"""
Temporary and Reference Variables (not SSA form)
Temporary and Reference Variables (not SSA form)
"""
return list(self._slithir_variables)
@ -759,48 +762,48 @@ class Function(
@property
def internal_calls(self) -> List["InternalCallType"]:
"""
list(Function or SolidityFunction): List of function calls (that does not create a transaction)
list(Function or SolidityFunction): List of function calls (that does not create a transaction)
"""
return list(self._internal_calls)
@property
def solidity_calls(self) -> List[SolidityFunction]:
"""
list(SolidityFunction): List of Soldity calls
list(SolidityFunction): List of Soldity calls
"""
return list(self._solidity_calls)
@property
def high_level_calls(self) -> List["HighLevelCallType"]:
"""
list((Contract, Function|Variable)):
List of high level calls (external calls).
A variable is called in case of call to a public state variable
Include library calls
list((Contract, Function|Variable)):
List of high level calls (external calls).
A variable is called in case of call to a public state variable
Include library calls
"""
return list(self._high_level_calls)
@property
def library_calls(self) -> List["LibraryCallType"]:
"""
list((Contract, Function)):
list((Contract, Function)):
"""
return list(self._library_calls)
@property
def low_level_calls(self) -> List["LowLevelCallType"]:
"""
list((Variable|SolidityVariable, str)): List of low_level call
A low level call is defined by
- the variable called
- the name of the function (call/delegatecall/codecall)
list((Variable|SolidityVariable, str)): List of low_level call
A low level call is defined by
- the variable called
- the name of the function (call/delegatecall/codecall)
"""
return list(self._low_level_calls)
@property
def external_calls_as_expressions(self) -> List["Expression"]:
"""
list(ExpressionCall): List of message calls (that creates a transaction)
list(ExpressionCall): List of message calls (that creates a transaction)
"""
return list(self._external_calls_as_expressions)
@ -818,7 +821,7 @@ class Function(
@property
def expressions(self) -> List["Expression"]:
"""
list(Expression): List of the expressions
list(Expression): List of the expressions
"""
if self._expressions is None:
expressionss = [n.expression for n in self.nodes]
@ -829,7 +832,7 @@ class Function(
@property
def return_values(self) -> List["SlithIRVariable"]:
"""
list(Return Values): List of the return values
list(Return Values): List of the return values
"""
from slither.core.cfg.node import NodeType
from slither.slithir.operations import Return
@ -850,7 +853,7 @@ class Function(
@property
def return_values_ssa(self) -> List["SlithIRVariable"]:
"""
list(Return Values in SSA form): List of the return values in ssa form
list(Return Values in SSA form): List of the return values in ssa form
"""
from slither.core.cfg.node import NodeType
from slither.slithir.operations import Return
@ -880,7 +883,7 @@ class Function(
@property
def slithir_operations(self) -> List["Operation"]:
"""
list(Operation): List of the slithir operations
list(Operation): List of the slithir operations
"""
if self._slithir_operations is None:
operationss = [n.irs for n in self.nodes]
@ -891,7 +894,7 @@ class Function(
@property
def slithir_ssa_operations(self) -> List["Operation"]:
"""
list(Operation): List of the slithir operations (SSA)
list(Operation): List of the slithir operations (SSA)
"""
if self._slithir_ssa_operations is None:
operationss = [n.irs_ssa for n in self.nodes]
@ -927,8 +930,8 @@ class Function(
@property
def signature(self) -> Tuple[str, List[str], List[str]]:
"""
(str, list(str), list(str)): Function signature as
(name, list parameters type, list return values type)
(str, list(str), list(str)): Function signature as
(name, list parameters type, list return values type)
"""
return (
self.name,
@ -939,8 +942,8 @@ class Function(
@property
def signature_str(self) -> str:
"""
str: func_name(type1,type2) returns (type3)
Return the function signature as a str (contains the return values)
str: func_name(type1,type2) returns (type3)
Return the function signature as a str (contains the return values)
"""
name, parameters, returnVars = self.signature
return name + "(" + ",".join(parameters) + ") returns(" + ",".join(returnVars) + ")"
@ -974,8 +977,8 @@ class Function(
@property
def reachable_from_nodes(self) -> Set[ReacheableNode]:
"""
Return
ReacheableNode
Return
ReacheableNode
"""
return self._reachable_from_nodes
@ -1029,8 +1032,7 @@ class Function(
return list(set(values))
def all_state_variables_read(self) -> List["StateVariable"]:
""" recursive version of variables_read
"""
"""recursive version of variables_read"""
if self._all_state_variables_read is None:
self._all_state_variables_read = self._explore_functions(
lambda x: x.state_variables_read
@ -1038,8 +1040,7 @@ class Function(
return self._all_state_variables_read
def all_solidity_variables_read(self) -> List[SolidityVariable]:
""" recursive version of solidity_read
"""
"""recursive version of solidity_read"""
if self._all_solidity_variables_read is None:
self._all_solidity_variables_read = self._explore_functions(
lambda x: x.solidity_variables_read
@ -1047,22 +1048,19 @@ class Function(
return self._all_solidity_variables_read
def all_slithir_variables(self) -> List["SlithIRVariable"]:
""" recursive version of slithir_variables
"""
"""recursive version of slithir_variables"""
if self._all_slithir_variables is None:
self._all_slithir_variables = self._explore_functions(lambda x: x.slithir_variables)
return self._all_slithir_variables
def all_nodes(self) -> List["Node"]:
""" recursive version of nodes
"""
"""recursive version of nodes"""
if self._all_nodes is None:
self._all_nodes = self._explore_functions(lambda x: x.nodes)
return self._all_nodes
def all_expressions(self) -> List["Expression"]:
""" recursive version of variables_read
"""
"""recursive version of variables_read"""
if self._all_expressions is None:
self._all_expressions = self._explore_functions(lambda x: x.expressions)
return self._all_expressions
@ -1073,8 +1071,7 @@ class Function(
return self._all_slithir_operations
def all_state_variables_written(self) -> List[StateVariable]:
""" recursive version of variables_written
"""
"""recursive version of variables_written"""
if self._all_state_variables_written is None:
self._all_state_variables_written = self._explore_functions(
lambda x: x.state_variables_written
@ -1082,36 +1079,31 @@ class Function(
return self._all_state_variables_written
def all_internal_calls(self) -> List["InternalCallType"]:
""" recursive version of internal_calls
"""
"""recursive version of internal_calls"""
if self._all_internals_calls is None:
self._all_internals_calls = self._explore_functions(lambda x: x.internal_calls)
return self._all_internals_calls
def all_low_level_calls(self) -> List["LowLevelCallType"]:
""" recursive version of low_level calls
"""
"""recursive version of low_level calls"""
if self._all_low_level_calls is None:
self._all_low_level_calls = self._explore_functions(lambda x: x.low_level_calls)
return self._all_low_level_calls
def all_high_level_calls(self) -> List["HighLevelCallType"]:
""" recursive version of high_level calls
"""
"""recursive version of high_level calls"""
if self._all_high_level_calls is None:
self._all_high_level_calls = self._explore_functions(lambda x: x.high_level_calls)
return self._all_high_level_calls
def all_library_calls(self) -> List["LibraryCallType"]:
""" recursive version of library calls
"""
"""recursive version of library calls"""
if self._all_library_calls is None:
self._all_library_calls = self._explore_functions(lambda x: x.library_calls)
return self._all_library_calls
def all_solidity_calls(self) -> List[SolidityFunction]:
""" recursive version of solidity calls
"""
"""recursive version of solidity calls"""
if self._all_solidity_calls is None:
self._all_solidity_calls = self._explore_functions(lambda x: x.solidity_calls)
return self._all_solidity_calls
@ -1123,10 +1115,10 @@ class Function(
def all_conditional_state_variables_read(self, include_loop=True) -> List["StateVariable"]:
"""
Return the state variable used in a condition
Return the state variable used in a condition
Over approximate and also return index access
It won't work if the variable is assigned to a temp variable
Over approximate and also return index access
It won't work if the variable is assigned to a temp variable
"""
if include_loop:
if self._all_conditional_state_variables_read_with_loop is None:
@ -1152,18 +1144,20 @@ class Function(
@staticmethod
def _explore_func_conditional(
func: "Function", f: Callable[["Node"], List[SolidityVariable]], include_loop: bool,
func: "Function",
f: Callable[["Node"], List[SolidityVariable]],
include_loop: bool,
):
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]:
"""
Return the Soldiity variables directly used in a condtion
Return the Soldiity variables directly used in a condtion
Use of the IR to filter index access
Assumption: the solidity vars are used directly in the conditional node
It won't work if the variable is assigned to a temp variable
Use of the IR to filter index access
Assumption: the solidity vars are used directly in the conditional node
It won't work if the variable is assigned to a temp variable
"""
if include_loop:
if self._all_conditional_solidity_variables_read_with_loop is None:
@ -1199,10 +1193,10 @@ class Function(
def all_solidity_variables_used_as_args(self) -> List[SolidityVariable]:
"""
Return the Soldiity variables directly used in a call
Return the Soldiity variables directly used in a call
Use of the IR to filter index access
Used to catch check(msg.sender)
Use of the IR to filter index access
Used to catch check(msg.sender)
"""
if self._all_solidity_variables_used_as_args is None:
self._all_solidity_variables_used_as_args = self._explore_functions(
@ -1432,9 +1426,7 @@ class Function(
###################################################################################
def _analyze_read_write(self):
""" Compute variables read/written/...
"""
"""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]
write_var = [item for sublist in write_var for item in sublist]
@ -1610,10 +1602,14 @@ class Function(
return ret
def get_last_ssa_state_variables_instances(self,) -> Dict[str, Set["SlithIRVariable"]]:
def get_last_ssa_state_variables_instances(
self,
) -> Dict[str, Set["SlithIRVariable"]]:
return self._get_last_ssa_variable_instances(target_state=True, target_local=False)
def get_last_ssa_local_variables_instances(self,) -> Dict[str, Set["SlithIRVariable"]]:
def get_last_ssa_local_variables_instances(
self,
) -> Dict[str, Set["SlithIRVariable"]]:
return self._get_last_ssa_variable_instances(target_state=False, target_local=True)
@staticmethod

@ -11,7 +11,7 @@ class Pragma(SourceMapping):
@property
def directive(self) -> List[str]:
"""
list(str)
list(str)
"""
return self._directive

@ -17,10 +17,10 @@ def intersection_predecessor(node: "Node"):
def compute_dominators(nodes: List["Node"]):
"""
Naive implementation of Cooper, Harvey, Kennedy algo
See 'A Simple,Fast Dominance Algorithm'
Naive implementation of Cooper, Harvey, Kennedy algo
See 'A Simple,Fast Dominance Algorithm'
Compute strict domniators
Compute strict domniators
"""
changed = True
@ -59,10 +59,10 @@ def compute_dominators(nodes: List["Node"]):
def compute_dominance_frontier(nodes: List["Node"]):
"""
Naive implementation of Cooper, Harvey, Kennedy algo
See 'A Simple,Fast Dominance Algorithm'
Naive implementation of Cooper, Harvey, Kennedy algo
See 'A Simple,Fast Dominance Algorithm'
Compute dominance frontier
Compute dominance frontier
"""
for node in nodes:
if len(node.fathers) >= 2:

@ -32,7 +32,7 @@ logging.basicConfig()
def _relative_path_format(path: str) -> str:
"""
Strip relative paths of "." and ".."
Strip relative paths of "." and ".."
"""
return path.split("..")[-1].strip(".").strip("/")
@ -251,7 +251,7 @@ class SlitherCore(Context): # pylint: disable=too-many-instance-attributes,too-
def print_functions(self, d: str):
"""
Export all the functions to dot files
Export all the functions to dot files
"""
for c in self.contracts:
for f in c.functions:
@ -266,11 +266,11 @@ class SlitherCore(Context): # pylint: disable=too-many-instance-attributes,too-
def valid_result(self, r: Dict) -> bool:
"""
Check if the result is valid
A result is invalid if:
- All its source paths belong to the source path filtered
- Or a similar result was reported and saved during a previous run
- The --exclude-dependencies flag is set and results are only related to dependencies
Check if the result is valid
A result is invalid if:
- All its source paths belong to the source path filtered
- Or a similar result was reported and saved during a previous run
- The --exclude-dependencies flag is set and results are only related to dependencies
"""
source_mapping_elements = [
elem["source_mapping"]["filename_absolute"]
@ -334,8 +334,8 @@ class SlitherCore(Context): # pylint: disable=too-many-instance-attributes,too-
def add_path_to_filter(self, path: str):
"""
Add path to filter
Path are used through direct comparison (no regex)
Add path to filter
Path are used through direct comparison (no regex)
"""
self._paths_to_filter.add(path)

@ -6,7 +6,9 @@ from slither.core.variables.function_type_variable import FunctionTypeVariable
class FunctionType(Type):
def __init__(
self, params: List[FunctionTypeVariable], return_values: List[FunctionTypeVariable],
self,
params: List[FunctionTypeVariable],
return_values: List[FunctionTypeVariable],
):
assert all(isinstance(x, FunctionTypeVariable) for x in params)
assert all(isinstance(x, FunctionTypeVariable) for x in return_values)
@ -42,7 +44,7 @@ class FunctionType(Type):
@property
def parameters_signature(self) -> str:
"""
Return the parameters signature(without the return statetement)
Return the parameters signature(without the return statetement)
"""
# Use x.type
# x.name may be empty
@ -52,7 +54,7 @@ class FunctionType(Type):
@property
def signature(self) -> str:
"""
Return the signature(with the return statetement if it exists)
Return the signature(with the return statetement if it exists)
"""
# Use x.type
# x.name may be empty

@ -17,10 +17,10 @@ class SourceMapping(Context):
@staticmethod
def _compute_line(source_code, start, length):
"""
Compute line(s) numbers and starting/ending columns
from a start/end offset. All numbers start from 1.
Compute line(s) numbers and starting/ending columns
from a start/end offset. All numbers start from 1.
Not done in an efficient way
Not done in an efficient way
"""
source_code = source_code.encode("utf-8")
total_length = len(source_code)

@ -5,11 +5,11 @@ from slither.core.variables.local_variable import LocalVariable
class LocalVariableInitFromTuple(LocalVariable):
"""
Use on this pattern:
var(a,b) = f()
Use on this pattern:
var(a,b) = f()
It is not possible to split the variable declaration in sigleton and keep the init value
We init a and b with f(). get_tuple_index ret() returns which returns values of f is to be used
It is not possible to split the variable declaration in sigleton and keep the init value
We init a and b with f(). get_tuple_index ret() returns which returns values of f is to be used
"""

@ -31,8 +31,8 @@ class StateVariable(ChildContract, Variable):
@property
def signature(self) -> Tuple[str, List[str], str]:
"""
Return the signature of the state variable as a function signature
:return: (str, list(str), list(str)), as (name, list parameters type, list return values type)
Return the signature of the state variable as a function signature
:return: (str, list(str), list(str)), as (name, list parameters type, list return values type)
"""
return (
self.name,
@ -43,8 +43,8 @@ class StateVariable(ChildContract, Variable):
@property
def signature_str(self) -> str:
"""
Return the signature of the state variable as a function signature
:return: str: func_name(type1,type2) returns(type3)
Return the signature of the state variable as a function signature
:return: str: func_name(type1,type2) returns(type3)
"""
name, parameters, returnVars = self.signature
return name + "(" + ",".join(parameters) + ") returns(" + ",".join(returnVars) + ")"
@ -63,9 +63,9 @@ class StateVariable(ChildContract, Variable):
@property
def full_name(self) -> str:
"""
Return the name of the state variable as a function signaure
str: func_name(type1,type2)
:return: the function signature without the return values
Return the name of the state variable as a function signaure
str: func_name(type1,type2)
:return: the function signature without the return values
"""
name, parameters, _ = self.signature
return name + "(" + ",".join(parameters) + ")"

@ -28,14 +28,14 @@ class Variable(SourceMapping):
@property
def expression(self) -> Optional["Expression"]:
"""
Expression: Expression of the node (if initialized)
Initial expression may be different than the expression of the node
where the variable is declared, if its used ternary operator
Ex: uint a = b?1:2
The expression associated to a is uint a = b?1:2
But two nodes are created,
one where uint a = 1,
and one where uint a = 2
Expression: Expression of the node (if initialized)
Initial expression may be different than the expression of the node
where the variable is declared, if its used ternary operator
Ex: uint a = b?1:2
The expression associated to a is uint a = b?1:2
But two nodes are created,
one where uint a = 1,
and one where uint a = 2
"""
return self._initial_expression
@ -47,7 +47,7 @@ class Variable(SourceMapping):
@property
def initialized(self) -> Optional[bool]:
"""
boolean: True if the variable is initialized at construction
boolean: True if the variable is initialized at construction
"""
return self._initialized
@ -58,14 +58,14 @@ class Variable(SourceMapping):
@property
def uninitialized(self) -> bool:
"""
boolean: True if the variable is not initialized
boolean: True if the variable is not initialized
"""
return not self._initialized
@property
def name(self) -> str:
"""
str: variable name
str: variable name
"""
return self._name
@ -92,7 +92,7 @@ class Variable(SourceMapping):
@property
def visibility(self) -> Optional[str]:
"""
str: variable visibility
str: variable visibility
"""
return self._visibility

@ -45,7 +45,7 @@ All the calls to `get` revert, breaking Bob's smart contract execution."""
)
def _detect(self):
""" Detect the constant function using assembly code
"""Detect the constant function using assembly code
Recursively visit the calls
Returns:

@ -45,7 +45,7 @@ All the calls to `get` revert, breaking Bob's smart contract execution."""
)
def _detect(self):
""" Detect the constant function changing the state
"""Detect the constant function changing the state
Recursively visit the calls
Returns:

@ -53,7 +53,8 @@ Every Ether sent to `Locked` will be lost."""
for node in function.nodes:
for ir in node.irs:
if isinstance(
ir, (Send, Transfer, HighLevelCall, LowLevelCall, NewContract),
ir,
(Send, Transfer, HighLevelCall, LowLevelCall, NewContract),
):
if ir.call_value and ir.call_value != 0:
return False

@ -66,7 +66,7 @@ contract Token{
@staticmethod
def detect_incorrect_erc20_interface(contract):
""" Detect incorrect ERC20 interface
"""Detect incorrect ERC20 interface
Returns:
list(str) : list of incorrect function signatures
@ -91,7 +91,7 @@ contract Token{
return functions
def _detect(self):
""" Detect incorrect erc20 interface
"""Detect incorrect erc20 interface
Returns:
dict: [contract name] = set(str) events

@ -81,7 +81,7 @@ contract Token{
@staticmethod
def detect_incorrect_erc721_interface(contract):
""" Detect incorrect ERC721 interface
"""Detect incorrect ERC721 interface
Returns:
list(str) : list of incorrect function signatures
@ -100,7 +100,7 @@ contract Token{
return functions
def _detect(self):
""" Detect incorrect erc721 interface
"""Detect incorrect erc721 interface
Returns:
dict: [contract name] = set(str) events

@ -41,7 +41,9 @@ def arbitrary_send(func):
if ir.variable_right == SolidityVariableComposed("msg.sender"):
return False
if is_dependent(
ir.variable_right, SolidityVariableComposed("msg.sender"), func.contract,
ir.variable_right,
SolidityVariableComposed("msg.sender"),
func.contract,
):
return False
if isinstance(ir, (HighLevelCall, LowLevelCall, Transfer, Send)):
@ -54,7 +56,9 @@ def arbitrary_send(func):
if ir.call_value == SolidityVariableComposed("msg.value"):
continue
if is_dependent(
ir.call_value, SolidityVariableComposed("msg.value"), func.contract,
ir.call_value,
SolidityVariableComposed("msg.value"),
func.contract,
):
continue
@ -108,8 +112,7 @@ Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract
WIKI_RECOMMENDATION = "Ensure that an arbitrary user cannot withdraw unauthorized funds."
def _detect(self):
"""
"""
""""""
results = []
for c in self.contracts:

@ -27,7 +27,7 @@ class ExternalFunction(AbstractDetector):
@staticmethod
def detect_functions_called(contract):
""" Returns a list of InternallCall, SolidityCall
"""Returns a list of InternallCall, SolidityCall
calls made in a function
Returns:

@ -35,7 +35,7 @@ Bob calls `kill` and destructs the contract."""
@staticmethod
def detect_suicidal_func(func):
""" Detect if the function is suicidal
"""Detect if the function is suicidal
Detect the public functions calling suicide/selfdestruct without protection
Returns:
@ -65,8 +65,7 @@ Bob calls `kill` and destructs the contract."""
return ret
def _detect(self):
""" Detect the suicidal functions
"""
"""Detect the suicidal functions"""
results = []
for c in self.contracts:
functions = self.detect_suicidal(c)

@ -86,10 +86,14 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2
if func.is_constructor:
continue
if not self.is_mixed_case(func.name):
if func.visibility in [
"internal",
"private",
] and self.is_mixed_case_with_underscore(func.name):
if (
func.visibility
in [
"internal",
"private",
]
and self.is_mixed_case_with_underscore(func.name)
):
continue
if func.name.startswith("echidna_") or func.name.startswith("crytic_"):
continue
@ -125,7 +129,11 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2
res = self.generate_result(info)
res.add(
var, {"target": "variable", "convention": "l_O_I_should_not_be_used",},
var,
{
"target": "variable",
"convention": "l_O_I_should_not_be_used",
},
)
results.append(res)

@ -36,7 +36,9 @@ def _timestamp(func: Function) -> List[Node]:
return sorted(list(ret), key=lambda x: x.node_id)
def _detect_dangerous_timestamp(contract: Contract,) -> List[Tuple[Function, List[Node]]]:
def _detect_dangerous_timestamp(
contract: Contract,
) -> List[Tuple[Function, List[Node]]]:
"""
Args:
contract (Contract)
@ -68,8 +70,7 @@ class Timestamp(AbstractDetector):
WIKI_RECOMMENDATION = "Avoid relying on `block.timestamp`."
def _detect(self):
"""
"""
""""""
results = []
for c in self.contracts:

@ -41,8 +41,7 @@ class LowLevelCalls(AbstractDetector):
return ret
def _detect(self):
""" Detect the functions that use low level calls
"""
"""Detect the functions that use low level calls"""
results = []
for c in self.contracts:
values = self.detect_low_level_calls(c)

@ -65,8 +65,7 @@ contract MyConc{
return [nodes_origin[value].node for value in values_returned]
def _detect(self):
""" Detect high level calls which return a value that are never used
"""
"""Detect high level calls which return a value that are never used"""
results = []
for c in self.slither.contracts:
for f in c.functions + c.modifiers:

@ -24,8 +24,7 @@ contract B is A{
When reading `B`'s constructor definition, we might assume that `A()` initiates the contract, but no code is executed."""
def _detect(self):
"""
"""
""""""
results = []
for c in self.contracts:
cst = c.constructor

@ -127,7 +127,8 @@ class AbstractState:
)
self._reads = union_dict(self._reads, father.context[detector.KEY].reads)
self._reads_prior_calls = union_dict(
self.reads_prior_calls, father.context[detector.KEY].reads_prior_calls,
self.reads_prior_calls,
father.context[detector.KEY].reads_prior_calls,
)
def analyze_node(self, node, detector):
@ -191,14 +192,14 @@ class AbstractState:
def _filter_if(node):
"""
Check if the node is a condtional node where
there is an external call checked
Heuristic:
- The call is a IF node
- It contains a, external call
- The condition is the negation (!)
This will work only on naive implementation
Check if the node is a condtional node where
there is an external call checked
Heuristic:
- The call is a IF node
- It contains a, external call
- The condition is the negation (!)
This will work only on naive implementation
"""
return (
isinstance(node.expression, UnaryOperation)
@ -215,12 +216,12 @@ class Reentrancy(AbstractDetector):
@staticmethod
def can_callback(ir):
"""
Detect if the node contains a call that can
be used to re-entrance
Detect if the node contains a call that can
be used to re-entrance
Consider as valid target:
- low level call
- high level call
Consider as valid target:
- low level call
- high level call
"""
@ -229,20 +230,20 @@ class Reentrancy(AbstractDetector):
@staticmethod
def can_send_eth(ir):
"""
Detect if the node can send eth
Detect if the node can send eth
"""
return isinstance(ir, Call) and ir.can_send_eth()
def _explore(self, node, visited, skip_father=None):
"""
Explore the CFG and look for re-entrancy
Heuristic: There is a re-entrancy if a state variable is written
after an external call
Explore the CFG and look for re-entrancy
Heuristic: There is a re-entrancy if a state variable is written
after an external call
node.context will contains the external calls executed
It contains the calls executed in father nodes
node.context will contains the external calls executed
It contains the calls executed in father nodes
if node.context is not empty, and variables are written, a re-entrancy is possible
if node.context is not empty, and variables are written, a re-entrancy is possible
"""
if node in visited:
return
@ -289,8 +290,7 @@ class Reentrancy(AbstractDetector):
function.context[self.KEY] = True
def _detect(self):
"""
"""
""""""
# if a node was already visited by another path
# we will only explore it if the traversal brings
# new variables written

@ -63,7 +63,11 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr
if v in node.context[self.KEY].reads_prior_calls[c]
]
not_read_then_written = {
FindingValue(v, node, tuple(sorted(nodes, key=lambda x: x.node_id)),)
FindingValue(
v,
node,
tuple(sorted(nodes, key=lambda x: x.node_id)),
)
for (v, nodes) in node.context[self.KEY].written.items()
if v not in read_then_written
}
@ -78,8 +82,7 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr
return result
def _detect(self): # pylint: disable=too-many-branches
"""
"""
""""""
super()._detect()
reentrancies = self.find_reentrancies()
@ -127,7 +130,8 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
#
@ -139,7 +143,8 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
# Add all variables written via nodes which write them.

@ -63,7 +63,9 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m
continue
read_then_written |= {
FindingValue(
v, node, tuple(sorted(nodes, key=lambda x: x.node_id)),
v,
node,
tuple(sorted(nodes, key=lambda x: x.node_id)),
)
for (v, nodes) in node.context[self.KEY].written.items()
if v in node.context[self.KEY].reads_prior_calls[c]
@ -81,8 +83,7 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m
return result
def _detect(self): # pylint: disable=too-many-branches
"""
"""
""""""
super()._detect()
reentrancies = self.find_reentrancies()
@ -129,7 +130,8 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
# If the calls are not the same ones that send eth, add the eth sending nodes.
@ -139,7 +141,8 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
# Add all variables written via nodes which write them.

@ -61,7 +61,11 @@ If `d.()` re-enters, the `Counter` events will be shown in an incorrect order, w
send_eth=to_hashable(node.context[self.KEY].send_eth),
)
finding_vars = {
FindingValue(e, e.node, tuple(sorted(nodes, key=lambda x: x.node_id)),)
FindingValue(
e,
e.node,
tuple(sorted(nodes, key=lambda x: x.node_id)),
)
for (e, nodes) in node.context[self.KEY].events.items()
}
if finding_vars:
@ -69,8 +73,7 @@ If `d.()` re-enters, the `Counter` events will be shown in an incorrect order, w
return result
def _detect(self): # pylint: disable=too-many-branches
"""
"""
""""""
super()._detect()
reentrancies = self.find_reentrancies()
@ -116,7 +119,8 @@ If `d.()` re-enters, the `Counter` events will be shown in an incorrect order, w
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
#
@ -128,7 +132,8 @@ If `d.()` re-enters, the `Counter` events will be shown in an incorrect order, w
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
for finding_value in events:

@ -72,11 +72,19 @@ Only report reentrancy that is based on `transfer` or `send`."""
send_eth=to_hashable(node.context[self.KEY].send_eth),
)
finding_vars = {
FindingValue(v, node, tuple(sorted(nodes, key=lambda x: x.node_id)),)
FindingValue(
v,
node,
tuple(sorted(nodes, key=lambda x: x.node_id)),
)
for (v, nodes) in node.context[self.KEY].written.items()
}
finding_vars |= {
FindingValue(e, e.node, tuple(sorted(nodes, key=lambda x: x.node_id)),)
FindingValue(
e,
e.node,
tuple(sorted(nodes, key=lambda x: x.node_id)),
)
for (e, nodes) in node.context[self.KEY].events.items()
}
if finding_vars:
@ -84,8 +92,7 @@ Only report reentrancy that is based on `transfer` or `send`."""
return result
def _detect(self): # pylint: disable=too-many-branches,too-many-locals
"""
"""
""""""
super()._detect()
reentrancies = self.find_reentrancies()
@ -152,7 +159,8 @@ Only report reentrancy that is based on `transfer` or `send`."""
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
#
@ -164,7 +172,8 @@ Only report reentrancy that is based on `transfer` or `send`."""
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
# Add all variables written via nodes which write them.

@ -58,7 +58,9 @@ Do not report reentrancies that involve Ether (see `reentrancy-eth`)."""
continue
read_then_written |= {
FindingValue(
v, node, tuple(sorted(nodes, key=lambda x: x.node_id)),
v,
node,
tuple(sorted(nodes, key=lambda x: x.node_id)),
)
for (v, nodes) in node.context[self.KEY].written.items()
if v in node.context[self.KEY].reads_prior_calls[c]
@ -75,8 +77,7 @@ Do not report reentrancies that involve Ether (see `reentrancy-eth`)."""
return result
def _detect(self): # pylint: disable=too-many-branches
"""
"""
""""""
super()._detect()
reentrancies = self.find_reentrancies()
@ -115,7 +116,8 @@ Do not report reentrancies that involve Ether (see `reentrancy-eth`)."""
for call_list_info in calls_list:
if call_list_info != call_info:
res.add(
call_list_info, {"underlying_type": "external_calls_sending_eth"},
call_list_info,
{"underlying_type": "external_calls_sending_eth"},
)
# Add all variables written via nodes which write them.

@ -49,7 +49,7 @@ contract DerivedContract is BaseContract{
WIKI_RECOMMENDATION = "Remove the state variable shadowing."
def _detect(self):
""" Detect shadowing
"""Detect shadowing
Recursively visit the calls
Returns:

@ -112,7 +112,7 @@ contract Bug {
]
def is_builtin_symbol(self, word):
""" Detects if a given word is a built-in symbol.
"""Detects if a given word is a built-in symbol.
Returns:
boolean: True if the given word represents a built-in symbol."""
@ -120,7 +120,7 @@ contract Bug {
return word in self.BUILTIN_SYMBOLS or word in self.RESERVED_KEYWORDS
def detect_builtin_shadowing_locals(self, function_or_modifier):
""" Detects if local variables in a given function/modifier are named after built-in symbols.
"""Detects if local variables in a given function/modifier are named after built-in symbols.
Any such items are returned in a list.
Returns:
@ -133,7 +133,7 @@ contract Bug {
return results
def detect_builtin_shadowing_definitions(self, contract):
""" Detects if functions, access modifiers, events, state variables, or local variables are named after built-in
"""Detects if functions, access modifiers, events, state variables, or local variables are named after built-in
symbols. Any such definitions are returned in a list.
Returns:
@ -162,7 +162,7 @@ contract Bug {
return result
def _detect(self):
""" Detect shadowing of built-in symbols
"""Detect shadowing of built-in symbols
Recursively visit the calls
Returns:

@ -48,7 +48,7 @@ contract Bug {
OVERSHADOWED_EVENT = "event"
def detect_shadowing_definitions(self, contract): # pylint: disable=too-many-branches
""" Detects if functions, access modifiers, events, state variables, and local variables are named after
"""Detects if functions, access modifiers, events, state variables, and local variables are named after
reserved keywords. Any such definitions are returned in a list.
Returns:
@ -91,7 +91,7 @@ contract Bug {
return result
def _detect(self):
""" Detect shadowing local variables
"""Detect shadowing local variables
Recursively visit the calls
Returns:

@ -62,7 +62,7 @@ contract DerivedContract is BaseContract{
WIKI_RECOMMENDATION = "Remove the state variable shadowing."
def _detect(self):
""" Detect shadowing
"""Detect shadowing
Recursively visit the calls
Returns:

@ -43,8 +43,7 @@ class Assembly(AbstractDetector):
return ret
def _detect(self):
""" Detect the functions that use inline assembly
"""
"""Detect the functions that use inline assembly"""
results = []
for c in self.contracts:
values = self.detect_assembly(c)

@ -74,8 +74,7 @@ If one of the destinations has a fallback function that reverts, `bad` will alwa
return ret
def _detect(self):
"""
"""
""""""
results = []
for c in self.slither.contracts_derived:
values = self.detect_call_in_loop(c)

@ -71,7 +71,7 @@ contract ContractWithDeprecatedReferences {
DEPRECATED_LOW_LEVEL_CALLS = [("callcode", "callcode", "delegatecall")]
def detect_deprecation_in_expression(self, expression):
""" Detects if an expression makes use of any deprecated standards.
"""Detects if an expression makes use of any deprecated standards.
Returns:
list of tuple: (detecting_signature, original_text, recommended_text)"""
@ -93,7 +93,7 @@ contract ContractWithDeprecatedReferences {
return results
def detect_deprecated_references_in_node(self, node):
""" Detects if a node makes use of any deprecated standards.
"""Detects if a node makes use of any deprecated standards.
Returns:
list of tuple: (detecting_signature, original_text, recommended_text)"""
@ -112,7 +112,7 @@ contract ContractWithDeprecatedReferences {
return results
def detect_deprecated_references_in_contract(self, contract):
""" Detects the usage of any deprecated built-in symbols.
"""Detects the usage of any deprecated built-in symbols.
Returns:
list of tuple: (state_variable | node, (detecting_signature, original_text, recommended_text))"""
@ -148,7 +148,7 @@ contract ContractWithDeprecatedReferences {
return results
def _detect(self):
""" Detects if an expression makes use of any deprecated standards.
"""Detects if an expression makes use of any deprecated standards.
Recursively visit the calls
Returns:

@ -65,8 +65,7 @@ Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls `
return ret
def _detect(self):
""" Detect the functions that use tx.origin in a conditional node
"""
"""Detect the functions that use tx.origin in a conditional node"""
results = []
for c in self.contracts:
values = self.detect_tx_origin(c)

@ -67,8 +67,7 @@ class ConstCandidateStateVars(AbstractDetector):
return False
def _detect(self):
""" Detect state variables that could be const
"""
"""Detect state variables that could be const"""
results = []
all_variables = [c.state_variables for c in self.slither.contracts]

@ -71,7 +71,7 @@ Bob calls `transfer`. As a result, all Ether is sent to the address `0x0` and is
self._detect_uninitialized(function, son, visited)
def _detect(self):
""" Detect uninitialized local variables
"""Detect uninitialized local variables
Recursively visit the calls
Returns:

@ -115,7 +115,7 @@ Initialize all the variables. If a variable is meant to be initialized to zero,
]
def _detect(self):
""" Detect uninitialized state variables
"""Detect uninitialized state variables
Recursively visit the calls
Returns:

@ -79,7 +79,7 @@ Bob calls `func`. As a result, `owner` is overridden to `0`.
self._detect_uninitialized(function, son, visited)
def _detect(self):
""" Detect uninitialized storage variables
"""Detect uninitialized storage variables
Recursively visit the calls
Returns:

@ -55,8 +55,7 @@ class UnusedStateVars(AbstractDetector):
WIKI_RECOMMENDATION = "Remove unused state variables."
def _detect(self):
""" Detect unused state variables
"""
"""Detect unused state variables"""
results = []
for c in self.slither.contracts_derived:
unusedVars = detect_unused(c)

@ -70,5 +70,10 @@ def _patch(
in_file_str = slither.source_code[in_file].encode("utf8")
old_str_of_interest = in_file_str[modify_loc_start:modify_loc_end]
create_patch(
result, in_file, int(modify_loc_start), int(modify_loc_end), old_str_of_interest, pragma,
result,
in_file,
int(modify_loc_start),
int(modify_loc_end),
old_str_of_interest,
pragma,
)

@ -575,7 +575,12 @@ def _explore_irs(slither, irs, result, target, convert):
loc_end = loc_start + len(old_str)
create_patch(
result, filename_source_code, loc_start, loc_end, old_str, new_str,
result,
filename_source_code,
loc_start,
loc_end,
old_str,
new_str,
)

@ -33,21 +33,39 @@ def _edge(from_node, to_node):
# return dot language string to add graph node (with optional label)
def _node(node, label=None):
return " ".join((f'"{node}"', f'[label="{label}"]' if label is not None else "",))
return " ".join(
(
f'"{node}"',
f'[label="{label}"]' if label is not None else "",
)
)
# pylint: disable=too-many-arguments
def _process_internal_call(
contract, function, internal_call, contract_calls, solidity_functions, solidity_calls,
contract,
function,
internal_call,
contract_calls,
solidity_functions,
solidity_calls,
):
if isinstance(internal_call, (Function)):
contract_calls[contract].add(
_edge(_function_node(contract, function), _function_node(contract, internal_call),)
_edge(
_function_node(contract, function),
_function_node(contract, internal_call),
)
)
elif isinstance(internal_call, (SolidityFunction)):
solidity_functions.add(_node(_solidity_function_node(internal_call)),)
solidity_functions.add(
_node(_solidity_function_node(internal_call)),
)
solidity_calls.add(
_edge(_function_node(contract, function), _solidity_function_node(internal_call),)
_edge(
_function_node(contract, function),
_solidity_function_node(internal_call),
)
)
@ -84,7 +102,12 @@ def _render_solidity_calls(solidity_functions, solidity_calls):
def _process_external_call(
contract, function, external_call, contract_functions, external_calls, all_contracts,
contract,
function,
external_call,
contract_functions,
external_calls,
all_contracts,
):
external_contract, external_function = external_call
@ -94,7 +117,10 @@ def _process_external_call(
# add variable as node to respective contract
if isinstance(external_function, (Variable)):
contract_functions[external_contract].add(
_node(_function_node(external_contract, external_function), external_function.name,)
_node(
_function_node(external_contract, external_function),
external_function.name,
)
)
external_calls.add(
@ -116,15 +142,27 @@ def _process_function(
external_calls,
all_contracts,
):
contract_functions[contract].add(_node(_function_node(contract, function), function.name),)
contract_functions[contract].add(
_node(_function_node(contract, function), function.name),
)
for internal_call in function.internal_calls:
_process_internal_call(
contract, function, internal_call, contract_calls, solidity_functions, solidity_calls,
contract,
function,
internal_call,
contract_calls,
solidity_functions,
solidity_calls,
)
for external_call in function.high_level_calls:
_process_external_call(
contract, function, external_call, contract_functions, external_calls, all_contracts,
contract,
function,
external_call,
contract_functions,
external_calls,
all_contracts,
)
@ -173,9 +211,9 @@ class PrinterCallGraph(AbstractPrinter):
def output(self, filename):
"""
Output the graph in filename
Args:
filename(string)
Output the graph in filename
Args:
filename(string)
"""
if not filename.endswith(".dot"):

@ -33,9 +33,9 @@ class PrinterWrittenVariablesAndAuthorization(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
txt = ""
@ -52,7 +52,11 @@ class PrinterWrittenVariablesAndAuthorization(AbstractPrinter):
state_variables_written = [v.name for v in function.all_state_variables_written()]
msg_sender_condition = self.get_msg_sender_checks(function)
table.add_row(
[function.name, str(state_variables_written), str(msg_sender_condition),]
[
function.name,
str(state_variables_written),
str(msg_sender_condition),
]
)
all_tables.append((contract.name, table))
txt += str(table) + "\n"

@ -10,9 +10,9 @@ class CFG(AbstractPrinter):
def output(self, filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
info = ""

@ -334,11 +334,11 @@ class Echidna(AbstractPrinter):
def output(self, filename): # pylint: disable=too-many-locals
"""
Output the inheritance relation
Output the inheritance relation
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
payable = _extract_payable(self.slither)

@ -22,11 +22,11 @@ class PrinterInheritance(AbstractPrinter):
def output(self, filename):
"""
Output the inheritance relation
Output the inheritance relation
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
info = "Inheritance\n"

@ -94,7 +94,7 @@ class PrinterInheritanceGraph(AbstractPrinter):
def _summary(self, contract):
"""
Build summary using HTML
Build summary using HTML
"""
ret = ""
@ -185,9 +185,9 @@ class PrinterInheritanceGraph(AbstractPrinter):
def output(self, filename):
"""
Output the graph in filename
Args:
filename(string)
Output the graph in filename
Args:
filename(string)
"""
if filename == "":

@ -15,9 +15,9 @@ class ContractSummary(AbstractPrinter):
def output(self, _filename): # pylint: disable=too-many-locals
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
txt = ""

@ -27,9 +27,9 @@ class DataDependency(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
all_tables = []

@ -55,9 +55,9 @@ class PrinterEVM(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
txt = ""
@ -101,7 +101,8 @@ class PrinterEVM(AbstractPrinter):
)
txt += green(
"\t\tSource line {}: {}\n".format(
node_source_line, contract_file_lines[node_source_line - 1].rstrip(),
node_source_line,
contract_file_lines[node_source_line - 1].rstrip(),
)
)
txt += magenta("\t\tEVM Instructions:\n")
@ -123,7 +124,8 @@ class PrinterEVM(AbstractPrinter):
)
txt += green(
"\t\tSource line {}: {}\n".format(
node_source_line, contract_file_lines[node_source_line - 1].rstrip(),
node_source_line,
contract_file_lines[node_source_line - 1].rstrip(),
)
)
txt += magenta("\t\tEVM Instructions:\n")

@ -24,9 +24,9 @@ class FunctionSummary(AbstractPrinter):
def output(self, _filename): # pylint: disable=too-many-locals
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
all_tables = []
@ -65,11 +65,26 @@ class FunctionSummary(AbstractPrinter):
internal_calls = self._convert(internal_calls)
external_calls = self._convert(external_calls)
table.add_row(
[f_name, visi, modifiers, read, write, internal_calls, external_calls,]
[
f_name,
visi,
modifiers,
read,
write,
internal_calls,
external_calls,
]
)
txt += "\n \n" + str(table)
table = MyPrettyTable(
["Modifiers", "Visibility", "Read", "Write", "Internal Calls", "External Calls",]
[
"Modifiers",
"Visibility",
"Read",
"Write",
"Internal Calls",
"External Calls",
]
)
for (
_c_name,

@ -15,9 +15,9 @@ class FunctionIds(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
txt = ""

@ -379,7 +379,14 @@ class PrinterHumanSummary(AbstractPrinter):
)
table.add_row(
[contract.name, number_functions, ercs, erc20_info, is_complex, features,]
[
contract.name,
number_functions,
ercs,
erc20_info,
is_complex,
features,
]
)
self.info(txt + "\n" + str(table))

@ -16,9 +16,9 @@ class Modifiers(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
all_txt = ""

@ -27,9 +27,9 @@ class RequireOrAssert(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
all_tables = []
@ -46,7 +46,10 @@ class RequireOrAssert(AbstractPrinter):
]
require = [ir.node for ir in require]
table.add_row(
[function.name, self._convert([str(m.expression) for m in set(require)]),]
[
function.name,
self._convert([str(m.expression) for m in set(require)]),
]
)
txt += "\n" + str(table)
self.info(txt)

@ -13,9 +13,9 @@ class PrinterSlithIR(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
txt = ""

@ -14,9 +14,9 @@ class PrinterSlithIRSSA(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
txt = ""

@ -15,9 +15,9 @@ class VariableOrder(AbstractPrinter):
def output(self, _filename):
"""
_filename is not used
Args:
_filename(string)
_filename is not used
Args:
_filename(string)
"""
txt = ""

@ -33,26 +33,26 @@ def _check_common_things(thing_name, cls, base_cls, instances_list):
class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes
def __init__(self, target, **kwargs):
"""
Args:
target (str | list(json) | CryticCompile)
Keyword Args:
solc (str): solc binary location (default 'solc')
disable_solc_warnings (bool): True to disable solc warnings (default false)
solc_arguments (str): solc arguments (default '')
ast_format (str): ast format (default '--ast-compact-json')
filter_paths (list(str)): list of path to filter (default [])
triage_mode (bool): if true, switch to triage mode (default false)
exclude_dependencies (bool): if true, exclude results that are only related to dependencies
generate_patches (bool): if true, patches are generated (json output only)
truffle_ignore (bool): ignore truffle.js presence (default false)
truffle_build_directory (str): build truffle directory (default 'build/contracts')
truffle_ignore_compile (bool): do not run truffle compile (default False)
truffle_version (str): use a specific truffle version (default None)
embark_ignore (bool): ignore embark.js presence (default false)
embark_ignore_compile (bool): do not run embark build (default False)
embark_overwrite_config (bool): overwrite original config file (default false)
Args:
target (str | list(json) | CryticCompile)
Keyword Args:
solc (str): solc binary location (default 'solc')
disable_solc_warnings (bool): True to disable solc warnings (default false)
solc_arguments (str): solc arguments (default '')
ast_format (str): ast format (default '--ast-compact-json')
filter_paths (list(str)): list of path to filter (default [])
triage_mode (bool): if true, switch to triage mode (default false)
exclude_dependencies (bool): if true, exclude results that are only related to dependencies
generate_patches (bool): if true, patches are generated (json output only)
truffle_ignore (bool): ignore truffle.js presence (default false)
truffle_build_directory (str): build truffle directory (default 'build/contracts')
truffle_ignore_compile (bool): do not run truffle compile (default False)
truffle_version (str): use a specific truffle version (default None)
embark_ignore (bool): ignore embark.js presence (default false)
embark_ignore_compile (bool): do not run embark build (default False)
embark_overwrite_config (bool): overwrite original config file (default false)
"""
super().__init__()

@ -206,7 +206,8 @@ def convert_arguments(arguments):
def is_temporary(ins):
return isinstance(
ins, (Argument, TmpNewElementaryType, TmpNewContract, TmpNewArray, TmpNewStructure),
ins,
(Argument, TmpNewElementaryType, TmpNewContract, TmpNewArray, TmpNewStructure),
)
@ -220,7 +221,7 @@ def is_temporary(ins):
def integrate_value_gas(result):
"""
Integrate value and gas temporary arguments to call instruction
Integrate value and gas temporary arguments to call instruction
"""
was_changed = True
@ -299,7 +300,7 @@ def integrate_value_gas(result):
def propagate_type_and_convert_call(result, node):
"""
Propagate the types variables and convert tmp call to real call operation
Propagate the types variables and convert tmp call to real call operation
"""
calls_value = {}
calls_gas = {}
@ -638,7 +639,8 @@ def propagate_types(ir, node): # pylint: disable=too-many-locals
# We dont need to check for function collision, as solc prevents the use of selector
# if there are multiple functions with the same name
f = next(
(f for f in type_t.functions if f.name == ir.variable_right), None,
(f for f in type_t.functions if f.name == ir.variable_right),
None,
)
if f:
ir.lvalue.set_type(f)
@ -773,7 +775,10 @@ def extract_tmp_call(ins, contract):
ins.called = SolidityFunction("blockhash(uint256)")
elif str(ins.called) == "this.balance":
s = SolidityCall(
SolidityFunction("this.balance()"), ins.nbr_arguments, ins.lvalue, ins.type_call,
SolidityFunction("this.balance()"),
ins.nbr_arguments,
ins.lvalue,
ins.type_call,
)
s.set_expression(ins.expression)
return s
@ -858,11 +863,11 @@ def can_be_low_level(ir):
def convert_to_low_level(ir):
"""
Convert to a transfer/send/or low level call
The funciton assume to receive a correct IR
The checks must be done by the caller
Convert to a transfer/send/or low level call
The funciton assume to receive a correct IR
The checks must be done by the caller
Must be called after can_be_low_level
Must be called after can_be_low_level
"""
if ir.function_name == "transfer":
assert len(ir.arguments) == 1
@ -1064,7 +1069,11 @@ def look_for_library(contract, ir, using_for, t):
lib_contract = contract.slither.get_contract_from_name(str(destination))
if lib_contract:
lib_call = LibraryCall(
lib_contract, ir.function_name, ir.nbr_arguments, ir.lvalue, ir.type_call,
lib_contract,
ir.function_name,
ir.nbr_arguments,
ir.lvalue,
ir.type_call,
)
lib_call.set_expression(ir.expression)
lib_call.set_node(ir.node)
@ -1098,8 +1107,8 @@ def convert_to_library(ir, node, using_for):
def get_type(t):
"""
Convert a type to a str
If the instance is a Contract, return 'address' instead
Convert a type to a str
If the instance is a Contract, return 'address' instead
"""
if isinstance(t, UserDefinedType):
if isinstance(t.type, Contract):
@ -1276,8 +1285,8 @@ def convert_type_of_high_and_internal_level_call(ir, contract):
def find_references_origin(irs):
"""
Make lvalue of each Index, Member operation
points to the left variable
Make lvalue of each Index, Member operation
points to the left variable
"""
for ir in irs:
if isinstance(ir, (Index, Member)):
@ -1297,7 +1306,14 @@ def remove_temporary(result):
ins
for ins in result
if not isinstance(
ins, (Argument, TmpNewElementaryType, TmpNewContract, TmpNewArray, TmpNewStructure,),
ins,
(
Argument,
TmpNewElementaryType,
TmpNewContract,
TmpNewArray,
TmpNewStructure,
),
)
]
@ -1440,7 +1456,7 @@ def convert_delete(irs):
def apply_ir_heuristics(irs, node):
"""
Apply a set of heuristic to improve slithIR
Apply a set of heuristic to improve slithIR
"""
irs = integrate_value_gas(irs)

@ -174,7 +174,11 @@ class Binary(OperationWithLValue):
while isinstance(points, ReferenceVariable):
points = points.points_to
return "{}(-> {}) = {} {} {}".format(
str(self.lvalue), points, self.variable_left, self.type_str, self.variable_right,
str(self.lvalue),
points,
self.variable_left,
self.type_str,
self.variable_right,
)
return "{}({}) = {} {} {}".format(
str(self.lvalue),

@ -5,8 +5,8 @@ from slither.slithir.utils.utils import is_valid_rvalue
class Condition(Operation):
"""
Condition
Only present as last operation in conditional node
Condition
Only present as last operation in conditional node
"""
def __init__(self, value):

@ -5,8 +5,8 @@ from slither.slithir.utils.utils import is_valid_lvalue
class Delete(OperationWithLValue):
"""
Delete has a lvalue, as it has for effect to change the value
of its operand
Delete has a lvalue, as it has for effect to change the value
of its operand
"""
def __init__(self, lvalue, variable):

@ -12,7 +12,7 @@ from slither.slithir.variables.constant import Constant
class HighLevelCall(Call, OperationWithLValue):
"""
High level message call
High level message call
"""
# pylint: disable=too-many-arguments,too-many-instance-attributes

@ -4,7 +4,7 @@ from slither.core.declarations.contract import Contract
class LibraryCall(HighLevelCall):
"""
High level message call
High level message call
"""
# Development function, to be removed once the code is stable
@ -38,5 +38,9 @@ class LibraryCall(HighLevelCall):
lvalue = "{}({}) = ".format(self.lvalue, self.lvalue.type)
txt = "{}LIBRARY_CALL, dest:{}, function:{}, arguments:{} {}"
return txt.format(
lvalue, self.destination, self.function_name, [str(x) for x in arguments], gas,
lvalue,
self.destination,
self.function_name,
[str(x) for x in arguments],
gas,
)

@ -8,7 +8,7 @@ from slither.slithir.variables.constant import Constant
class LowLevelCall(Call, OperationWithLValue): # pylint: disable=too-many-instance-attributes
"""
High level message call
High level message call
"""
def __init__(self, destination, function_name, nbr_arguments, result, type_call):

@ -3,7 +3,7 @@ from slither.slithir.operations.operation import Operation
class OperationWithLValue(Operation):
"""
Operation with a lvalue
Operation with a lvalue
"""
def __init__(self):

@ -10,7 +10,7 @@ class AbstractOperation(abc.ABC):
@abc.abstractmethod
def read(self):
"""
Return the list of variables READ
Return the list of variables READ
"""
pass # pylint: disable=unnecessary-pass
@ -18,7 +18,7 @@ class AbstractOperation(abc.ABC):
@abc.abstractmethod
def used(self):
"""
Return the list of variables used
Return the list of variables used
"""
pass # pylint: disable=unnecessary-pass
@ -27,7 +27,7 @@ class Operation(Context, ChildExpression, ChildNode, AbstractOperation):
@property
def used(self):
"""
By default used is all the variables read
By default used is all the variables read
"""
return self.read

@ -26,7 +26,7 @@ class PhiCallback(Phi):
@property
def rvalue_no_callback(self):
"""
rvalue if callback are not considered
rvalue if callback are not considered
"""
return self._rvalue_no_callback

@ -7,8 +7,8 @@ from slither.slithir.utils.utils import is_valid_rvalue
class Return(Operation):
"""
Return
Only present as last operation in RETURN node
Return
Only present as last operation in RETURN node
"""
def __init__(self, values):

@ -13,7 +13,14 @@ class TmpCall(OperationWithLValue): # pylint: disable=too-many-instance-attribu
def __init__(self, called, nbr_arguments, result, type_call):
assert isinstance(
called,
(Contract, Variable, SolidityVariableComposed, SolidityFunction, Structure, Event,),
(
Contract,
Variable,
SolidityVariableComposed,
SolidityFunction,
Structure,
Event,
),
)
super().__init__()
self._called = called

@ -70,7 +70,7 @@ logger = logging.getLogger("SSA_Conversion")
def transform_slithir_vars_to_ssa(function):
"""
Transform slithIR vars to SSA (TemporaryVariable, ReferenceVariable, TupleVariable)
Transform slithIR vars to SSA (TemporaryVariable, ReferenceVariable, TupleVariable)
"""
variables = []
for node in function.nodes:
@ -173,7 +173,9 @@ def add_ssa_ir(function, all_state_variables_instances):
init_state_variables_instances = dict(all_state_variables_instances)
initiate_all_local_variables_instances(
function.nodes, init_local_variables_instances, all_init_local_variables_instances,
function.nodes,
init_local_variables_instances,
all_init_local_variables_instances,
)
generate_ssa_irs(
@ -506,7 +508,8 @@ def add_phi_origins(node, local_variables_definition, state_variables_definition
# We keep the instance as we want to avoid to add __hash__ on v.name in Variable
# That might work for this used, but could create collision for other uses
local_variables_definition = dict(
local_variables_definition, **{v.name: (v, node) for v in node.local_variables_written},
local_variables_definition,
**{v.name: (v, node) for v in node.local_variables_written},
)
state_variables_definition = dict(
state_variables_definition,
@ -598,7 +601,16 @@ def get(
return tuple_variables_instances[variable.index]
assert isinstance(
variable,
(Constant, SolidityVariable, Contract, Enum, SolidityFunction, Structure, Function, Type,),
(
Constant,
SolidityVariable,
Contract,
Enum,
SolidityFunction,
Structure,
Function,
Type,
),
) # type for abi.decode(.., t)
return variable

@ -25,5 +25,12 @@ def is_valid_rvalue(v):
def is_valid_lvalue(v):
return isinstance(
v, (StateVariable, LocalVariable, TemporaryVariable, ReferenceVariable, TupleVariable,),
v,
(
StateVariable,
LocalVariable,
TemporaryVariable,
ReferenceVariable,
TupleVariable,
),
)

@ -28,8 +28,8 @@ class ReferenceVariable(ChildNode, Variable):
@property
def points_to(self):
"""
Return the variable pointer by the reference
It is the left member of a Index or Member operator
Return the variable pointer by the reference
It is the left member of a Index or Member operator
"""
return self._points_to

@ -441,10 +441,15 @@ class ContractSolc:
elem.set_contract(self._contract)
elem.set_contract_declarer(element_parser.underlying_function.contract_declarer)
elem.set_offset(
element_parser.function_not_parsed["src"], self._contract.slither,
element_parser.function_not_parsed["src"],
self._contract.slither,
)
elem_parser = Cls_parser(elem, element_parser.function_not_parsed, self,)
elem_parser = Cls_parser(
elem,
element_parser.function_not_parsed,
self,
)
elem_parser.analyze_params()
if isinstance(elem, Modifier):
self._contract.slither.add_modifier(elem)

@ -48,7 +48,10 @@ class FunctionSolc:
# elems = [(type, name)]
def __init__(
self, function: Function, function_data: Dict, contract_parser: "ContractSolc",
self,
function: Function,
function_data: Dict,
contract_parser: "ContractSolc",
):
self._slither_parser: "SlitherSolc" = contract_parser.slither_parser
self._contract_parser = contract_parser
@ -127,7 +130,7 @@ class FunctionSolc:
@property
def referenced_declaration(self) -> Optional[str]:
"""
Return the compact AST referenced declaration id (None for legacy AST)
Return the compact AST referenced declaration id (None for legacy AST)
"""
return self._referenced_declaration
@ -572,7 +575,8 @@ class FunctionSolc:
link_underlying_nodes(node_startDoWhile, node_condition)
else:
link_nodes(
node_startDoWhile.underlying_node, node_condition.underlying_node.sons[0],
node_startDoWhile.underlying_node,
node_condition.underlying_node.sons[0],
)
link_underlying_nodes(statement, node_condition)
link_underlying_nodes(node_condition, node_endDoWhile)
@ -1150,22 +1154,22 @@ class FunctionSolc:
def _remove_alone_endif(self):
"""
Can occur on:
if(..){
return
}
else{
return
}
Iterate until a fix point to remove the ENDIF node
creates on the following pattern
if(){
return
}
else if(){
return
}
Can occur on:
if(..){
return
}
else{
return
}
Iterate until a fix point to remove the ENDIF node
creates on the following pattern
if(){
return
}
else if(){
return
}
"""
prev_nodes = []
while set(prev_nodes) != set(self._node_to_nodesolc.keys()):

@ -84,7 +84,14 @@ def find_variable( # pylint: disable=too-many-locals,too-many-statements
referenced_declaration: Optional[int] = None,
is_super=False,
) -> Union[
Variable, Function, Contract, SolidityVariable, SolidityFunction, Event, Enum, Structure,
Variable,
Function,
Contract,
SolidityVariable,
SolidityFunction,
Event,
Enum,
Structure,
]:
from slither.solc_parsing.declarations.contract import ContractSolc
from slither.solc_parsing.declarations.function import FunctionSolc

@ -371,7 +371,9 @@ Please rename it, this name is reserved for Slither's internals"""
contracts_to_be_analyzed += [contract]
def _analyze_first_part(
self, contracts_to_be_analyzed: List[ContractSolc], libraries: List[ContractSolc],
self,
contracts_to_be_analyzed: List[ContractSolc],
libraries: List[ContractSolc],
):
for lib in libraries:
self._parse_struct_var_modifiers_functions(lib)
@ -396,7 +398,9 @@ Please rename it, this name is reserved for Slither's internals"""
contracts_to_be_analyzed += [contract]
def _analyze_second_part(
self, contracts_to_be_analyzed: List[ContractSolc], libraries: List[ContractSolc],
self,
contracts_to_be_analyzed: List[ContractSolc],
libraries: List[ContractSolc],
):
for lib in libraries:
self._analyze_struct_events(lib)
@ -421,7 +425,9 @@ Please rename it, this name is reserved for Slither's internals"""
contracts_to_be_analyzed += [contract]
def _analyze_third_part(
self, contracts_to_be_analyzed: List[ContractSolc], libraries: List[ContractSolc],
self,
contracts_to_be_analyzed: List[ContractSolc],
libraries: List[ContractSolc],
):
for lib in libraries:
self._analyze_variables_modifiers_functions(lib)

@ -132,7 +132,8 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t
found = re.findall("mapping\(([a-zA-Z0-9\.]*) => ([a-zA-Z0-9\.\[\]]*)\)", name)
else:
found = re.findall(
"mapping\(([a-zA-Z0-9\.]*) => (mapping\([=> a-zA-Z0-9\.\[\]]*\))\)", name,
"mapping\(([a-zA-Z0-9\.]*) => (mapping\([=> a-zA-Z0-9\.\[\]]*\))\)",
name,
)
assert len(found) == 1
from_ = found[0][0]
@ -188,7 +189,11 @@ def parse_type(t: Union[Dict, UnknownType], caller_context):
if t[key] == "UserDefinedTypeName":
if is_compact_ast:
return _find_from_type_name(
t["typeDescriptions"]["typeString"], contract, contracts, structures, enums,
t["typeDescriptions"]["typeString"],
contract,
contracts,
structures,
enums,
)
# Determine if we have a type node (otherwise we use the name node, as some older solc did not have 'type').

@ -16,8 +16,8 @@ class LocalVariableSolc(VariableDeclarationSolc):
def _analyze_variable_attributes(self, attributes: Dict):
"""'
Variable Location
Can be storage/memory or default
Variable Location
Can be storage/memory or default
"""
if "storageLocation" in attributes:
location = attributes["storageLocation"]

@ -32,11 +32,11 @@ class VariableDeclarationSolc:
self, variable: Variable, variable_data: Dict
): # pylint: disable=too-many-branches
"""
A variable can be declared through a statement, or directly.
If it is through a statement, the following children may contain
the init value.
It may be possible that the variable is declared through a statement,
but the init value is declared at the VariableDeclaration children level
A variable can be declared through a statement, or directly.
If it is through a statement, the following children may contain
the init value.
It may be possible that the variable is declared through a statement,
but the init value is declared at the VariableDeclaration children level
"""
self._variable = variable
@ -97,8 +97,8 @@ class VariableDeclarationSolc:
@property
def reference_id(self) -> int:
"""
Return the solc id. It can be compared with the referencedDeclaration attr
Returns None if it was not parsed (legacy AST)
Return the solc id. It can be compared with the referencedDeclaration attr
Returns None if it was not parsed (legacy AST)
"""
return self._reference_id

@ -136,14 +136,18 @@ class YulScope(metaclass=abc.ABCMeta):
def get_yul_local_variable_from_name(self, variable_name):
return next(
(v for v in self._yul_local_variables if v.underlying.name == variable_name), None,
(v for v in self._yul_local_variables if v.underlying.name == variable_name),
None,
)
def add_yul_local_function(self, func):
self._yul_local_functions.append(func)
def get_yul_local_function_from_name(self, func_name):
return next((v for v in self._yul_local_functions if v.underlying.name == func_name), None,)
return next(
(v for v in self._yul_local_functions if v.underlying.name == func_name),
None,
)
class YulLocalVariable: # pylint: disable=too-few-public-methods
@ -434,7 +438,11 @@ def convert_yul_switch(root: YulScope, parent: YulNode, ast: Dict) -> YulNode:
"name": "eq",
},
"arguments": [
{"nodeType": "YulIdentifier", "src": case_ast["src"], "name": switch_expr_var,},
{
"nodeType": "YulIdentifier",
"src": case_ast["src"],
"name": switch_expr_var,
},
value_ast,
],
},

@ -31,7 +31,8 @@ def parse_args():
:return: Returns the arguments for the program.
"""
parser = argparse.ArgumentParser(
description="Check the ERC 20 conformance", usage="slither-check-erc project contractName",
description="Check the ERC 20 conformance",
usage="slither-check-erc project contractName",
)
parser.add_argument("project", help="The codebase to be tested.")

@ -41,7 +41,9 @@ def parse_args():
group_export = parser.add_argument_group("Export options")
group_export.add_argument(
"--dir", help=f"Export directory (default: {DEFAULT_EXPORT_PATH}).", default=None,
"--dir",
help=f"Export directory (default: {DEFAULT_EXPORT_PATH}).",
default=None,
)
group_export.add_argument(
@ -52,7 +54,10 @@ def parse_args():
)
parser.add_argument(
"--zip", help="Export all the files to a zip file", action="store", default=None,
"--zip",
help="Export all the files to a zip file",
action="store",
default=None,
)
parser.add_argument(
@ -69,7 +74,9 @@ def parse_args():
)
group_patching.add_argument(
"--convert-private", help="Convert private variables to internal.", action="store_true",
"--convert-private",
help="Convert private variables to internal.",
action="store_true",
)
group_patching.add_argument(

@ -24,7 +24,9 @@ def save_to_zip(files: List[Export], zip_filename: str, zip_type: str = "lzma"):
"""
logger.info(f"Export {zip_filename}")
with zipfile.ZipFile(
zip_filename, "w", compression=ZIP_TYPES_ACCEPTED.get(zip_type, zipfile.ZIP_LZMA),
zip_filename,
"w",
compression=ZIP_TYPES_ACCEPTED.get(zip_type, zipfile.ZIP_LZMA),
) as file_desc:
for f in files:
file_desc.writestr(str(f.filename), f.content)

@ -108,7 +108,10 @@ class Flattening:
regex = re.search(r"((\sexternal)\s+)|(\sexternal)$|(\)external)$", attributes)
if regex:
to_patch.append(
Patch(attributes_start + regex.span()[0] + 1, "public_to_external",)
Patch(
attributes_start + regex.span()[0] + 1,
"public_to_external",
)
)
else:
raise SlitherException(f"External keyword not found {f.name} {attributes}")
@ -119,7 +122,10 @@ class Flattening:
calldata_end = calldata_start + var.source_mapping["length"]
calldata_idx = content[calldata_start:calldata_end].find(" calldata ")
to_patch.append(
Patch(calldata_start + calldata_idx + 1, "calldata_to_memory",)
Patch(
calldata_start + calldata_idx + 1,
"calldata_to_memory",
)
)
if self._private_to_internal:
@ -133,7 +139,10 @@ class Flattening:
regex = re.search(r" private ", attributes)
if regex:
to_patch.append(
Patch(attributes_start + regex.span()[0] + 1, "private_to_internal",)
Patch(
attributes_start + regex.span()[0] + 1,
"private_to_internal",
)
)
else:
raise SlitherException(

@ -22,18 +22,23 @@ def parse_args():
:return: Returns the arguments for the program.
"""
parser = argparse.ArgumentParser(
description="slither-kspec-coverage", usage="slither-kspec-coverage contract.sol kspec.md",
description="slither-kspec-coverage",
usage="slither-kspec-coverage contract.sol kspec.md",
)
parser.add_argument(
"contract", help="The filename of the contract or truffle directory to analyze."
)
parser.add_argument(
"kspec", help="The filename of the Klab spec markdown for the analyzed contract(s)",
"kspec",
help="The filename of the Klab spec markdown for the analyzed contract(s)",
)
parser.add_argument(
"--version", help="displays the current version", version="0.1.0", action="version",
"--version",
help="displays the current version",
version="0.1.0",
action="version",
)
parser.add_argument(
"--json",

@ -21,7 +21,8 @@ def parse_args():
:return: Returns the arguments for the program.
"""
parser = argparse.ArgumentParser(
description="PossiblePaths", usage="possible_paths.py filename [contract.function targets]",
description="PossiblePaths",
usage="possible_paths.py filename [contract.function targets]",
)
parser.add_argument(

@ -18,7 +18,8 @@ def resolve_function(slither, contract_name, function_name):
# Obtain the target function
target_function = next(
(function for function in contract.functions if function.name == function_name), None,
(function for function in contract.functions if function.name == function_name),
None,
)
# Verify we have resolved the function specified.

@ -105,7 +105,9 @@ def parse_args():
)
parser.add_argument(
"--address-attacker", help=f"Attacker address. Default {ATTACKER_ADDRESS}", default=None,
"--address-attacker",
help=f"Attacker address. Default {ATTACKER_ADDRESS}",
default=None,
)
# Add default arguments from crytic-compile

@ -102,7 +102,11 @@ def generate_erc20(contract: Contract, type_property: str, addresses: Addresses)
# Generate the Test contract
initialization_recommendation = _initialization_recommendation(type_property)
contract_filename, contract_name = generate_test_contract(
contract, type_property, output_dir, property_file, initialization_recommendation,
contract,
type_property,
output_dir,
property_file,
initialization_recommendation,
)
# Generate Echidna config file

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

Loading…
Cancel
Save