Change the way slither handles top level enum/struct

- Split declaration.Enum/Structure to EnumContract/EnumToplevel (same
for structure)
- Update the parsing accordingly
pull/728/head
Josselin 4 years ago
parent e52a2aee0e
commit 0a7738d225
  1. 2
      slither/core/declarations/__init__.py
  2. 23
      slither/core/declarations/contract.py
  3. 16
      slither/core/declarations/enum.py
  4. 17
      slither/core/declarations/enum_contract.py
  5. 6
      slither/core/declarations/enum_top_level.py
  6. 11
      slither/core/declarations/structure.py
  7. 12
      slither/core/declarations/structure_contract.py
  8. 6
      slither/core/declarations/structure_top_level.py
  9. 5
      slither/core/declarations/top_level.py
  10. 29
      slither/core/slither_core.py
  11. 6
      slither/slither.py
  12. 32
      slither/solc_parsing/declarations/contract.py
  13. 27
      slither/solc_parsing/declarations/structure_contract.py
  14. 56
      slither/solc_parsing/declarations/structure_top_level.py
  15. 4
      slither/solc_parsing/expressions/expression_parsing.py
  16. 109
      slither/solc_parsing/slitherSolc.py
  17. 6
      slither/solc_parsing/solidity_types/type_parsing.py
  18. 3
      tests/ast-parsing/expected/struct-0.6.0-compact.json
  19. 3
      tests/ast-parsing/expected/struct-0.6.1-compact.json
  20. 3
      tests/ast-parsing/expected/struct-0.6.10-compact.json
  21. 3
      tests/ast-parsing/expected/struct-0.6.11-compact.json
  22. 3
      tests/ast-parsing/expected/struct-0.6.12-compact.json
  23. 3
      tests/ast-parsing/expected/struct-0.6.2-compact.json
  24. 3
      tests/ast-parsing/expected/struct-0.6.3-compact.json
  25. 3
      tests/ast-parsing/expected/struct-0.6.4-compact.json
  26. 3
      tests/ast-parsing/expected/struct-0.6.5-compact.json
  27. 3
      tests/ast-parsing/expected/struct-0.6.6-compact.json
  28. 3
      tests/ast-parsing/expected/struct-0.6.7-compact.json
  29. 3
      tests/ast-parsing/expected/struct-0.6.8-compact.json
  30. 3
      tests/ast-parsing/expected/struct-0.6.9-compact.json
  31. 3
      tests/ast-parsing/expected/struct-0.7.0-compact.json
  32. 3
      tests/ast-parsing/expected/struct-0.7.1-compact.json
  33. 3
      tests/ast-parsing/expected/struct-0.7.2-compact.json
  34. 2
      tests/test_ast_parsing.py

@ -11,3 +11,5 @@ from .solidity_variables import (
SolidityFunction,
)
from .structure import Structure
from .enum_contract import EnumContract
from .structure_contract import StructureContract

@ -25,8 +25,7 @@ from slither.utils.tests_pattern import is_test_contract
# pylint: disable=too-many-lines,too-many-instance-attributes,import-outside-toplevel,too-many-nested-blocks
if TYPE_CHECKING:
from slither.utils.type_helpers import LibraryCallType, HighLevelCallType, InternalCallType
from slither.core.declarations import Enum, Event, Modifier
from slither.core.declarations import Structure
from slither.core.declarations import Enum, Event, Modifier, EnumContract, StructureContract
from slither.slithir.variables.variable import SlithIRVariable
from slither.core.variables.variable import Variable
from slither.core.variables.state_variable import StateVariable
@ -51,8 +50,8 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
# contract B is A(1) { ..
self._explicit_base_constructor_calls: List["Contract"] = []
self._enums: Dict[str, "Enum"] = {}
self._structures: Dict[str, "Structure"] = {}
self._enums: Dict[str, "EnumContract"] = {}
self._structures: Dict[str, "StructureContract"] = {}
self._events: Dict[str, "Event"] = {}
self._variables: Dict[str, "StateVariable"] = {}
self._variables_ordered: List["StateVariable"] = []
@ -135,28 +134,28 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
###################################################################################
@property
def structures(self) -> List["Structure"]:
def structures(self) -> List["StructureContract"]:
"""
list(Structure): List of the structures
"""
return list(self._structures.values())
@property
def structures_inherited(self) -> List["Structure"]:
def structures_inherited(self) -> List["StructureContract"]:
"""
list(Structure): List of the inherited structures
"""
return [s for s in self.structures if s.contract != self]
@property
def structures_declared(self) -> List["Structure"]:
def structures_declared(self) -> List["StructureContract"]:
"""
list(Structues): List of the structures declared within the contract (not inherited)
"""
return [s for s in self.structures if s.contract == self]
@property
def structures_as_dict(self) -> Dict[str, "Structure"]:
def structures_as_dict(self) -> Dict[str, "StructureContract"]:
return self._structures
# endregion
@ -167,25 +166,25 @@ class Contract(ChildSlither, SourceMapping): # pylint: disable=too-many-public-
###################################################################################
@property
def enums(self) -> List["Enum"]:
def enums(self) -> List["EnumContract"]:
return list(self._enums.values())
@property
def enums_inherited(self) -> List["Enum"]:
def enums_inherited(self) -> List["EnumContract"]:
"""
list(Enum): List of the inherited enums
"""
return [e for e in self.enums if e.contract != self]
@property
def enums_declared(self) -> List["Enum"]:
def enums_declared(self) -> List["EnumContract"]:
"""
list(Enum): List of the enums declared within the contract (not inherited)
"""
return [e for e in self.enums if e.contract == self]
@property
def enums_as_dict(self) -> Dict[str, "Enum"]:
def enums_as_dict(self) -> Dict[str, "EnumContract"]:
return self._enums
# endregion

@ -1,13 +1,9 @@
from typing import List, TYPE_CHECKING
from typing import List
from slither.core.source_mapping.source_mapping import SourceMapping
from slither.core.children.child_contract import ChildContract
if TYPE_CHECKING:
from slither.core.declarations import Contract
class Enum(ChildContract, SourceMapping):
class Enum(SourceMapping):
def __init__(self, name: str, canonical_name: str, values: List[str]):
super().__init__()
self._name = name
@ -26,13 +22,5 @@ class Enum(ChildContract, SourceMapping):
def values(self) -> List[str]:
return self._values
def is_declared_by(self, contract: "Contract") -> bool:
"""
Check if the element is declared by the contract
:param contract:
:return:
"""
return self.contract == contract
def __str__(self):
return self.name

@ -0,0 +1,17 @@
from typing import TYPE_CHECKING
from slither.core.children.child_contract import ChildContract
from slither.core.declarations import Enum
if TYPE_CHECKING:
from slither.core.declarations import Contract
class EnumContract(Enum, ChildContract):
def is_declared_by(self, contract: "Contract") -> bool:
"""
Check if the element is declared by the contract
:param contract:
:return:
"""
return self.contract == contract

@ -0,0 +1,6 @@
from slither.core.declarations import Enum
from slither.core.declarations.top_level import TopLevel
class EnumTopLevel(Enum, TopLevel):
pass

@ -1,13 +1,12 @@
from typing import List, TYPE_CHECKING, Dict
from slither.core.children.child_contract import ChildContract
from slither.core.source_mapping.source_mapping import SourceMapping
if TYPE_CHECKING:
from slither.core.variables.structure_variable import StructureVariable
class Structure(ChildContract, SourceMapping):
class Structure(SourceMapping):
def __init__(self):
super().__init__()
self._name = None
@ -39,14 +38,6 @@ class Structure(ChildContract, SourceMapping):
def add_elem_in_order(self, s: str):
self._elems_ordered.append(s)
def is_declared_by(self, contract):
"""
Check if the element is declared by the contract
:param contract:
:return:
"""
return self.contract == contract
@property
def elems_ordered(self) -> List["StructureVariable"]:
ret = []

@ -0,0 +1,12 @@
from slither.core.children.child_contract import ChildContract
from slither.core.declarations import Structure
class StructureContract(Structure, ChildContract):
def is_declared_by(self, contract):
"""
Check if the element is declared by the contract
:param contract:
:return:
"""
return self.contract == contract

@ -0,0 +1,6 @@
from slither.core.declarations import Structure
from slither.core.declarations.top_level import TopLevel
class StructureTopLevel(Structure, TopLevel):
pass

@ -0,0 +1,5 @@
from slither.core.source_mapping.source_mapping import SourceMapping
class TopLevel(SourceMapping):
pass

@ -1,11 +1,11 @@
"""
Main module
"""
import os
import logging
import json
import re
import logging
import math
import os
import re
from collections import defaultdict
from typing import Optional, Dict, List, Set, Union, Tuple
@ -18,9 +18,9 @@ from slither.core.declarations import (
Import,
Function,
Modifier,
Structure,
Enum,
)
from slither.core.declarations.enum_top_level import EnumTopLevel
from slither.core.declarations.structure_top_level import StructureTopLevel
from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations import InternalCall
from slither.slithir.variables import Constant
@ -44,12 +44,17 @@ class SlitherCore(Context): # pylint: disable=too-many-instance-attributes,too-
def __init__(self):
super().__init__()
# Top level object
self._contracts: Dict[str, Contract] = {}
self._structures_top_level: List[StructureTopLevel] = []
self._enums_top_level: List[EnumTopLevel] = []
self._pragma_directives: List[Pragma] = []
self._import_directives: List[Import] = []
self._filename: Optional[str] = None
self._source_units: Dict[int, str] = {}
self._solc_version: Optional[str] = None # '0.3' or '0.4':!
self._pragma_directives: List[Pragma] = []
self._import_directives: List[Import] = []
self._raw_source_code: Dict[str, str] = {}
self._all_functions: Set[Function] = set()
self._all_modifiers: Set[Modifier] = set()
@ -234,14 +239,12 @@ class SlitherCore(Context): # pylint: disable=too-many-instance-attributes,too-
###################################################################################
@property
def top_level_structures(self) -> List[Structure]:
top_level_structures = [c.structures for c in self.contracts if c.is_top_level]
return [st for sublist in top_level_structures for st in sublist]
def structures_top_level(self) -> List[StructureTopLevel]:
return self._structures_top_level
@property
def top_level_enums(self) -> List[Enum]:
top_level_enums = [c.enums for c in self.contracts if c.is_top_level]
return [st for sublist in top_level_enums for st in sublist]
def enums_top_level(self) -> List[EnumTopLevel]:
return self._enums_top_level
# endregion
###################################################################################

@ -78,7 +78,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes
# pylint: disable=raise-missing-from
raise SlitherError(f"Invalid compilation: \n{str(e)}")
for path, ast in crytic_compile.asts.items():
self._parser.parse_contracts_from_loaded_json(ast, path)
self._parser.parse_top_level_from_loaded_json(ast, path)
self.add_source_code(path)
if kwargs.get("generate_patches", False):
@ -120,7 +120,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes
self._parser = SlitherSolc(filename, self)
for c in contracts_json:
self._parser.parse_contracts_from_json(c)
self._parser.parse_top_level_from_json(c)
def _init_from_list(self, contract):
self._parser = SlitherSolc("", self)
@ -129,7 +129,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes
path = c["absolutePath"]
else:
path = c["attributes"]["absolutePath"]
self._parser.parse_contracts_from_loaded_json(c, path)
self._parser.parse_top_level_from_loaded_json(c, path)
@property
def detectors(self):

@ -1,15 +1,14 @@
import logging
from typing import List, Dict, Callable, TYPE_CHECKING, Union
from slither.core.declarations import Modifier, Structure, Event
from slither.core.declarations import Modifier, Event, EnumContract, StructureContract
from slither.core.declarations.contract import Contract
from slither.core.declarations.enum import Enum
from slither.core.declarations.function import Function
from slither.core.variables.state_variable import StateVariable
from slither.solc_parsing.declarations.event import EventSolc
from slither.solc_parsing.declarations.function import FunctionSolc
from slither.solc_parsing.declarations.modifier import ModifierSolc
from slither.solc_parsing.declarations.structure import StructureSolc
from slither.solc_parsing.declarations.structure_contract import StructureContractSolc
from slither.solc_parsing.exceptions import ParsingError, VariableNotFound
from slither.solc_parsing.solidity_types.type_parsing import parse_type
from slither.solc_parsing.variables.state_variable import StateVariableSolc
@ -44,7 +43,7 @@ class ContractSolc:
self._functions_parser: List[FunctionSolc] = []
self._modifiers_parser: List[ModifierSolc] = []
self._structures_parser: List[StructureSolc] = []
self._structures_parser: List[StructureContractSolc] = []
self._is_analyzed: bool = False
@ -252,28 +251,13 @@ class ContractSolc:
return
def _parse_struct(self, struct: Dict):
if self.is_compact_ast:
name = struct["name"]
attributes = struct
else:
name = struct["attributes"][self.get_key()]
attributes = struct["attributes"]
if "canonicalName" in attributes:
canonicalName = attributes["canonicalName"]
else:
canonicalName = self._contract.name + "." + name
if self.get_children("members") in struct:
children = struct[self.get_children("members")]
else:
children = [] # empty struct
st = Structure()
st = StructureContract()
st.set_contract(self._contract)
st.set_offset(struct["src"], self._contract.slither)
st_parser = StructureSolc(st, name, canonicalName, children, self)
self._contract.structures_as_dict[name] = st
st_parser = StructureContractSolc(st, struct, self)
self._contract.structures_as_dict[st.name] = st
self._structures_parser.append(st_parser)
def parse_structs(self):
@ -573,12 +557,12 @@ class ContractSolc:
else:
values.append(child["attributes"][self.get_key()])
new_enum = Enum(name, canonicalName, values)
new_enum = EnumContract(name, canonicalName, values)
new_enum.set_contract(self._contract)
new_enum.set_offset(enum["src"], self._contract.slither)
self._contract.enums_as_dict[canonicalName] = new_enum
def _analyze_struct(self, struct: StructureSolc): # pylint: disable=no-self-use
def _analyze_struct(self, struct: StructureContractSolc): # pylint: disable=no-self-use
struct.analyze()
def analyze_structs(self):

@ -1,7 +1,7 @@
"""
Structure module
"""
from typing import List, TYPE_CHECKING
from typing import List, TYPE_CHECKING, Dict
from slither.core.variables.structure_variable import StructureVariable
from slither.solc_parsing.variables.structure_variable import StructureVariableSolc
@ -11,7 +11,7 @@ if TYPE_CHECKING:
from slither.solc_parsing.declarations.contract import ContractSolc
class StructureSolc: # pylint: disable=too-few-public-methods
class StructureContractSolc: # pylint: disable=too-few-public-methods
"""
Structure class
"""
@ -19,19 +19,28 @@ class StructureSolc: # pylint: disable=too-few-public-methods
# elems = [(type, name)]
def __init__( # pylint: disable=too-many-arguments
self,
st: Structure,
name: str,
canonicalName: str,
elems: List[str],
contract_parser: "ContractSolc",
self, st: Structure, struct: Dict, contract_parser: "ContractSolc",
):
if contract_parser.is_compact_ast:
name = struct["name"]
attributes = struct
else:
name = struct["attributes"][contract_parser.get_key()]
attributes = struct["attributes"]
if "canonicalName" in attributes:
canonicalName = attributes["canonicalName"]
else:
canonicalName = contract_parser.underlying_contract.name + "." + name
children = struct["members"] if "members" in struct else struct.get("children", [])
self._structure = st
st.name = name
st.canonical_name = canonicalName
self._contract_parser = contract_parser
self._elemsNotParsed = elems
self._elemsNotParsed = children
def analyze(self):
for elem_to_parse in self._elemsNotParsed:

@ -0,0 +1,56 @@
"""
Structure module
"""
from typing import List, TYPE_CHECKING, Dict
from slither.core.variables.structure_variable import StructureVariable
from slither.solc_parsing.variables.structure_variable import StructureVariableSolc
from slither.core.declarations.structure import Structure
if TYPE_CHECKING:
from slither.solc_parsing.slitherSolc import SlitherSolc
class StructureTopLevelSolc: # pylint: disable=too-few-public-methods
"""
Structure class
"""
# elems = [(type, name)]
def __init__( # pylint: disable=too-many-arguments
self, st: Structure, struct: Dict, slither_parser: "SlitherSolc",
):
if slither_parser.is_compact_ast:
name = struct["name"]
attributes = struct
else:
name = struct["attributes"][slither_parser.get_key()]
attributes = struct["attributes"]
if "canonicalName" in attributes:
canonicalName = attributes["canonicalName"]
else:
canonicalName = name
children = struct["members"] if "members" in struct else struct.get("children", [])
self._structure = st
st.name = name
st.canonical_name = canonicalName
self._slither_parser = slither_parser
self._elemsNotParsed = children
def analyze(self):
for elem_to_parse in self._elemsNotParsed:
elem = StructureVariable()
elem.set_structure(self._structure)
elem.set_offset(elem_to_parse["src"], self._structure.contract.slither)
elem_parser = StructureVariableSolc(elem, elem_to_parse)
elem_parser.analyze(self._slither_parser)
self._structure.elems[elem.name] = elem
self._structure.add_elem_in_order(elem.name)
self._elemsNotParsed = []

@ -178,7 +178,7 @@ def find_variable( # pylint: disable=too-many-locals,too-many-statements
if var_name in structures:
return structures[var_name]
structures_top_level = contract.slither.top_level_structures
structures_top_level = contract.slither.structures_top_level
for st in structures_top_level:
if st.name == var_name:
return st
@ -191,7 +191,7 @@ def find_variable( # pylint: disable=too-many-locals,too-many-statements
if var_name in enums:
return enums[var_name]
enums_top_level = contract.slither.top_level_enums
enums_top_level = contract.slither.enums_top_level
for enum in enums_top_level:
if enum.name == var_name:
return enum

@ -5,6 +5,8 @@ import re
from typing import List, Dict
from slither.core.declarations import Contract
from slither.core.declarations.enum_top_level import EnumTopLevel
from slither.core.declarations.structure_top_level import StructureTopLevel
from slither.exceptions import SlitherException
from slither.solc_parsing.declarations.contract import ContractSolc
@ -13,6 +15,7 @@ from slither.core.slither_core import SlitherCore
from slither.core.declarations.pragma_directive import Pragma
from slither.core.declarations.import_directive import Import
from slither.analyses.data_dependency.data_dependency import compute_dependency
from slither.solc_parsing.declarations.structure_top_level import StructureTopLevelSolc
logging.basicConfig()
logger = logging.getLogger("SlitherSolcParsing")
@ -29,6 +32,7 @@ class SlitherSolc:
self._analyzed = False
self._underlying_contract_to_parser: Dict[Contract, ContractSolc] = dict()
self._structures_top_level_parser: List[StructureTopLevelSolc] = []
self._is_compact_ast = False
self._core: SlitherCore = core
@ -79,19 +83,19 @@ class SlitherSolc:
###################################################################################
###################################################################################
def parse_contracts_from_json(self, json_data: str) -> bool:
def parse_top_level_from_json(self, json_data: str) -> bool:
try:
data_loaded = json.loads(json_data)
# Truffle AST
if "ast" in data_loaded:
self.parse_contracts_from_loaded_json(data_loaded["ast"], data_loaded["sourcePath"])
self.parse_top_level_from_loaded_json(data_loaded["ast"], data_loaded["sourcePath"])
return True
# solc AST, where the non-json text was removed
if "attributes" in data_loaded:
filename = data_loaded["attributes"]["absolutePath"]
else:
filename = data_loaded["absolutePath"]
self.parse_contracts_from_loaded_json(data_loaded, filename)
self.parse_top_level_from_loaded_json(data_loaded, filename)
return True
except ValueError:
@ -102,11 +106,38 @@ class SlitherSolc:
json_data = json_data[first:last]
data_loaded = json.loads(json_data)
self.parse_contracts_from_loaded_json(data_loaded, filename)
self.parse_top_level_from_loaded_json(data_loaded, filename)
return True
return False
def parse_contracts_from_loaded_json(
def _parse_enum(self, top_level_data:Dict):
if self.is_compact_ast:
name = top_level_data["name"]
canonicalName = top_level_data["canonicalName"]
else:
name = top_level_data["attributes"][self.get_key()]
if "canonicalName" in top_level_data["attributes"]:
canonicalName = top_level_data["attributes"]["canonicalName"]
else:
canonicalName = name
values = []
children = (
top_level_data["members"]
if "members" in top_level_data
else top_level_data.get("children", [])
)
for child in children:
assert child[self.get_key()] == "EnumValue"
if self.is_compact_ast:
values.append(child["name"])
else:
values.append(child["attributes"][self.get_key()])
enum = EnumTopLevel(name, canonicalName, values)
enum.set_offset(top_level_data["src"], self._core)
self.core.enums_top_level.append(enum)
def parse_top_level_from_loaded_json(
self, data_loaded: Dict, filename: str
): # pylint: disable=too-many-branches
if "nodeType" in data_loaded:
@ -128,68 +159,48 @@ class SlitherSolc:
logger.error("solc version is not supported")
return
for contract_data in data_loaded[self.get_children()]:
assert contract_data[self.get_key()] in [
for top_level_data in data_loaded[self.get_children()]:
assert top_level_data[self.get_key()] in [
"ContractDefinition",
"PragmaDirective",
"ImportDirective",
"StructDefinition",
"EnumDefinition",
]
if contract_data[self.get_key()] == "ContractDefinition":
if top_level_data[self.get_key()] == "ContractDefinition":
contract = Contract()
contract_parser = ContractSolc(self, contract, contract_data)
if "src" in contract_data:
contract.set_offset(contract_data["src"], self._core)
contract_parser = ContractSolc(self, contract, top_level_data)
if "src" in top_level_data:
contract.set_offset(top_level_data["src"], self._core)
self._underlying_contract_to_parser[contract] = contract_parser
elif contract_data[self.get_key()] == "PragmaDirective":
elif top_level_data[self.get_key()] == "PragmaDirective":
if self._is_compact_ast:
pragma = Pragma(contract_data["literals"])
pragma = Pragma(top_level_data["literals"])
else:
pragma = Pragma(contract_data["attributes"]["literals"])
pragma.set_offset(contract_data["src"], self._core)
pragma = Pragma(top_level_data["attributes"]["literals"])
pragma.set_offset(top_level_data["src"], self._core)
self._core.pragma_directives.append(pragma)
elif contract_data[self.get_key()] == "ImportDirective":
elif top_level_data[self.get_key()] == "ImportDirective":
if self.is_compact_ast:
import_directive = Import(contract_data["absolutePath"])
import_directive = Import(top_level_data["absolutePath"])
else:
import_directive = Import(contract_data["attributes"].get("absolutePath", ""))
import_directive.set_offset(contract_data["src"], self._core)
import_directive = Import(top_level_data["attributes"].get("absolutePath", ""))
import_directive.set_offset(top_level_data["src"], self._core)
self._core.import_directives.append(import_directive)
elif contract_data[self.get_key()] in [
"StructDefinition",
"EnumDefinition",
]:
# This can only happen for top-level structure and enum
# They were introduced with 0.6.5
assert self._is_compact_ast # Do not support top level definition for legacy AST
fake_contract_data = {
"name": f"SlitherInternalTopLevelContract{self._top_level_contracts_counter}",
"id": -1000
+ self._top_level_contracts_counter, # TODO: determine if collission possible
"linearizedBaseContracts": [],
"fullyImplemented": True,
"contractKind": "SLitherInternal",
}
self._top_level_contracts_counter += 1
contract = Contract()
top_level_contract = ContractSolc(self, contract, fake_contract_data)
contract.is_top_level = True
contract.set_offset(contract_data["src"], self._core)
if contract_data[self.get_key()] == "StructDefinition":
top_level_contract.structures_not_parsed.append(
contract_data
) # Todo add proper setters
else:
top_level_contract.enums_not_parsed.append(
contract_data
) # Todo add proper setters
elif top_level_data[self.get_key()] == "StructDefinition":
st = StructureTopLevel()
st.set_offset(top_level_data["src"], self._core)
st_parser = StructureTopLevelSolc(st, top_level_data, self)
self._core.structures_top_level.append(st)
self._structures_top_level_parser.append(st_parser)
self._underlying_contract_to_parser[contract] = top_level_contract
elif top_level_data[self.get_key()] == "EnumDefinition":
# Note enum don't need a complex parser, so everything is directly done
self._parse_enum(top_level_data)
def _parse_source_unit(self, data: Dict, filename: str):
if data[self.get_key()] != "SourceUnit":

@ -73,6 +73,7 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t
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
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)
@ -84,6 +85,7 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t
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
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)
@ -175,8 +177,8 @@ def parse_type(t: Union[Dict, UnknownType], caller_context):
else:
key = "name"
structures = contract.structures + contract.slither.top_level_structures
enums = contract.enums + contract.slither.top_level_enums
structures = contract.structures + contract.slither.structures_top_level
enums = contract.enums + contract.slither.enums_top_level
contracts = contract.slither.contracts
if isinstance(t, UnknownType):

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -1,4 +1,3 @@
{
"C": {},
"SlitherInternalTopLevelContract0": {}
"C": {}
}

@ -558,7 +558,7 @@ def test_parsing(test_item: Item):
diff = DeepDiff(expected, actual, ignore_order=True, verbose_level=2, view="tree")
if diff:
for change in diff["values_changed"]:
for change in diff.get("values_changed", []):
path_list = re.findall(r"\['(.*?)'\]", change.path())
path = "_".join(path_list)
with open(f"test_artifacts/{id_test(test_item)}_{path}_expected.dot", "w") as f:

Loading…
Cancel
Save