slither.utils.inheritance_analysis
Detects various properties of inheritance in provided contracts.
1""" 2Detects various properties of inheritance in provided contracts. 3""" 4 5from collections import defaultdict 6from typing import TYPE_CHECKING, List, Dict, Set, Tuple 7 8if TYPE_CHECKING: 9 from slither.core.declarations import Contract, Function 10 from slither.core.variables.state_variable import StateVariable 11 12 13def detect_c3_function_shadowing( 14 contract: "Contract", 15) -> Dict["Function", Set["Function"]]: 16 """ 17 Detects and obtains functions which are indirectly shadowed via multiple inheritance by C3 linearization 18 properties, despite not directly inheriting from each other. 19 20 :param contract: The contract to check for potential C3 linearization shadowing within. 21 :return: A dict (function winner -> [shadowed functions]) 22 """ 23 24 targets: Dict[str, "Function"] = { 25 f.full_name: f 26 for f in contract.functions_inherited 27 if f.shadows and not f.is_constructor and not f.is_constructor_variables 28 } 29 30 collisions: Dict["Function", Set["Function"]] = defaultdict(set) 31 32 for contract_inherited in contract.immediate_inheritance: 33 for candidate in contract_inherited.functions: 34 if candidate.full_name not in targets or candidate.is_shadowed: 35 continue 36 if targets[candidate.full_name].canonical_name != candidate.canonical_name: 37 collisions[targets[candidate.full_name]].add(candidate) 38 return collisions 39 40 41def detect_state_variable_shadowing( 42 contracts: List["Contract"], 43) -> Set[Tuple["Contract", "StateVariable", "Contract", "StateVariable"]]: 44 """ 45 Detects all overshadowing and overshadowed state variables in the provided contracts. 46 :param contracts: The contracts to detect shadowing within. 47 :return: Returns a set of tuples (overshadowing_contract, overshadowing_state_var, overshadowed_contract, 48 overshadowed_state_var). 49 The contract-variable pair's variable does not need to be defined in its paired contract, it may have been 50 inherited. The contracts are simply included to denote the immediate inheritance path from which the shadowed 51 variable originates. 52 """ 53 results: Set[Tuple["Contract", "StateVariable", "Contract", "StateVariable"]] = set() 54 for contract in contracts: 55 variables_declared: Dict[str, "StateVariable"] = { 56 variable.name: variable for variable in contract.state_variables_declared 57 } 58 for immediate_base_contract in contract.immediate_inheritance: 59 for variable in immediate_base_contract.variables: 60 if variable.name in variables_declared: 61 results.add( 62 ( 63 contract, 64 variables_declared[variable.name], 65 immediate_base_contract, 66 variable, 67 ) 68 ) 69 return results
def
detect_c3_function_shadowing( contract: slither.core.declarations.contract.Contract) -> dict[slither.core.declarations.function.Function, set[slither.core.declarations.function.Function]]:
14def detect_c3_function_shadowing( 15 contract: "Contract", 16) -> Dict["Function", Set["Function"]]: 17 """ 18 Detects and obtains functions which are indirectly shadowed via multiple inheritance by C3 linearization 19 properties, despite not directly inheriting from each other. 20 21 :param contract: The contract to check for potential C3 linearization shadowing within. 22 :return: A dict (function winner -> [shadowed functions]) 23 """ 24 25 targets: Dict[str, "Function"] = { 26 f.full_name: f 27 for f in contract.functions_inherited 28 if f.shadows and not f.is_constructor and not f.is_constructor_variables 29 } 30 31 collisions: Dict["Function", Set["Function"]] = defaultdict(set) 32 33 for contract_inherited in contract.immediate_inheritance: 34 for candidate in contract_inherited.functions: 35 if candidate.full_name not in targets or candidate.is_shadowed: 36 continue 37 if targets[candidate.full_name].canonical_name != candidate.canonical_name: 38 collisions[targets[candidate.full_name]].add(candidate) 39 return collisions
Detects and obtains functions which are indirectly shadowed via multiple inheritance by C3 linearization properties, despite not directly inheriting from each other.
Parameters
- contract: The contract to check for potential C3 linearization shadowing within.
Returns
A dict (function winner -> [shadowed functions])
def
detect_state_variable_shadowing( contracts: list[slither.core.declarations.contract.Contract]) -> set[tuple[slither.core.declarations.contract.Contract, slither.core.variables.state_variable.StateVariable, slither.core.declarations.contract.Contract, slither.core.variables.state_variable.StateVariable]]:
42def detect_state_variable_shadowing( 43 contracts: List["Contract"], 44) -> Set[Tuple["Contract", "StateVariable", "Contract", "StateVariable"]]: 45 """ 46 Detects all overshadowing and overshadowed state variables in the provided contracts. 47 :param contracts: The contracts to detect shadowing within. 48 :return: Returns a set of tuples (overshadowing_contract, overshadowing_state_var, overshadowed_contract, 49 overshadowed_state_var). 50 The contract-variable pair's variable does not need to be defined in its paired contract, it may have been 51 inherited. The contracts are simply included to denote the immediate inheritance path from which the shadowed 52 variable originates. 53 """ 54 results: Set[Tuple["Contract", "StateVariable", "Contract", "StateVariable"]] = set() 55 for contract in contracts: 56 variables_declared: Dict[str, "StateVariable"] = { 57 variable.name: variable for variable in contract.state_variables_declared 58 } 59 for immediate_base_contract in contract.immediate_inheritance: 60 for variable in immediate_base_contract.variables: 61 if variable.name in variables_declared: 62 results.add( 63 ( 64 contract, 65 variables_declared[variable.name], 66 immediate_base_contract, 67 variable, 68 ) 69 ) 70 return results
Detects all overshadowing and overshadowed state variables in the provided contracts.
Parameters
- contracts: The contracts to detect shadowing within.
Returns
Returns a set of tuples (overshadowing_contract, overshadowing_state_var, overshadowed_contract, overshadowed_state_var). The contract-variable pair's variable does not need to be defined in its paired contract, it may have been inherited. The contracts are simply included to denote the immediate inheritance path from which the shadowed variable originates.