slither.utils.encoding
1from typing import Union 2 3from slither.core import variables 4from slither.core.declarations import ( 5 SolidityVariable, 6 SolidityVariableComposed, 7 Structure, 8 Enum, 9 Contract, 10) 11from slither.core import solidity_types 12from slither.slithir import operations 13from slither.slithir import variables as SlitherIRVariable 14 15 16# pylint: disable=too-many-branches 17def ntype(_type: Union[solidity_types.Type, str]) -> str: 18 if isinstance(_type, solidity_types.ElementaryType): 19 _type = str(_type) 20 elif isinstance(_type, solidity_types.ArrayType): 21 if isinstance(_type.type, solidity_types.ElementaryType): 22 _type = str(_type) 23 else: 24 _type = "user_defined_array" 25 elif isinstance(_type, Structure): 26 _type = str(_type) 27 elif isinstance(_type, Enum): 28 _type = str(_type) 29 elif isinstance(_type, solidity_types.MappingType): 30 _type = str(_type) 31 elif isinstance(_type, solidity_types.UserDefinedType): 32 if isinstance(_type.type, Contract): 33 _type = f"contract({_type.type.name})" 34 elif isinstance(_type.type, Structure): 35 _type = f"struct({_type.type.name})" 36 elif isinstance(_type.type, Enum): 37 _type = f"enum({_type.type.name})" 38 else: 39 _type = str(_type) 40 41 _type = _type.replace(" memory", "") 42 _type = _type.replace(" storage ref", "") 43 44 if "struct" in _type: 45 return "struct" 46 if "enum" in _type: 47 return "enum" 48 if "tuple" in _type: 49 return "tuple" 50 if "contract" in _type: 51 return "contract" 52 if "mapping" in _type: 53 return "mapping" 54 return _type.replace(" ", "_") 55 56 57# pylint: disable=too-many-branches 58def encode_var_for_compare(var: Union[variables.Variable, SolidityVariable]) -> str: 59 60 # variables 61 if isinstance(var, SlitherIRVariable.Constant): 62 return f"constant({ntype(var.type)},{var.value})" 63 if isinstance(var, SolidityVariableComposed): 64 return f"solidity_variable_composed({var.name})" 65 if isinstance(var, SolidityVariable): 66 return f"solidity_variable{var.name}" 67 if isinstance(var, SlitherIRVariable.TemporaryVariable): 68 return "temporary_variable" 69 if isinstance(var, SlitherIRVariable.ReferenceVariable): 70 return f"reference({ntype(var.type)})" 71 if isinstance(var, variables.LocalVariable): 72 return f"local_solc_variable({ntype(var.type)},{var.location})" 73 if isinstance(var, variables.StateVariable): 74 if var.is_stored: 75 try: 76 slot, _ = var.contract.compilation_unit.storage_layout_of(var.contract, var) 77 except KeyError: 78 slot = var.name 79 else: 80 slot = var.name 81 return f"state_solc_variable({ntype(var.type)},{slot})" 82 if isinstance(var, variables.LocalVariableInitFromTuple): 83 return "local_variable_init_tuple" 84 if isinstance(var, SlitherIRVariable.TupleVariable): 85 return "tuple_variable" 86 87 # default 88 return "" 89 90 91# pylint: disable=too-many-branches 92def encode_ir_for_upgradeability_compare(ir: operations.Operation) -> str: 93 # operations 94 if isinstance(ir, operations.Assignment): 95 return f"({encode_var_for_compare(ir.lvalue)}):=({encode_var_for_compare(ir.rvalue)})" 96 if isinstance(ir, operations.Index): 97 return f"index({ntype(ir.variable_right.type)})" 98 if isinstance(ir, operations.Member): 99 return "member" # .format(ntype(ir._type)) 100 if isinstance(ir, operations.Length): 101 return "length" 102 if isinstance(ir, operations.Binary): 103 return f"binary({encode_var_for_compare(ir.variable_left)}{ir.type}{encode_var_for_compare(ir.variable_right)})" 104 if isinstance(ir, operations.Unary): 105 return f"unary({str(ir.type)})" 106 if isinstance(ir, operations.Condition): 107 return f"condition({encode_var_for_compare(ir.value)})" 108 if isinstance(ir, operations.NewStructure): 109 return "new_structure" 110 if isinstance(ir, operations.NewContract): 111 return "new_contract" 112 if isinstance(ir, operations.NewArray): 113 return f"new_array({ntype(ir.array_type)})" 114 if isinstance(ir, operations.NewElementaryType): 115 return f"new_elementary({ntype(ir.type)})" 116 if isinstance(ir, operations.Delete): 117 return f"delete({encode_var_for_compare(ir.lvalue)},{encode_var_for_compare(ir.variable)})" 118 if isinstance(ir, operations.SolidityCall): 119 return f"solidity_call({ir.function.full_name})" 120 if isinstance(ir, operations.InternalCall): 121 return f"internal_call({ntype(ir.type_call)})" 122 if isinstance(ir, operations.EventCall): # is this useful? 123 return "event" 124 if isinstance(ir, operations.LibraryCall): 125 return "library_call" 126 if isinstance(ir, operations.InternalDynamicCall): 127 return "internal_dynamic_call" 128 if isinstance(ir, operations.HighLevelCall): # TODO: improve 129 return "high_level_call" 130 if isinstance(ir, operations.LowLevelCall): # TODO: improve 131 return "low_level_call" 132 if isinstance(ir, operations.TypeConversion): 133 return f"type_conversion({ntype(ir.type)})" 134 if isinstance(ir, operations.Return): # this can be improved using values 135 return "return" # .format(ntype(ir.type)) 136 if isinstance(ir, operations.Transfer): 137 return f"transfer({encode_var_for_compare(ir.call_value)})" 138 if isinstance(ir, operations.Send): 139 return f"send({encode_var_for_compare(ir.call_value)})" 140 if isinstance(ir, operations.Unpack): # TODO: improve 141 return "unpack" 142 if isinstance(ir, operations.InitArray): # TODO: improve 143 return "init_array" 144 145 # default 146 return "" 147 148 149def encode_ir_for_halstead(ir: operations.Operation) -> str: 150 # operations 151 if isinstance(ir, operations.Assignment): 152 return "assignment" 153 if isinstance(ir, operations.Index): 154 return "index" 155 if isinstance(ir, operations.Member): 156 return "member" # .format(ntype(ir._type)) 157 if isinstance(ir, operations.Length): 158 return "length" 159 if isinstance(ir, operations.Binary): 160 return f"binary({str(ir.type)})" 161 if isinstance(ir, operations.Unary): 162 return f"unary({str(ir.type)})" 163 if isinstance(ir, operations.Condition): 164 return f"condition({encode_var_for_compare(ir.value)})" 165 if isinstance(ir, operations.NewStructure): 166 return "new_structure" 167 if isinstance(ir, operations.NewContract): 168 return "new_contract" 169 if isinstance(ir, operations.NewArray): 170 return f"new_array({ntype(ir.array_type)})" 171 if isinstance(ir, operations.NewElementaryType): 172 return f"new_elementary({ntype(ir.type)})" 173 if isinstance(ir, operations.Delete): 174 return "delete" 175 if isinstance(ir, operations.SolidityCall): 176 return f"solidity_call({ir.function.full_name})" 177 if isinstance(ir, operations.InternalCall): 178 return f"internal_call({ntype(ir.type_call)})" 179 if isinstance(ir, operations.EventCall): # is this useful? 180 return "event" 181 if isinstance(ir, operations.LibraryCall): 182 return "library_call" 183 if isinstance(ir, operations.InternalDynamicCall): 184 return "internal_dynamic_call" 185 if isinstance(ir, operations.HighLevelCall): # TODO: improve 186 return "high_level_call" 187 if isinstance(ir, operations.LowLevelCall): # TODO: improve 188 return "low_level_call" 189 if isinstance(ir, operations.TypeConversion): 190 return f"type_conversion({ntype(ir.type)})" 191 if isinstance(ir, operations.Return): # this can be improved using values 192 return "return" # .format(ntype(ir.type)) 193 if isinstance(ir, operations.Transfer): 194 return "transfer" 195 if isinstance(ir, operations.Send): 196 return "send" 197 if isinstance(ir, operations.Unpack): # TODO: improve 198 return "unpack" 199 if isinstance(ir, operations.InitArray): # TODO: improve 200 return "init_array" 201 # default 202 raise NotImplementedError(f"encode_ir_for_halstead: {ir}")
18def ntype(_type: Union[solidity_types.Type, str]) -> str: 19 if isinstance(_type, solidity_types.ElementaryType): 20 _type = str(_type) 21 elif isinstance(_type, solidity_types.ArrayType): 22 if isinstance(_type.type, solidity_types.ElementaryType): 23 _type = str(_type) 24 else: 25 _type = "user_defined_array" 26 elif isinstance(_type, Structure): 27 _type = str(_type) 28 elif isinstance(_type, Enum): 29 _type = str(_type) 30 elif isinstance(_type, solidity_types.MappingType): 31 _type = str(_type) 32 elif isinstance(_type, solidity_types.UserDefinedType): 33 if isinstance(_type.type, Contract): 34 _type = f"contract({_type.type.name})" 35 elif isinstance(_type.type, Structure): 36 _type = f"struct({_type.type.name})" 37 elif isinstance(_type.type, Enum): 38 _type = f"enum({_type.type.name})" 39 else: 40 _type = str(_type) 41 42 _type = _type.replace(" memory", "") 43 _type = _type.replace(" storage ref", "") 44 45 if "struct" in _type: 46 return "struct" 47 if "enum" in _type: 48 return "enum" 49 if "tuple" in _type: 50 return "tuple" 51 if "contract" in _type: 52 return "contract" 53 if "mapping" in _type: 54 return "mapping" 55 return _type.replace(" ", "_")
def
encode_var_for_compare( var: Union[slither.core.variables.variable.Variable, slither.core.declarations.solidity_variables.SolidityVariable]) -> str:
59def encode_var_for_compare(var: Union[variables.Variable, SolidityVariable]) -> str: 60 61 # variables 62 if isinstance(var, SlitherIRVariable.Constant): 63 return f"constant({ntype(var.type)},{var.value})" 64 if isinstance(var, SolidityVariableComposed): 65 return f"solidity_variable_composed({var.name})" 66 if isinstance(var, SolidityVariable): 67 return f"solidity_variable{var.name}" 68 if isinstance(var, SlitherIRVariable.TemporaryVariable): 69 return "temporary_variable" 70 if isinstance(var, SlitherIRVariable.ReferenceVariable): 71 return f"reference({ntype(var.type)})" 72 if isinstance(var, variables.LocalVariable): 73 return f"local_solc_variable({ntype(var.type)},{var.location})" 74 if isinstance(var, variables.StateVariable): 75 if var.is_stored: 76 try: 77 slot, _ = var.contract.compilation_unit.storage_layout_of(var.contract, var) 78 except KeyError: 79 slot = var.name 80 else: 81 slot = var.name 82 return f"state_solc_variable({ntype(var.type)},{slot})" 83 if isinstance(var, variables.LocalVariableInitFromTuple): 84 return "local_variable_init_tuple" 85 if isinstance(var, SlitherIRVariable.TupleVariable): 86 return "tuple_variable" 87 88 # default 89 return ""
def
encode_ir_for_upgradeability_compare(ir: slither.slithir.operations.operation.Operation) -> str:
93def encode_ir_for_upgradeability_compare(ir: operations.Operation) -> str: 94 # operations 95 if isinstance(ir, operations.Assignment): 96 return f"({encode_var_for_compare(ir.lvalue)}):=({encode_var_for_compare(ir.rvalue)})" 97 if isinstance(ir, operations.Index): 98 return f"index({ntype(ir.variable_right.type)})" 99 if isinstance(ir, operations.Member): 100 return "member" # .format(ntype(ir._type)) 101 if isinstance(ir, operations.Length): 102 return "length" 103 if isinstance(ir, operations.Binary): 104 return f"binary({encode_var_for_compare(ir.variable_left)}{ir.type}{encode_var_for_compare(ir.variable_right)})" 105 if isinstance(ir, operations.Unary): 106 return f"unary({str(ir.type)})" 107 if isinstance(ir, operations.Condition): 108 return f"condition({encode_var_for_compare(ir.value)})" 109 if isinstance(ir, operations.NewStructure): 110 return "new_structure" 111 if isinstance(ir, operations.NewContract): 112 return "new_contract" 113 if isinstance(ir, operations.NewArray): 114 return f"new_array({ntype(ir.array_type)})" 115 if isinstance(ir, operations.NewElementaryType): 116 return f"new_elementary({ntype(ir.type)})" 117 if isinstance(ir, operations.Delete): 118 return f"delete({encode_var_for_compare(ir.lvalue)},{encode_var_for_compare(ir.variable)})" 119 if isinstance(ir, operations.SolidityCall): 120 return f"solidity_call({ir.function.full_name})" 121 if isinstance(ir, operations.InternalCall): 122 return f"internal_call({ntype(ir.type_call)})" 123 if isinstance(ir, operations.EventCall): # is this useful? 124 return "event" 125 if isinstance(ir, operations.LibraryCall): 126 return "library_call" 127 if isinstance(ir, operations.InternalDynamicCall): 128 return "internal_dynamic_call" 129 if isinstance(ir, operations.HighLevelCall): # TODO: improve 130 return "high_level_call" 131 if isinstance(ir, operations.LowLevelCall): # TODO: improve 132 return "low_level_call" 133 if isinstance(ir, operations.TypeConversion): 134 return f"type_conversion({ntype(ir.type)})" 135 if isinstance(ir, operations.Return): # this can be improved using values 136 return "return" # .format(ntype(ir.type)) 137 if isinstance(ir, operations.Transfer): 138 return f"transfer({encode_var_for_compare(ir.call_value)})" 139 if isinstance(ir, operations.Send): 140 return f"send({encode_var_for_compare(ir.call_value)})" 141 if isinstance(ir, operations.Unpack): # TODO: improve 142 return "unpack" 143 if isinstance(ir, operations.InitArray): # TODO: improve 144 return "init_array" 145 146 # default 147 return ""
150def encode_ir_for_halstead(ir: operations.Operation) -> str: 151 # operations 152 if isinstance(ir, operations.Assignment): 153 return "assignment" 154 if isinstance(ir, operations.Index): 155 return "index" 156 if isinstance(ir, operations.Member): 157 return "member" # .format(ntype(ir._type)) 158 if isinstance(ir, operations.Length): 159 return "length" 160 if isinstance(ir, operations.Binary): 161 return f"binary({str(ir.type)})" 162 if isinstance(ir, operations.Unary): 163 return f"unary({str(ir.type)})" 164 if isinstance(ir, operations.Condition): 165 return f"condition({encode_var_for_compare(ir.value)})" 166 if isinstance(ir, operations.NewStructure): 167 return "new_structure" 168 if isinstance(ir, operations.NewContract): 169 return "new_contract" 170 if isinstance(ir, operations.NewArray): 171 return f"new_array({ntype(ir.array_type)})" 172 if isinstance(ir, operations.NewElementaryType): 173 return f"new_elementary({ntype(ir.type)})" 174 if isinstance(ir, operations.Delete): 175 return "delete" 176 if isinstance(ir, operations.SolidityCall): 177 return f"solidity_call({ir.function.full_name})" 178 if isinstance(ir, operations.InternalCall): 179 return f"internal_call({ntype(ir.type_call)})" 180 if isinstance(ir, operations.EventCall): # is this useful? 181 return "event" 182 if isinstance(ir, operations.LibraryCall): 183 return "library_call" 184 if isinstance(ir, operations.InternalDynamicCall): 185 return "internal_dynamic_call" 186 if isinstance(ir, operations.HighLevelCall): # TODO: improve 187 return "high_level_call" 188 if isinstance(ir, operations.LowLevelCall): # TODO: improve 189 return "low_level_call" 190 if isinstance(ir, operations.TypeConversion): 191 return f"type_conversion({ntype(ir.type)})" 192 if isinstance(ir, operations.Return): # this can be improved using values 193 return "return" # .format(ntype(ir.type)) 194 if isinstance(ir, operations.Transfer): 195 return "transfer" 196 if isinstance(ir, operations.Send): 197 return "send" 198 if isinstance(ir, operations.Unpack): # TODO: improve 199 return "unpack" 200 if isinstance(ir, operations.InitArray): # TODO: improve 201 return "init_array" 202 # default 203 raise NotImplementedError(f"encode_ir_for_halstead: {ir}")