slither.core.compilation_unit
1import math 2from enum import Enum 3from typing import Optional, Dict, List, Set, Union, TYPE_CHECKING, Tuple 4 5from crytic_compile import CompilationUnit, CryticCompile 6from crytic_compile.compiler.compiler import CompilerVersion 7from crytic_compile.utils.naming import Filename 8 9from slither.core.context.context import Context 10from slither.core.declarations import ( 11 Contract, 12 Pragma, 13 Import, 14 Function, 15 Modifier, 16) 17from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel 18from slither.core.declarations.enum_top_level import EnumTopLevel 19from slither.core.declarations.event_top_level import EventTopLevel 20from slither.core.declarations.function_top_level import FunctionTopLevel 21from slither.core.declarations.structure_top_level import StructureTopLevel 22from slither.core.declarations.using_for_top_level import UsingForTopLevel 23from slither.core.scope.scope import FileScope 24from slither.core.solidity_types.type_alias import TypeAliasTopLevel 25from slither.core.variables.state_variable import StateVariable 26from slither.core.variables.top_level_variable import TopLevelVariable 27from slither.slithir.operations import InternalCall 28from slither.slithir.variables import Constant 29 30if TYPE_CHECKING: 31 from slither.core.slither_core import SlitherCore 32 33 34class Language(Enum): 35 SOLIDITY = "solidity" 36 VYPER = "vyper" 37 38 @staticmethod 39 def from_str(label: str): 40 if label == "solc": 41 return Language.SOLIDITY 42 if label == "vyper": 43 return Language.VYPER 44 45 raise ValueError(f"Unknown language: {label}") 46 47 48# pylint: disable=too-many-instance-attributes,too-many-public-methods 49class SlitherCompilationUnit(Context): 50 def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit) -> None: 51 super().__init__() 52 53 self._core = core 54 self._crytic_compile_compilation_unit = crytic_compilation_unit 55 self._language = Language.from_str(crytic_compilation_unit.compiler_version.compiler) 56 57 # Top level object 58 self.contracts: List[Contract] = [] 59 self._structures_top_level: List[StructureTopLevel] = [] 60 self._enums_top_level: List[EnumTopLevel] = [] 61 self._events_top_level: List[EventTopLevel] = [] 62 self._variables_top_level: List[TopLevelVariable] = [] 63 self._functions_top_level: List[FunctionTopLevel] = [] 64 self._using_for_top_level: List[UsingForTopLevel] = [] 65 self._pragma_directives: List[Pragma] = [] 66 self._import_directives: List[Import] = [] 67 self._custom_errors: List[CustomErrorTopLevel] = [] 68 self._type_aliases: Dict[str, TypeAliasTopLevel] = {} 69 70 self._all_functions: Set[Function] = set() 71 self._all_modifiers: Set[Modifier] = set() 72 73 # Memoize 74 self._all_state_variables: Optional[Set[StateVariable]] = None 75 76 self._storage_layouts: Dict[str, Dict[str, Tuple[int, int]]] = {} 77 78 self._contract_with_missing_inheritance: Set[Contract] = set() 79 80 self._source_units: Dict[int, str] = {} 81 82 self.counter_slithir_tuple = 0 83 self.counter_slithir_temporary = 0 84 self.counter_slithir_reference = 0 85 86 self.scopes: Dict[Filename, FileScope] = {} 87 88 @property 89 def core(self) -> "SlitherCore": 90 return self._core 91 92 @property 93 def source_units(self) -> Dict[int, str]: 94 return self._source_units 95 96 # endregion 97 ################################################################################### 98 ################################################################################### 99 # region Compiler 100 ################################################################################### 101 ################################################################################### 102 @property 103 def language(self) -> Language: 104 return self._language 105 106 @property 107 def is_vyper(self) -> bool: 108 return self._language == Language.VYPER 109 110 @property 111 def is_solidity(self) -> bool: 112 return self._language == Language.SOLIDITY 113 114 @property 115 def compiler_version(self) -> CompilerVersion: 116 return self._crytic_compile_compilation_unit.compiler_version 117 118 @property 119 def solc_version(self) -> str: 120 # TODO: make version a non optional argument of compiler version in cc 121 return self._crytic_compile_compilation_unit.compiler_version.version # type:ignore 122 123 @property 124 def crytic_compile_compilation_unit(self) -> CompilationUnit: 125 return self._crytic_compile_compilation_unit 126 127 @property 128 def crytic_compile(self) -> CryticCompile: 129 return self._crytic_compile_compilation_unit.crytic_compile 130 131 # endregion 132 ################################################################################### 133 ################################################################################### 134 # region Pragma attributes 135 ################################################################################### 136 ################################################################################### 137 138 @property 139 def pragma_directives(self) -> List[Pragma]: 140 """list(core.declarations.Pragma): Pragma directives.""" 141 return self._pragma_directives 142 143 @property 144 def import_directives(self) -> List[Import]: 145 """list(core.declarations.Import): Import directives""" 146 return self._import_directives 147 148 # endregion 149 ################################################################################### 150 ################################################################################### 151 # region Contracts 152 ################################################################################### 153 ################################################################################### 154 155 @property 156 def contracts_derived(self) -> List[Contract]: 157 """list(Contract): List of contracts that are derived and not inherited.""" 158 inheritances = [x.inheritance for x in self.contracts] 159 inheritance = [item for sublist in inheritances for item in sublist] 160 return [c for c in self.contracts if c not in inheritance] 161 162 def get_contract_from_name(self, contract_name: Union[str, Constant]) -> List[Contract]: 163 """ 164 Return a list of contract from a name 165 Args: 166 contract_name (str): name of the contract 167 Returns: 168 List[Contract] 169 """ 170 return [c for c in self.contracts if c.name == contract_name] 171 172 # endregion 173 ################################################################################### 174 ################################################################################### 175 # region Functions and modifiers 176 ################################################################################### 177 ################################################################################### 178 179 @property 180 def functions(self) -> List[Function]: 181 return list(self._all_functions) 182 183 def add_function(self, func: Function) -> None: 184 self._all_functions.add(func) 185 186 @property 187 def modifiers(self) -> List[Modifier]: 188 return list(self._all_modifiers) 189 190 def add_modifier(self, modif: Modifier) -> None: 191 self._all_modifiers.add(modif) 192 193 @property 194 def functions_and_modifiers(self) -> List[Function]: 195 return self.functions + list(self.modifiers) 196 197 def propagate_function_calls(self) -> None: 198 """This info is used to compute the rvalues of Phi operations in `fix_phi` and ultimately 199 is responsible for the `read` property of Phi operations which is vital to 200 propagating taints inter-procedurally 201 """ 202 for f in self.functions_and_modifiers: 203 for node in f.nodes: 204 for ir in node.irs_ssa: 205 if isinstance(ir, InternalCall): 206 assert ir.function 207 ir.function.add_reachable_from_node(node, ir) 208 209 # endregion 210 ################################################################################### 211 ################################################################################### 212 # region Variables 213 ################################################################################### 214 ################################################################################### 215 216 @property 217 def state_variables(self) -> List[StateVariable]: 218 if self._all_state_variables is None: 219 state_variabless = [c.state_variables for c in self.contracts] 220 state_variables = [item for sublist in state_variabless for item in sublist] 221 self._all_state_variables = set(state_variables) 222 return list(self._all_state_variables) 223 224 # endregion 225 ################################################################################### 226 ################################################################################### 227 # region Top level 228 ################################################################################### 229 ################################################################################### 230 231 @property 232 def structures_top_level(self) -> List[StructureTopLevel]: 233 return self._structures_top_level 234 235 @property 236 def enums_top_level(self) -> List[EnumTopLevel]: 237 return self._enums_top_level 238 239 @property 240 def events_top_level(self) -> List[EventTopLevel]: 241 return self._events_top_level 242 243 @property 244 def variables_top_level(self) -> List[TopLevelVariable]: 245 return self._variables_top_level 246 247 @property 248 def functions_top_level(self) -> List[FunctionTopLevel]: 249 return self._functions_top_level 250 251 @property 252 def using_for_top_level(self) -> List[UsingForTopLevel]: 253 return self._using_for_top_level 254 255 @property 256 def custom_errors(self) -> List[CustomErrorTopLevel]: 257 return self._custom_errors 258 259 @property 260 def type_aliases(self) -> Dict[str, TypeAliasTopLevel]: 261 return self._type_aliases 262 263 # endregion 264 ################################################################################### 265 ################################################################################### 266 # region Internals 267 ################################################################################### 268 ################################################################################### 269 270 @property 271 def contracts_with_missing_inheritance(self) -> Set[Contract]: 272 return self._contract_with_missing_inheritance 273 274 # endregion 275 ################################################################################### 276 ################################################################################### 277 # region Scope 278 ################################################################################### 279 ################################################################################### 280 281 def get_scope(self, filename_str: str) -> FileScope: 282 filename = self._crytic_compile_compilation_unit.crytic_compile.filename_lookup( 283 filename_str 284 ) 285 286 if filename not in self.scopes: 287 self.scopes[filename] = FileScope(filename) 288 289 return self.scopes[filename] 290 291 # endregion 292 ################################################################################### 293 ################################################################################### 294 # region Storage Layouts 295 ################################################################################### 296 ################################################################################### 297 298 def compute_storage_layout(self) -> None: 299 assert self.is_solidity 300 for contract in self.contracts_derived: 301 self._storage_layouts[contract.name] = {} 302 303 slot = 0 304 offset = 0 305 for var in contract.stored_state_variables_ordered: 306 assert var.type 307 size, new_slot = var.type.storage_size 308 309 if new_slot: 310 if offset > 0: 311 slot += 1 312 offset = 0 313 elif size + offset > 32: 314 slot += 1 315 offset = 0 316 317 self._storage_layouts[contract.name][var.canonical_name] = ( 318 slot, 319 offset, 320 ) 321 if new_slot: 322 slot += math.ceil(size / 32) 323 else: 324 offset += size 325 326 def storage_layout_of(self, contract: Contract, var: StateVariable) -> Tuple[int, int]: 327 return self._storage_layouts[contract.name][var.canonical_name] 328 329 # endregion
class
Language(enum.Enum):
35class Language(Enum): 36 SOLIDITY = "solidity" 37 VYPER = "vyper" 38 39 @staticmethod 40 def from_str(label: str): 41 if label == "solc": 42 return Language.SOLIDITY 43 if label == "vyper": 44 return Language.VYPER 45 46 raise ValueError(f"Unknown language: {label}")
An enumeration.
SOLIDITY =
<Language.SOLIDITY: 'solidity'>
VYPER =
<Language.VYPER: 'vyper'>
Inherited Members
- enum.Enum
- name
- value
50class SlitherCompilationUnit(Context): 51 def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit) -> None: 52 super().__init__() 53 54 self._core = core 55 self._crytic_compile_compilation_unit = crytic_compilation_unit 56 self._language = Language.from_str(crytic_compilation_unit.compiler_version.compiler) 57 58 # Top level object 59 self.contracts: List[Contract] = [] 60 self._structures_top_level: List[StructureTopLevel] = [] 61 self._enums_top_level: List[EnumTopLevel] = [] 62 self._events_top_level: List[EventTopLevel] = [] 63 self._variables_top_level: List[TopLevelVariable] = [] 64 self._functions_top_level: List[FunctionTopLevel] = [] 65 self._using_for_top_level: List[UsingForTopLevel] = [] 66 self._pragma_directives: List[Pragma] = [] 67 self._import_directives: List[Import] = [] 68 self._custom_errors: List[CustomErrorTopLevel] = [] 69 self._type_aliases: Dict[str, TypeAliasTopLevel] = {} 70 71 self._all_functions: Set[Function] = set() 72 self._all_modifiers: Set[Modifier] = set() 73 74 # Memoize 75 self._all_state_variables: Optional[Set[StateVariable]] = None 76 77 self._storage_layouts: Dict[str, Dict[str, Tuple[int, int]]] = {} 78 79 self._contract_with_missing_inheritance: Set[Contract] = set() 80 81 self._source_units: Dict[int, str] = {} 82 83 self.counter_slithir_tuple = 0 84 self.counter_slithir_temporary = 0 85 self.counter_slithir_reference = 0 86 87 self.scopes: Dict[Filename, FileScope] = {} 88 89 @property 90 def core(self) -> "SlitherCore": 91 return self._core 92 93 @property 94 def source_units(self) -> Dict[int, str]: 95 return self._source_units 96 97 # endregion 98 ################################################################################### 99 ################################################################################### 100 # region Compiler 101 ################################################################################### 102 ################################################################################### 103 @property 104 def language(self) -> Language: 105 return self._language 106 107 @property 108 def is_vyper(self) -> bool: 109 return self._language == Language.VYPER 110 111 @property 112 def is_solidity(self) -> bool: 113 return self._language == Language.SOLIDITY 114 115 @property 116 def compiler_version(self) -> CompilerVersion: 117 return self._crytic_compile_compilation_unit.compiler_version 118 119 @property 120 def solc_version(self) -> str: 121 # TODO: make version a non optional argument of compiler version in cc 122 return self._crytic_compile_compilation_unit.compiler_version.version # type:ignore 123 124 @property 125 def crytic_compile_compilation_unit(self) -> CompilationUnit: 126 return self._crytic_compile_compilation_unit 127 128 @property 129 def crytic_compile(self) -> CryticCompile: 130 return self._crytic_compile_compilation_unit.crytic_compile 131 132 # endregion 133 ################################################################################### 134 ################################################################################### 135 # region Pragma attributes 136 ################################################################################### 137 ################################################################################### 138 139 @property 140 def pragma_directives(self) -> List[Pragma]: 141 """list(core.declarations.Pragma): Pragma directives.""" 142 return self._pragma_directives 143 144 @property 145 def import_directives(self) -> List[Import]: 146 """list(core.declarations.Import): Import directives""" 147 return self._import_directives 148 149 # endregion 150 ################################################################################### 151 ################################################################################### 152 # region Contracts 153 ################################################################################### 154 ################################################################################### 155 156 @property 157 def contracts_derived(self) -> List[Contract]: 158 """list(Contract): List of contracts that are derived and not inherited.""" 159 inheritances = [x.inheritance for x in self.contracts] 160 inheritance = [item for sublist in inheritances for item in sublist] 161 return [c for c in self.contracts if c not in inheritance] 162 163 def get_contract_from_name(self, contract_name: Union[str, Constant]) -> List[Contract]: 164 """ 165 Return a list of contract from a name 166 Args: 167 contract_name (str): name of the contract 168 Returns: 169 List[Contract] 170 """ 171 return [c for c in self.contracts if c.name == contract_name] 172 173 # endregion 174 ################################################################################### 175 ################################################################################### 176 # region Functions and modifiers 177 ################################################################################### 178 ################################################################################### 179 180 @property 181 def functions(self) -> List[Function]: 182 return list(self._all_functions) 183 184 def add_function(self, func: Function) -> None: 185 self._all_functions.add(func) 186 187 @property 188 def modifiers(self) -> List[Modifier]: 189 return list(self._all_modifiers) 190 191 def add_modifier(self, modif: Modifier) -> None: 192 self._all_modifiers.add(modif) 193 194 @property 195 def functions_and_modifiers(self) -> List[Function]: 196 return self.functions + list(self.modifiers) 197 198 def propagate_function_calls(self) -> None: 199 """This info is used to compute the rvalues of Phi operations in `fix_phi` and ultimately 200 is responsible for the `read` property of Phi operations which is vital to 201 propagating taints inter-procedurally 202 """ 203 for f in self.functions_and_modifiers: 204 for node in f.nodes: 205 for ir in node.irs_ssa: 206 if isinstance(ir, InternalCall): 207 assert ir.function 208 ir.function.add_reachable_from_node(node, ir) 209 210 # endregion 211 ################################################################################### 212 ################################################################################### 213 # region Variables 214 ################################################################################### 215 ################################################################################### 216 217 @property 218 def state_variables(self) -> List[StateVariable]: 219 if self._all_state_variables is None: 220 state_variabless = [c.state_variables for c in self.contracts] 221 state_variables = [item for sublist in state_variabless for item in sublist] 222 self._all_state_variables = set(state_variables) 223 return list(self._all_state_variables) 224 225 # endregion 226 ################################################################################### 227 ################################################################################### 228 # region Top level 229 ################################################################################### 230 ################################################################################### 231 232 @property 233 def structures_top_level(self) -> List[StructureTopLevel]: 234 return self._structures_top_level 235 236 @property 237 def enums_top_level(self) -> List[EnumTopLevel]: 238 return self._enums_top_level 239 240 @property 241 def events_top_level(self) -> List[EventTopLevel]: 242 return self._events_top_level 243 244 @property 245 def variables_top_level(self) -> List[TopLevelVariable]: 246 return self._variables_top_level 247 248 @property 249 def functions_top_level(self) -> List[FunctionTopLevel]: 250 return self._functions_top_level 251 252 @property 253 def using_for_top_level(self) -> List[UsingForTopLevel]: 254 return self._using_for_top_level 255 256 @property 257 def custom_errors(self) -> List[CustomErrorTopLevel]: 258 return self._custom_errors 259 260 @property 261 def type_aliases(self) -> Dict[str, TypeAliasTopLevel]: 262 return self._type_aliases 263 264 # endregion 265 ################################################################################### 266 ################################################################################### 267 # region Internals 268 ################################################################################### 269 ################################################################################### 270 271 @property 272 def contracts_with_missing_inheritance(self) -> Set[Contract]: 273 return self._contract_with_missing_inheritance 274 275 # endregion 276 ################################################################################### 277 ################################################################################### 278 # region Scope 279 ################################################################################### 280 ################################################################################### 281 282 def get_scope(self, filename_str: str) -> FileScope: 283 filename = self._crytic_compile_compilation_unit.crytic_compile.filename_lookup( 284 filename_str 285 ) 286 287 if filename not in self.scopes: 288 self.scopes[filename] = FileScope(filename) 289 290 return self.scopes[filename] 291 292 # endregion 293 ################################################################################### 294 ################################################################################### 295 # region Storage Layouts 296 ################################################################################### 297 ################################################################################### 298 299 def compute_storage_layout(self) -> None: 300 assert self.is_solidity 301 for contract in self.contracts_derived: 302 self._storage_layouts[contract.name] = {} 303 304 slot = 0 305 offset = 0 306 for var in contract.stored_state_variables_ordered: 307 assert var.type 308 size, new_slot = var.type.storage_size 309 310 if new_slot: 311 if offset > 0: 312 slot += 1 313 offset = 0 314 elif size + offset > 32: 315 slot += 1 316 offset = 0 317 318 self._storage_layouts[contract.name][var.canonical_name] = ( 319 slot, 320 offset, 321 ) 322 if new_slot: 323 slot += math.ceil(size / 32) 324 else: 325 offset += size 326 327 def storage_layout_of(self, contract: Contract, var: StateVariable) -> Tuple[int, int]: 328 return self._storage_layouts[contract.name][var.canonical_name] 329 330 # endregion
SlitherCompilationUnit( core: slither.core.slither_core.SlitherCore, crytic_compilation_unit: crytic_compile.compilation_unit.CompilationUnit)
51 def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit) -> None: 52 super().__init__() 53 54 self._core = core 55 self._crytic_compile_compilation_unit = crytic_compilation_unit 56 self._language = Language.from_str(crytic_compilation_unit.compiler_version.compiler) 57 58 # Top level object 59 self.contracts: List[Contract] = [] 60 self._structures_top_level: List[StructureTopLevel] = [] 61 self._enums_top_level: List[EnumTopLevel] = [] 62 self._events_top_level: List[EventTopLevel] = [] 63 self._variables_top_level: List[TopLevelVariable] = [] 64 self._functions_top_level: List[FunctionTopLevel] = [] 65 self._using_for_top_level: List[UsingForTopLevel] = [] 66 self._pragma_directives: List[Pragma] = [] 67 self._import_directives: List[Import] = [] 68 self._custom_errors: List[CustomErrorTopLevel] = [] 69 self._type_aliases: Dict[str, TypeAliasTopLevel] = {} 70 71 self._all_functions: Set[Function] = set() 72 self._all_modifiers: Set[Modifier] = set() 73 74 # Memoize 75 self._all_state_variables: Optional[Set[StateVariable]] = None 76 77 self._storage_layouts: Dict[str, Dict[str, Tuple[int, int]]] = {} 78 79 self._contract_with_missing_inheritance: Set[Contract] = set() 80 81 self._source_units: Dict[int, str] = {} 82 83 self.counter_slithir_tuple = 0 84 self.counter_slithir_temporary = 0 85 self.counter_slithir_reference = 0 86 87 self.scopes: Dict[Filename, FileScope] = {}
contracts: List[slither.core.declarations.contract.Contract]
scopes: Dict[crytic_compile.utils.naming.Filename, slither.core.scope.scope.FileScope]
pragma_directives: List[slither.core.declarations.pragma_directive.Pragma]
139 @property 140 def pragma_directives(self) -> List[Pragma]: 141 """list(core.declarations.Pragma): Pragma directives.""" 142 return self._pragma_directives
list(core.declarations.Pragma): Pragma directives.
import_directives: List[slither.core.declarations.import_directive.Import]
144 @property 145 def import_directives(self) -> List[Import]: 146 """list(core.declarations.Import): Import directives""" 147 return self._import_directives
list(core.declarations.Import): Import directives
contracts_derived: List[slither.core.declarations.contract.Contract]
156 @property 157 def contracts_derived(self) -> List[Contract]: 158 """list(Contract): List of contracts that are derived and not inherited.""" 159 inheritances = [x.inheritance for x in self.contracts] 160 inheritance = [item for sublist in inheritances for item in sublist] 161 return [c for c in self.contracts if c not in inheritance]
list(Contract): List of contracts that are derived and not inherited.
def
get_contract_from_name( self, contract_name: Union[str, slither.slithir.variables.constant.Constant]) -> List[slither.core.declarations.contract.Contract]:
163 def get_contract_from_name(self, contract_name: Union[str, Constant]) -> List[Contract]: 164 """ 165 Return a list of contract from a name 166 Args: 167 contract_name (str): name of the contract 168 Returns: 169 List[Contract] 170 """ 171 return [c for c in self.contracts if c.name == contract_name]
Return a list of contract from a name Args: contract_name (str): name of the contract Returns: List[Contract]
functions: List[slither.core.declarations.function.Function]
modifiers: List[slither.core.declarations.modifier.Modifier]
functions_and_modifiers: List[slither.core.declarations.function.Function]
def
propagate_function_calls(self) -> None:
198 def propagate_function_calls(self) -> None: 199 """This info is used to compute the rvalues of Phi operations in `fix_phi` and ultimately 200 is responsible for the `read` property of Phi operations which is vital to 201 propagating taints inter-procedurally 202 """ 203 for f in self.functions_and_modifiers: 204 for node in f.nodes: 205 for ir in node.irs_ssa: 206 if isinstance(ir, InternalCall): 207 assert ir.function 208 ir.function.add_reachable_from_node(node, ir)
This info is used to compute the rvalues of Phi operations in fix_phi
and ultimately
is responsible for the read
property of Phi operations which is vital to
propagating taints inter-procedurally
state_variables: List[slither.core.variables.state_variable.StateVariable]
217 @property 218 def state_variables(self) -> List[StateVariable]: 219 if self._all_state_variables is None: 220 state_variabless = [c.state_variables for c in self.contracts] 221 state_variables = [item for sublist in state_variabless for item in sublist] 222 self._all_state_variables = set(state_variables) 223 return list(self._all_state_variables)
structures_top_level: List[slither.core.declarations.structure_top_level.StructureTopLevel]
enums_top_level: List[slither.core.declarations.enum_top_level.EnumTopLevel]
events_top_level: List[slither.core.declarations.event_top_level.EventTopLevel]
variables_top_level: List[slither.core.variables.top_level_variable.TopLevelVariable]
functions_top_level: List[slither.core.declarations.function_top_level.FunctionTopLevel]
using_for_top_level: List[slither.core.declarations.using_for_top_level.UsingForTopLevel]
custom_errors: List[slither.core.declarations.custom_error_top_level.CustomErrorTopLevel]
type_aliases: Dict[str, slither.core.solidity_types.type_alias.TypeAliasTopLevel]
contracts_with_missing_inheritance: Set[slither.core.declarations.contract.Contract]
def
compute_storage_layout(self) -> None:
299 def compute_storage_layout(self) -> None: 300 assert self.is_solidity 301 for contract in self.contracts_derived: 302 self._storage_layouts[contract.name] = {} 303 304 slot = 0 305 offset = 0 306 for var in contract.stored_state_variables_ordered: 307 assert var.type 308 size, new_slot = var.type.storage_size 309 310 if new_slot: 311 if offset > 0: 312 slot += 1 313 offset = 0 314 elif size + offset > 32: 315 slot += 1 316 offset = 0 317 318 self._storage_layouts[contract.name][var.canonical_name] = ( 319 slot, 320 offset, 321 ) 322 if new_slot: 323 slot += math.ceil(size / 32) 324 else: 325 offset += size
def
storage_layout_of( self, contract: slither.core.declarations.contract.Contract, var: slither.core.variables.state_variable.StateVariable) -> Tuple[int, int]: