Improvements

pull/1334/head
Josselin Feist 2 years ago
parent 4d28a3d61c
commit 07964f93f0
  1. 7
      slither/core/declarations/contract.py
  2. 44
      slither/core/variables/state_variable.py
  3. 34
      slither/detectors/functions/permit_domain_signature_collision.py

@ -316,6 +316,13 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods
"""
return list(self._variables.values())
@property
def state_variables_entry_points(self) -> List["StateVariable"]:
"""
list(StateVariable): List of the state variables that are public.
"""
return [var for var in self._variables.values() if var.visibility == "public"]
@property
def state_variables_ordered(self) -> List["StateVariable"]:
"""

@ -1,9 +1,7 @@
from typing import Optional, TYPE_CHECKING, Tuple, List
from typing import Optional, TYPE_CHECKING
from slither.core.children.child_contract import ChildContract
from slither.core.variables.variable import Variable
from slither.utils.type import export_nested_types_from_variable
from slither.core.solidity_types.type import Type
if TYPE_CHECKING:
from slither.core.cfg.node import Node
@ -23,46 +21,6 @@ class StateVariable(ChildContract, Variable):
"""
return self.contract == contract
###################################################################################
###################################################################################
# region Signature and return type of state variable getters
###################################################################################
###################################################################################
@property
def signature(self) -> Tuple[str, List[str], List[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 (
self.name,
[str(x) for x in export_nested_types_from_variable(self)],
[str(self.type)],
)
@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)
"""
name, parameters, returnVars = self.signature
return name + "(" + ",".join(parameters) + ") returns(" + ",".join(returnVars) + ")"
@property
def solidity_signature(self) -> Optional[str]:
if self.visibility in ["public", "external"]:
name, parameters, _ = self.signature
return f"{name}({','.join(parameters)})"
return None
@property
def return_type(self) -> Optional[List[Type]]:
if self.visibility in ["public", "external"]:
return [self.type]
return None
# endregion
###################################################################################
###################################################################################

@ -1,9 +1,13 @@
"""
Module detecting EIP-2612 domain separator collision
"""
from slither.utils.function import get_function_id
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from typing import Union, List
from slither.core.declarations import Function
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.core.variables.state_variable import StateVariable
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.function import get_function_id
class DomainSeparatorCollision(AbstractDetector):
@ -39,24 +43,28 @@ contract Contract{
domain_sig = get_function_id("DOMAIN_SEPARATOR()")
for contract in self.compilation_unit.contracts_derived:
if contract.is_erc20():
for func in contract.functions_entry_points + contract.state_variables:
# Skip internal and private variables
if func.solidity_signature is None:
continue
funcs_and_vars: List[Union[Function, StateVariable]] = contract.functions_entry_points + contract.state_variables_entry_points # type: ignore
for func_or_var in funcs_and_vars:
# External/ public function names should not collide with DOMAIN_SEPARATOR()
hash_collision = (
func.solidity_signature != "DOMAIN_SEPARATOR()"
and get_function_id(func.solidity_signature) == domain_sig
func_or_var.solidity_signature != "DOMAIN_SEPARATOR()"
and get_function_id(func_or_var.solidity_signature) == domain_sig
)
# DOMAIN_SEPARATOR() should return bytes32
incorrect_return_type = (
func.solidity_signature == "DOMAIN_SEPARATOR()"
and func.return_type[0] != ElementaryType("bytes32")
)
incorrect_return_type = func_or_var.solidity_signature == "DOMAIN_SEPARATOR()"
if incorrect_return_type:
if isinstance(func_or_var, Function):
incorrect_return_type = (
not func_or_var.return_type
or func_or_var.return_type[0] != ElementaryType("bytes32")
)
else:
assert isinstance(func_or_var, StateVariable)
incorrect_return_type = func_or_var.type != ElementaryType("bytes32")
if hash_collision or incorrect_return_type:
info = [
"The function signature of ",
func,
func_or_var,
" collides with DOMAIN_SEPARATOR and should be renamed or removed.\n",
]
res = self.generate_result(info)

Loading…
Cancel
Save