|
|
|
@ -39,10 +39,12 @@ class UnknownType: # pylint: disable=too-few-public-methods |
|
|
|
|
|
|
|
|
|
def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,too-many-statements |
|
|
|
|
name: str, |
|
|
|
|
contract: Contract, |
|
|
|
|
contracts: List[Contract], |
|
|
|
|
structures: List["Structure"], |
|
|
|
|
enums: List["Enum"], |
|
|
|
|
functions_direct_access: List["Function"], |
|
|
|
|
contracts_direct_access: List["Contract"], |
|
|
|
|
structures_direct_access: List["Structure"], |
|
|
|
|
all_structures: List["Structure"], |
|
|
|
|
enums_direct_access: List["Enum"], |
|
|
|
|
all_enums: List["Enum"], |
|
|
|
|
) -> Type: |
|
|
|
|
name_elementary = name.split(" ")[0] |
|
|
|
|
if "[" in name_elementary: |
|
|
|
@ -60,20 +62,20 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t |
|
|
|
|
name_contract = name_contract[len("contract ") :] |
|
|
|
|
if name_contract.startswith("library "): |
|
|
|
|
name_contract = name_contract[len("library ") :] |
|
|
|
|
var_type = next((c for c in contracts if c.name == name_contract), None) |
|
|
|
|
var_type = next((c for c in contracts_direct_access if c.name == name_contract), None) |
|
|
|
|
|
|
|
|
|
if not var_type: |
|
|
|
|
var_type = next((st for st in structures if st.name == name), None) |
|
|
|
|
var_type = next((st for st in structures_direct_access if st.name == name), None) |
|
|
|
|
if not var_type: |
|
|
|
|
var_type = next((e for e in enums if e.name == name), None) |
|
|
|
|
var_type = next((e for e in enums_direct_access if e.name == name), None) |
|
|
|
|
if not var_type: |
|
|
|
|
# any contract can refer to another contract's enum |
|
|
|
|
enum_name = name |
|
|
|
|
if enum_name.startswith("enum "): |
|
|
|
|
enum_name = enum_name[len("enum ") :] |
|
|
|
|
all_enums = [c.enums for c in contracts] |
|
|
|
|
all_enums = [item for sublist in all_enums for item in sublist] |
|
|
|
|
all_enums += contract.slither.enums_top_level |
|
|
|
|
# all_enums = [c.enums for c in contracts] |
|
|
|
|
# all_enums = [item for sublist in all_enums for item in sublist] |
|
|
|
|
# all_enums += contract.slither.enums_top_level |
|
|
|
|
var_type = next((e for e in all_enums if e.name == enum_name), None) |
|
|
|
|
if not var_type: |
|
|
|
|
var_type = next((e for e in all_enums if e.canonical_name == enum_name), None) |
|
|
|
@ -83,9 +85,9 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t |
|
|
|
|
if name_struct.startswith("struct "): |
|
|
|
|
name_struct = name_struct[len("struct ") :] |
|
|
|
|
name_struct = name_struct.split(" ")[0] # remove stuff like storage pointer at the end |
|
|
|
|
all_structures = [c.structures for c in contracts] |
|
|
|
|
all_structures = [item for sublist in all_structures for item in sublist] |
|
|
|
|
all_structures += contract.slither.structures_top_level |
|
|
|
|
# all_structures = [c.structures for c in contracts] |
|
|
|
|
# all_structures = [item for sublist in all_structures for item in sublist] |
|
|
|
|
# all_structures += contract.slither.structures_top_level |
|
|
|
|
var_type = next((st for st in all_structures if st.name == name_struct), None) |
|
|
|
|
if not var_type: |
|
|
|
|
var_type = next((st for st in all_structures if st.canonical_name == name_struct), None) |
|
|
|
@ -100,7 +102,7 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t |
|
|
|
|
return ArrayType(UserDefinedType(var_type), Literal(depth, "uint256")) |
|
|
|
|
|
|
|
|
|
if not var_type: |
|
|
|
|
var_type = next((f for f in contract.functions if f.name == name), None) |
|
|
|
|
var_type = next((f for f in functions_direct_access if f.name == name), None) |
|
|
|
|
if not var_type: |
|
|
|
|
if name.startswith("function "): |
|
|
|
|
found = re.findall( |
|
|
|
@ -112,10 +114,27 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t |
|
|
|
|
[v for v in found[0][1].split(",") if v != ""] if len(found[0]) > 1 else [] |
|
|
|
|
) |
|
|
|
|
params = [ |
|
|
|
|
_find_from_type_name(p, contract, contracts, structures, enums) for p in params |
|
|
|
|
_find_from_type_name( |
|
|
|
|
p, |
|
|
|
|
functions_direct_access, |
|
|
|
|
contracts_direct_access, |
|
|
|
|
structures_direct_access, |
|
|
|
|
all_structures, |
|
|
|
|
enums_direct_access, |
|
|
|
|
all_enums, |
|
|
|
|
) |
|
|
|
|
for p in params |
|
|
|
|
] |
|
|
|
|
return_values = [ |
|
|
|
|
_find_from_type_name(r, contract, contracts, structures, enums) |
|
|
|
|
_find_from_type_name( |
|
|
|
|
r, |
|
|
|
|
functions_direct_access, |
|
|
|
|
contracts_direct_access, |
|
|
|
|
structures_direct_access, |
|
|
|
|
all_structures, |
|
|
|
|
enums_direct_access, |
|
|
|
|
all_enums, |
|
|
|
|
) |
|
|
|
|
for r in return_values |
|
|
|
|
] |
|
|
|
|
params_vars = [] |
|
|
|
@ -142,8 +161,24 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t |
|
|
|
|
from_ = found[0][0] |
|
|
|
|
to_ = found[0][1] |
|
|
|
|
|
|
|
|
|
from_type = _find_from_type_name(from_, contract, contracts, structures, enums) |
|
|
|
|
to_type = _find_from_type_name(to_, contract, contracts, structures, enums) |
|
|
|
|
from_type = _find_from_type_name( |
|
|
|
|
from_, |
|
|
|
|
functions_direct_access, |
|
|
|
|
contracts_direct_access, |
|
|
|
|
structures_direct_access, |
|
|
|
|
all_structures, |
|
|
|
|
enums_direct_access, |
|
|
|
|
all_enums, |
|
|
|
|
) |
|
|
|
|
to_type = _find_from_type_name( |
|
|
|
|
to_, |
|
|
|
|
functions_direct_access, |
|
|
|
|
contracts_direct_access, |
|
|
|
|
structures_direct_access, |
|
|
|
|
all_structures, |
|
|
|
|
enums_direct_access, |
|
|
|
|
all_enums, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
return MappingType(from_type, to_type) |
|
|
|
|
|
|
|
|
@ -160,29 +195,59 @@ def parse_type(t: Union[Dict, UnknownType], caller_context): |
|
|
|
|
from slither.solc_parsing.variables.function_type_variable import FunctionTypeVariableSolc |
|
|
|
|
from slither.solc_parsing.declarations.contract import ContractSolc |
|
|
|
|
from slither.solc_parsing.declarations.function import FunctionSolc |
|
|
|
|
from slither.solc_parsing.slitherSolc import SlitherSolc |
|
|
|
|
|
|
|
|
|
if isinstance(caller_context, ContractSolc): |
|
|
|
|
contract = caller_context.underlying_contract |
|
|
|
|
contract_parser = caller_context |
|
|
|
|
is_compact_ast = caller_context.is_compact_ast |
|
|
|
|
elif isinstance(caller_context, FunctionSolc): |
|
|
|
|
if isinstance(caller_context, (ContractSolc, FunctionSolc)): |
|
|
|
|
if isinstance(caller_context, FunctionSolc): |
|
|
|
|
contract = caller_context.underlying_function.contract |
|
|
|
|
contract_parser = caller_context.contract_parser |
|
|
|
|
is_compact_ast = caller_context.is_compact_ast |
|
|
|
|
else: |
|
|
|
|
contract = caller_context.underlying_contract |
|
|
|
|
contract_parser = caller_context |
|
|
|
|
|
|
|
|
|
structures_direct_access = contract.structures + contract.slither.structures_top_level |
|
|
|
|
all_structuress = [c.structures for c in contract.slither.contracts] |
|
|
|
|
all_structures = [item for sublist in all_structuress for item in sublist] |
|
|
|
|
all_structures += contract.slither.structures_top_level |
|
|
|
|
enums_direct_access = contract.enums + contract.slither.enums_top_level |
|
|
|
|
all_enumss = [c.enums for c in contract.slither.contracts] |
|
|
|
|
all_enums = [item for sublist in all_enumss for item in sublist] |
|
|
|
|
all_enums += contract.slither.enums_top_level |
|
|
|
|
contracts = contract.slither.contracts |
|
|
|
|
functions = contract.functions |
|
|
|
|
|
|
|
|
|
elif isinstance(caller_context, SlitherSolc): |
|
|
|
|
structures_direct_access = caller_context.core.structures_top_level |
|
|
|
|
all_structuress = [c.structures for c in caller_context.core.contracts] |
|
|
|
|
all_structures = [item for sublist in all_structuress for item in sublist] |
|
|
|
|
all_structures += structures_direct_access |
|
|
|
|
enums_direct_access = caller_context.core.enums_top_level |
|
|
|
|
all_enumss = [c.enums for c in caller_context.core.contracts] |
|
|
|
|
all_enums = [item for sublist in all_enumss for item in sublist] |
|
|
|
|
all_enums += enums_direct_access |
|
|
|
|
contracts = caller_context.core.contracts |
|
|
|
|
functions = [] |
|
|
|
|
else: |
|
|
|
|
raise ParsingError(f"Incorrect caller context: {type(caller_context)}") |
|
|
|
|
|
|
|
|
|
is_compact_ast = caller_context.is_compact_ast |
|
|
|
|
if is_compact_ast: |
|
|
|
|
key = "nodeType" |
|
|
|
|
else: |
|
|
|
|
key = "name" |
|
|
|
|
|
|
|
|
|
structures = contract.structures + contract.slither.structures_top_level |
|
|
|
|
enums = contract.enums + contract.slither.enums_top_level |
|
|
|
|
contracts = contract.slither.contracts |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if isinstance(t, UnknownType): |
|
|
|
|
return _find_from_type_name(t.name, contract, contracts, structures, enums) |
|
|
|
|
return _find_from_type_name( |
|
|
|
|
t.name, |
|
|
|
|
functions, |
|
|
|
|
contracts, |
|
|
|
|
structures_direct_access, |
|
|
|
|
all_structures, |
|
|
|
|
enums_direct_access, |
|
|
|
|
all_enums, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if t[key] == "ElementaryTypeName": |
|
|
|
|
if is_compact_ast: |
|
|
|
@ -192,13 +257,25 @@ 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"], |
|
|
|
|
functions, |
|
|
|
|
contracts, |
|
|
|
|
structures_direct_access, |
|
|
|
|
all_structures, |
|
|
|
|
enums_direct_access, |
|
|
|
|
all_enums, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
# Determine if we have a type node (otherwise we use the name node, as some older solc did not have 'type'). |
|
|
|
|
type_name_key = "type" if "type" in t["attributes"] else key |
|
|
|
|
return _find_from_type_name( |
|
|
|
|
t["attributes"][type_name_key], contract, contracts, structures, enums |
|
|
|
|
t["attributes"][type_name_key], |
|
|
|
|
functions, |
|
|
|
|
contracts, |
|
|
|
|
structures_direct_access, |
|
|
|
|
all_structures, |
|
|
|
|
enums_direct_access, |
|
|
|
|
all_enums, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if t[key] == "ArrayTypeName": |
|
|
|
|