crytic_compile.platform.standard

Standard crytic-compile export

  1"""
  2Standard crytic-compile export
  3"""
  4import json
  5import os
  6from collections import defaultdict
  7from pathlib import Path
  8from typing import TYPE_CHECKING, Dict, List, Tuple, Type, Any
  9
 10from crytic_compile.compilation_unit import CompilationUnit
 11from crytic_compile.compiler.compiler import CompilerVersion
 12from crytic_compile.platform import Type as PlatformType
 13from crytic_compile.platform.abstract_platform import AbstractPlatform
 14from crytic_compile.utils.naming import Filename
 15
 16# Cycle dependency
 17from crytic_compile.utils.natspec import Natspec
 18
 19if TYPE_CHECKING:
 20    from crytic_compile import CryticCompile
 21
 22
 23def export_to_standard(crytic_compile: "CryticCompile", **kwargs: str) -> List[str]:
 24    """Export the project to the standard crytic compile format
 25
 26    Args:
 27        crytic_compile (CryticCompile): CryticCompile object to export
 28        **kwargs: optional arguments. Used: "export_dir"
 29
 30    Returns:
 31        List[str]: List of files generated
 32    """
 33    # Obtain objects to represent each contract
 34
 35    output = generate_standard_export(crytic_compile)
 36
 37    export_dir = kwargs.get("export_dir", "crytic-export")
 38    if not os.path.exists(export_dir):
 39        os.makedirs(export_dir)
 40
 41    target = (
 42        "contracts"
 43        if os.path.isdir(crytic_compile.target)
 44        else Path(crytic_compile.target).parts[-1]
 45    )
 46
 47    path = os.path.join(export_dir, f"{target}.json")
 48    with open(path, "w", encoding="utf8") as file_desc:
 49        json.dump(output, file_desc)
 50
 51    return [path]
 52
 53
 54class Standard(AbstractPlatform):
 55    """
 56    Standard platform (crytic-compile specific)
 57    """
 58
 59    NAME = "Standard"
 60    PROJECT_URL = "https://github.com/crytic/crytic-compile"
 61    TYPE = PlatformType.STANDARD
 62
 63    HIDE = True
 64
 65    def __init__(self, target: str, **kwargs: str):
 66        """Init the Standard platform
 67
 68        Args:
 69            target (str): path to the target
 70            **kwargs: optional arguments. Not used
 71
 72        """
 73        super().__init__(str(target), **kwargs)
 74        self._underlying_platform: Type[AbstractPlatform] = Standard
 75        self._unit_tests: List[str] = []
 76
 77    def compile(self, crytic_compile: "CryticCompile", **_kwargs: str) -> None:
 78        """Compile the file (load the file for the Standard platform) and populates the CryticCompile object
 79
 80        Args:
 81            crytic_compile (CryticCompile): Associated CryticCompile
 82            **_kwargs: optional arguments. Not used
 83
 84        """
 85        # pylint: disable=import-outside-toplevel
 86        from crytic_compile.crytic_compile import get_platforms
 87
 88        with open(self._target, encoding="utf8") as file_desc:
 89            loaded_json = json.load(file_desc)
 90        (underlying_type, unit_tests) = load_from_compile(crytic_compile, loaded_json)
 91        underlying_type = PlatformType(underlying_type)
 92        platforms: List[Type[AbstractPlatform]] = get_platforms()
 93        platform = next((p for p in platforms if p.TYPE == underlying_type), Standard)
 94        self._underlying_platform = platform
 95        self._unit_tests = unit_tests
 96
 97    def clean(self, **_kwargs: str) -> None:
 98        """Clean compilation artifacts
 99
100        Args:
101            **_kwargs: unused.
102        """
103        return
104
105    @staticmethod
106    def is_supported(target: str, **kwargs: str) -> bool:
107        """Check if the target has the standard crytic-compile format
108
109        Args:
110            target (str): path to the target
111            **kwargs: optional arguments. Used: "standard_ignore"
112
113        Returns:
114            bool: True if the target is a crytic-compile generated project
115        """
116        standard_ignore = kwargs.get("standard_ignore", False)
117        if standard_ignore:
118            return False
119        if not Path(target).parts:
120            return False
121        return Path(target).parts[-1].endswith("_export.json")
122
123    def is_dependency(self, path: str) -> bool:
124        """Check if the target is a dependency
125        This function always return false, the deps are handled by crytic_compile_dependencies
126
127        Args:
128            path (str): path to the target
129
130        Returns:
131            bool: Always False
132        """
133        # handled by crytic_compile_dependencies
134        return False
135
136    def _guessed_tests(self) -> List[str]:
137        """Guess the potential unit tests commands
138
139        Returns:
140            List[str]: list of potential unit tests commands
141        """
142        return self._unit_tests
143
144    @property
145    def platform_name_used(self) -> str:
146        """Return the name of the underlying platform used
147
148        Returns:
149            str: The name of the underlying platform used
150        """
151        return self._underlying_platform.NAME
152
153    @property
154    def platform_project_url_used(self) -> str:
155        """Return the underlying platform project 's url
156
157        Returns:
158            str: Underlying platform project 's url
159        """
160        return self._underlying_platform.PROJECT_URL
161
162    @property
163    def platform_type_used(self) -> PlatformType:
164        """Return the type of the underlying platform used
165
166        Returns:
167            PlatformType: Type of the underlying platform
168        """
169        return self._underlying_platform.TYPE
170
171
172def _convert_filename_to_dict(filename: Filename) -> Dict:
173    """Convert the filename to a dict containing the four filename fields
174
175    Args:
176        filename (Filename): Filename to convert
177
178    Returns:
179        Dict: Dict with the four filenames fields
180    """
181    return {
182        "absolute": filename.absolute,
183        "used": filename.used,
184        "short": filename.short,
185        "relative": filename.relative,
186    }
187
188
189def _convert_dict_to_filename(filename: Dict) -> Filename:
190    """Convert a dict to a Filename
191    This function should be called only on well formed json
192
193    Args:
194        filename (Dict): Json to convert
195
196    Returns:
197        Filename: Filename converted
198    """
199
200    assert "absolute" in filename
201    assert "used" in filename
202    assert "short" in filename
203    assert "relative" in filename
204
205    return Filename(
206        absolute=filename["absolute"],
207        relative=filename["relative"],
208        short=filename["short"],
209        used=filename["used"],
210    )
211
212
213def generate_standard_export(crytic_compile: "CryticCompile") -> Dict:
214    """Convert the CryticCompile object to a json
215
216    Args:
217        crytic_compile (CryticCompile): CryticCompile object to export
218
219    Returns:
220        Dict: CryticCompile converted to a json
221    """
222
223    compilation_units = {}
224    libraries_to_update = crytic_compile.libraries
225    for key, compilation_unit in crytic_compile.compilation_units.items():
226        source_unit_dict: Dict[str, Dict[str, Dict[str, Any]]] = {}
227
228        for filename, source_unit in compilation_unit.source_units.items():
229            source_unit_dict[filename.relative] = defaultdict(dict)
230            source_unit_dict[filename.relative]["ast"] = source_unit.ast
231            for contract_name in source_unit.contracts_names:
232                libraries = source_unit.libraries_names_and_patterns(contract_name)
233                source_unit_dict[filename.relative]["contracts"][contract_name] = {
234                    "abi": source_unit.abi(contract_name),
235                    "bin": source_unit.bytecode_init(contract_name, libraries_to_update),
236                    "bin-runtime": source_unit.bytecode_runtime(contract_name, libraries_to_update),
237                    "srcmap": ";".join(source_unit.srcmap_init(contract_name)),
238                    "srcmap-runtime": ";".join(source_unit.srcmap_runtime(contract_name)),
239                    "filenames": _convert_filename_to_dict(filename),
240                    "libraries": dict(libraries) if libraries else {},
241                    "is_dependency": crytic_compile.is_dependency(filename.absolute),
242                    "userdoc": source_unit.natspec[contract_name].userdoc.export(),
243                    "devdoc": source_unit.natspec[contract_name].devdoc.export(),
244                }
245
246        # Create our root object to contain the contracts and other information.
247
248        compiler: Dict = {}
249        if compilation_unit.compiler_version:
250            compiler = {
251                "compiler": compilation_unit.compiler_version.compiler,
252                "version": compilation_unit.compiler_version.version,
253                "optimized": compilation_unit.compiler_version.optimized,
254            }
255
256        compilation_units[key] = {
257            "compiler": compiler,
258            "source_units": source_unit_dict,
259            "filenames": [
260                _convert_filename_to_dict(filename) for filename in compilation_unit.filenames
261            ],
262        }
263
264    output = {
265        "compilation_units": compilation_units,
266        "package": crytic_compile.package,
267        "working_dir": str(crytic_compile.working_dir),
268        "type": int(crytic_compile.platform.platform_type_used),
269        "unit_tests": crytic_compile.platform.guessed_tests(),
270        "crytic_version": "0.0.2",
271    }
272    return output
273
274
275def _load_from_compile_legacy1(crytic_compile: "CryticCompile", loaded_json: Dict) -> None:
276    """Load from old (old) export
277
278    Args:
279        crytic_compile (CryticCompile): CryticCompile object to populate
280        loaded_json (Dict): Json representation of the CryticCompile object
281    """
282    compilation_unit = CompilationUnit(crytic_compile, "legacy")
283    compilation_unit.compiler_version = CompilerVersion(
284        compiler=loaded_json["compiler"]["compiler"],
285        version=loaded_json["compiler"]["version"],
286        optimized=loaded_json["compiler"]["optimized"],
287    )
288
289    if "filenames" in loaded_json:
290        compilation_unit.filenames = [
291            _convert_dict_to_filename(filename) for filename in loaded_json["filenames"]
292        ]
293
294    for path, ast in loaded_json["asts"].items():
295        # The following might create lookup issue?
296        filename = crytic_compile.filename_lookup(path)
297        source_unit = compilation_unit.create_source_unit(filename)
298        source_unit.ast = ast
299
300    for contract_name, contract in loaded_json["contracts"].items():
301        filename = _convert_dict_to_filename(contract["filenames"])
302        compilation_unit.filename_to_contracts[filename].add(contract_name)
303        source_unit = compilation_unit.create_source_unit(filename)
304
305        source_unit.add_contract_name(contract_name)
306        source_unit.abis[contract_name] = contract["abi"]
307        source_unit.bytecodes_init[contract_name] = contract["bin"]
308        source_unit.bytecodes_runtime[contract_name] = contract["bin-runtime"]
309        source_unit.srcmaps_init[contract_name] = contract["srcmap"].split(";")
310        source_unit.srcmaps_runtime[contract_name] = contract["srcmap-runtime"].split(";")
311        source_unit.libraries[contract_name] = contract["libraries"]
312
313        userdoc = contract.get("userdoc", {})
314        devdoc = contract.get("devdoc", {})
315        source_unit.natspec[contract_name] = Natspec(userdoc, devdoc)
316
317        if contract["is_dependency"]:
318            compilation_unit.crytic_compile.dependencies.add(filename.absolute)
319            compilation_unit.crytic_compile.dependencies.add(filename.relative)
320            compilation_unit.crytic_compile.dependencies.add(filename.short)
321            compilation_unit.crytic_compile.dependencies.add(filename.used)
322
323
324def _load_from_compile_legacy2(crytic_compile: "CryticCompile", loaded_json: Dict) -> None:
325    """Load from old (old) export
326
327    Args:
328        crytic_compile (CryticCompile): CryticCompile object to populate
329        loaded_json (Dict): Json representation of the CryticCompile object
330    """
331
332    for key, compilation_unit_json in loaded_json["compilation_units"].items():
333        compilation_unit = CompilationUnit(crytic_compile, key)
334        compilation_unit.compiler_version = CompilerVersion(
335            compiler=compilation_unit_json["compiler"]["compiler"],
336            version=compilation_unit_json["compiler"]["version"],
337            optimized=compilation_unit_json["compiler"]["optimized"],
338        )
339
340        if "filenames" in compilation_unit_json:
341            compilation_unit.filenames = [
342                _convert_dict_to_filename(filename)
343                for filename in compilation_unit_json["filenames"]
344            ]
345
346        for path, ast in loaded_json["asts"].items():
347            # The following might create lookup issue?
348            filename = crytic_compile.filename_lookup(path)
349            source_unit = compilation_unit.create_source_unit(filename)
350            source_unit.ast = ast
351
352        for contract_name, contract in compilation_unit_json["contracts"].items():
353
354            filename = Filename(
355                absolute=contract["filenames"]["absolute"],
356                relative=contract["filenames"]["relative"],
357                short=contract["filenames"]["short"],
358                used=contract["filenames"]["used"],
359            )
360            compilation_unit.filename_to_contracts[filename].add(contract_name)
361
362            source_unit = compilation_unit.create_source_unit(filename)
363            source_unit.add_contract_name(contract_name)
364            source_unit.abis[contract_name] = contract["abi"]
365            source_unit.bytecodes_init[contract_name] = contract["bin"]
366            source_unit.bytecodes_runtime[contract_name] = contract["bin-runtime"]
367            source_unit.srcmaps_init[contract_name] = contract["srcmap"].split(";")
368            source_unit.srcmaps_runtime[contract_name] = contract["srcmap-runtime"].split(";")
369            source_unit.libraries[contract_name] = contract["libraries"]
370
371            userdoc = contract.get("userdoc", {})
372            devdoc = contract.get("devdoc", {})
373            source_unit.natspec[contract_name] = Natspec(userdoc, devdoc)
374
375            if contract["is_dependency"]:
376                crytic_compile.dependencies.add(filename.absolute)
377                crytic_compile.dependencies.add(filename.relative)
378                crytic_compile.dependencies.add(filename.short)
379                crytic_compile.dependencies.add(filename.used)
380
381
382def _load_from_compile_0_0_1(crytic_compile: "CryticCompile", loaded_json: Dict) -> None:
383    for key, compilation_unit_json in loaded_json["compilation_units"].items():
384        compilation_unit = CompilationUnit(crytic_compile, key)
385        compilation_unit.compiler_version = CompilerVersion(
386            compiler=compilation_unit_json["compiler"]["compiler"],
387            version=compilation_unit_json["compiler"]["version"],
388            optimized=compilation_unit_json["compiler"]["optimized"],
389        )
390
391        compilation_unit.filenames = [
392            _convert_dict_to_filename(filename) for filename in compilation_unit_json["filenames"]
393        ]
394
395        for path, ast in compilation_unit_json["asts"].items():
396            # The following might create lookup issue?
397            filename = crytic_compile.filename_lookup(path)
398            source_unit = compilation_unit.create_source_unit(filename)
399            source_unit.ast = ast
400
401        for contracts_data in compilation_unit_json["contracts"].values():
402            for contract_name, contract in contracts_data.items():
403
404                filename = Filename(
405                    absolute=contract["filenames"]["absolute"],
406                    relative=contract["filenames"]["relative"],
407                    short=contract["filenames"]["short"],
408                    used=contract["filenames"]["used"],
409                )
410                compilation_unit.filename_to_contracts[filename].add(contract_name)
411                source_unit = compilation_unit.create_source_unit(filename)
412                source_unit.add_contract_name(contract_name)
413                source_unit.abis[contract_name] = contract["abi"]
414                source_unit.bytecodes_init[contract_name] = contract["bin"]
415                source_unit.bytecodes_runtime[contract_name] = contract["bin-runtime"]
416                source_unit.srcmaps_init[contract_name] = contract["srcmap"].split(";")
417                source_unit.srcmaps_runtime[contract_name] = contract["srcmap-runtime"].split(";")
418                source_unit.libraries[contract_name] = contract["libraries"]
419
420                userdoc = contract.get("userdoc", {})
421                devdoc = contract.get("devdoc", {})
422                source_unit.natspec[contract_name] = Natspec(userdoc, devdoc)
423
424                if contract["is_dependency"]:
425                    crytic_compile.dependencies.add(filename.absolute)
426                    crytic_compile.dependencies.add(filename.relative)
427                    crytic_compile.dependencies.add(filename.short)
428                    crytic_compile.dependencies.add(filename.used)
429
430
431def _load_from_compile_current(crytic_compile: "CryticCompile", loaded_json: Dict) -> None:
432    for key, compilation_unit_json in loaded_json["compilation_units"].items():
433        compilation_unit = CompilationUnit(crytic_compile, key)
434        compilation_unit.compiler_version = CompilerVersion(
435            compiler=compilation_unit_json["compiler"]["compiler"],
436            version=compilation_unit_json["compiler"]["version"],
437            optimized=compilation_unit_json["compiler"]["optimized"],
438        )
439
440        compilation_unit.filenames = [
441            _convert_dict_to_filename(filename) for filename in compilation_unit_json["filenames"]
442        ]
443
444        for filename_str, source_unit_data in compilation_unit_json["source_units"].items():
445            filename = compilation_unit.filename_lookup(filename_str)
446            source_unit = compilation_unit.create_source_unit(filename)
447
448            for contract_name, contract in source_unit_data.get("contracts", {}).items():
449                compilation_unit.filename_to_contracts[filename].add(contract_name)
450
451                source_unit = compilation_unit.create_source_unit(filename)
452                source_unit.add_contract_name(contract_name)
453                source_unit.abis[contract_name] = contract["abi"]
454                source_unit.bytecodes_init[contract_name] = contract["bin"]
455                source_unit.bytecodes_runtime[contract_name] = contract["bin-runtime"]
456                source_unit.srcmaps_init[contract_name] = contract["srcmap"].split(";")
457                source_unit.srcmaps_runtime[contract_name] = contract["srcmap-runtime"].split(";")
458                source_unit.libraries[contract_name] = contract["libraries"]
459
460                userdoc = contract.get("userdoc", {})
461                devdoc = contract.get("devdoc", {})
462                source_unit.natspec[contract_name] = Natspec(userdoc, devdoc)
463
464                if contract["is_dependency"]:
465                    crytic_compile.dependencies.add(filename.absolute)
466                    crytic_compile.dependencies.add(filename.relative)
467                    crytic_compile.dependencies.add(filename.short)
468                    crytic_compile.dependencies.add(filename.used)
469
470            source_unit.ast = source_unit_data["ast"]
471
472
473def load_from_compile(crytic_compile: "CryticCompile", loaded_json: Dict) -> Tuple[int, List[str]]:
474    """Load from a standard crytic compile json
475    This function must be called on well-formed json
476
477    Args:
478        crytic_compile (CryticCompile): CryticCompile object to populate
479        loaded_json (Dict): Json to load
480
481    Returns:
482        Tuple[int, List[str]]: (underlying platform types, guessed unit tests)
483    """
484    crytic_compile.package_name = loaded_json.get("package", None)
485    if "compilation_units" not in loaded_json:
486        _load_from_compile_legacy1(crytic_compile, loaded_json)
487
488    elif "crytic_version" not in loaded_json:
489        _load_from_compile_legacy2(crytic_compile, loaded_json)
490
491    elif loaded_json["crytic_version"] == "0.0.1":
492        _load_from_compile_0_0_1(crytic_compile, loaded_json)
493    else:
494        _load_from_compile_current(crytic_compile, loaded_json)
495
496    crytic_compile.working_dir = loaded_json["working_dir"]
497
498    return loaded_json["type"], loaded_json.get("unit_tests", [])
def export_to_standard( crytic_compile: crytic_compile.crytic_compile.CryticCompile, **kwargs: str) -> List[str]:
24def export_to_standard(crytic_compile: "CryticCompile", **kwargs: str) -> List[str]:
25    """Export the project to the standard crytic compile format
26
27    Args:
28        crytic_compile (CryticCompile): CryticCompile object to export
29        **kwargs: optional arguments. Used: "export_dir"
30
31    Returns:
32        List[str]: List of files generated
33    """
34    # Obtain objects to represent each contract
35
36    output = generate_standard_export(crytic_compile)
37
38    export_dir = kwargs.get("export_dir", "crytic-export")
39    if not os.path.exists(export_dir):
40        os.makedirs(export_dir)
41
42    target = (
43        "contracts"
44        if os.path.isdir(crytic_compile.target)
45        else Path(crytic_compile.target).parts[-1]
46    )
47
48    path = os.path.join(export_dir, f"{target}.json")
49    with open(path, "w", encoding="utf8") as file_desc:
50        json.dump(output, file_desc)
51
52    return [path]

Export the project to the standard crytic compile format

Args: crytic_compile (CryticCompile): CryticCompile object to export **kwargs: optional arguments. Used: "export_dir"

Returns: List[str]: List of files generated

 55class Standard(AbstractPlatform):
 56    """
 57    Standard platform (crytic-compile specific)
 58    """
 59
 60    NAME = "Standard"
 61    PROJECT_URL = "https://github.com/crytic/crytic-compile"
 62    TYPE = PlatformType.STANDARD
 63
 64    HIDE = True
 65
 66    def __init__(self, target: str, **kwargs: str):
 67        """Init the Standard platform
 68
 69        Args:
 70            target (str): path to the target
 71            **kwargs: optional arguments. Not used
 72
 73        """
 74        super().__init__(str(target), **kwargs)
 75        self._underlying_platform: Type[AbstractPlatform] = Standard
 76        self._unit_tests: List[str] = []
 77
 78    def compile(self, crytic_compile: "CryticCompile", **_kwargs: str) -> None:
 79        """Compile the file (load the file for the Standard platform) and populates the CryticCompile object
 80
 81        Args:
 82            crytic_compile (CryticCompile): Associated CryticCompile
 83            **_kwargs: optional arguments. Not used
 84
 85        """
 86        # pylint: disable=import-outside-toplevel
 87        from crytic_compile.crytic_compile import get_platforms
 88
 89        with open(self._target, encoding="utf8") as file_desc:
 90            loaded_json = json.load(file_desc)
 91        (underlying_type, unit_tests) = load_from_compile(crytic_compile, loaded_json)
 92        underlying_type = PlatformType(underlying_type)
 93        platforms: List[Type[AbstractPlatform]] = get_platforms()
 94        platform = next((p for p in platforms if p.TYPE == underlying_type), Standard)
 95        self._underlying_platform = platform
 96        self._unit_tests = unit_tests
 97
 98    def clean(self, **_kwargs: str) -> None:
 99        """Clean compilation artifacts
100
101        Args:
102            **_kwargs: unused.
103        """
104        return
105
106    @staticmethod
107    def is_supported(target: str, **kwargs: str) -> bool:
108        """Check if the target has the standard crytic-compile format
109
110        Args:
111            target (str): path to the target
112            **kwargs: optional arguments. Used: "standard_ignore"
113
114        Returns:
115            bool: True if the target is a crytic-compile generated project
116        """
117        standard_ignore = kwargs.get("standard_ignore", False)
118        if standard_ignore:
119            return False
120        if not Path(target).parts:
121            return False
122        return Path(target).parts[-1].endswith("_export.json")
123
124    def is_dependency(self, path: str) -> bool:
125        """Check if the target is a dependency
126        This function always return false, the deps are handled by crytic_compile_dependencies
127
128        Args:
129            path (str): path to the target
130
131        Returns:
132            bool: Always False
133        """
134        # handled by crytic_compile_dependencies
135        return False
136
137    def _guessed_tests(self) -> List[str]:
138        """Guess the potential unit tests commands
139
140        Returns:
141            List[str]: list of potential unit tests commands
142        """
143        return self._unit_tests
144
145    @property
146    def platform_name_used(self) -> str:
147        """Return the name of the underlying platform used
148
149        Returns:
150            str: The name of the underlying platform used
151        """
152        return self._underlying_platform.NAME
153
154    @property
155    def platform_project_url_used(self) -> str:
156        """Return the underlying platform project 's url
157
158        Returns:
159            str: Underlying platform project 's url
160        """
161        return self._underlying_platform.PROJECT_URL
162
163    @property
164    def platform_type_used(self) -> PlatformType:
165        """Return the type of the underlying platform used
166
167        Returns:
168            PlatformType: Type of the underlying platform
169        """
170        return self._underlying_platform.TYPE

Standard platform (crytic-compile specific)

Standard(target: str, **kwargs: str)
66    def __init__(self, target: str, **kwargs: str):
67        """Init the Standard platform
68
69        Args:
70            target (str): path to the target
71            **kwargs: optional arguments. Not used
72
73        """
74        super().__init__(str(target), **kwargs)
75        self._underlying_platform: Type[AbstractPlatform] = Standard
76        self._unit_tests: List[str] = []

Init the Standard platform

Args: target (str): path to the target **kwargs: optional arguments. Not used

NAME: str = 'Standard'
PROJECT_URL: str = 'https://github.com/crytic/crytic-compile'
TYPE: crytic_compile.platform.types.Type = <Type.STANDARD: 100>
HIDE = True
def compile( self, crytic_compile: crytic_compile.crytic_compile.CryticCompile, **_kwargs: str) -> None:
78    def compile(self, crytic_compile: "CryticCompile", **_kwargs: str) -> None:
79        """Compile the file (load the file for the Standard platform) and populates the CryticCompile object
80
81        Args:
82            crytic_compile (CryticCompile): Associated CryticCompile
83            **_kwargs: optional arguments. Not used
84
85        """
86        # pylint: disable=import-outside-toplevel
87        from crytic_compile.crytic_compile import get_platforms
88
89        with open(self._target, encoding="utf8") as file_desc:
90            loaded_json = json.load(file_desc)
91        (underlying_type, unit_tests) = load_from_compile(crytic_compile, loaded_json)
92        underlying_type = PlatformType(underlying_type)
93        platforms: List[Type[AbstractPlatform]] = get_platforms()
94        platform = next((p for p in platforms if p.TYPE == underlying_type), Standard)
95        self._underlying_platform = platform
96        self._unit_tests = unit_tests

Compile the file (load the file for the Standard platform) and populates the CryticCompile object

Args: crytic_compile (CryticCompile): Associated CryticCompile **_kwargs: optional arguments. Not used

def clean(self, **_kwargs: str) -> None:
 98    def clean(self, **_kwargs: str) -> None:
 99        """Clean compilation artifacts
100
101        Args:
102            **_kwargs: unused.
103        """
104        return

Clean compilation artifacts

Args: **_kwargs: unused.

@staticmethod
def is_supported(target: str, **kwargs: str) -> bool:
106    @staticmethod
107    def is_supported(target: str, **kwargs: str) -> bool:
108        """Check if the target has the standard crytic-compile format
109
110        Args:
111            target (str): path to the target
112            **kwargs: optional arguments. Used: "standard_ignore"
113
114        Returns:
115            bool: True if the target is a crytic-compile generated project
116        """
117        standard_ignore = kwargs.get("standard_ignore", False)
118        if standard_ignore:
119            return False
120        if not Path(target).parts:
121            return False
122        return Path(target).parts[-1].endswith("_export.json")

Check if the target has the standard crytic-compile format

Args: target (str): path to the target **kwargs: optional arguments. Used: "standard_ignore"

Returns: bool: True if the target is a crytic-compile generated project

def is_dependency(self, path: str) -> bool:
124    def is_dependency(self, path: str) -> bool:
125        """Check if the target is a dependency
126        This function always return false, the deps are handled by crytic_compile_dependencies
127
128        Args:
129            path (str): path to the target
130
131        Returns:
132            bool: Always False
133        """
134        # handled by crytic_compile_dependencies
135        return False

Check if the target is a dependency This function always return false, the deps are handled by crytic_compile_dependencies

Args: path (str): path to the target

Returns: bool: Always False

platform_name_used: str
145    @property
146    def platform_name_used(self) -> str:
147        """Return the name of the underlying platform used
148
149        Returns:
150            str: The name of the underlying platform used
151        """
152        return self._underlying_platform.NAME

Return the name of the underlying platform used

Returns: str: The name of the underlying platform used

platform_project_url_used: str
154    @property
155    def platform_project_url_used(self) -> str:
156        """Return the underlying platform project 's url
157
158        Returns:
159            str: Underlying platform project 's url
160        """
161        return self._underlying_platform.PROJECT_URL

Return the underlying platform project 's url

Returns: str: Underlying platform project 's url

platform_type_used: crytic_compile.platform.types.Type
163    @property
164    def platform_type_used(self) -> PlatformType:
165        """Return the type of the underlying platform used
166
167        Returns:
168            PlatformType: Type of the underlying platform
169        """
170        return self._underlying_platform.TYPE

Return the type of the underlying platform used

Returns: PlatformType: Type of the underlying platform

def generate_standard_export(crytic_compile: crytic_compile.crytic_compile.CryticCompile) -> Dict:
214def generate_standard_export(crytic_compile: "CryticCompile") -> Dict:
215    """Convert the CryticCompile object to a json
216
217    Args:
218        crytic_compile (CryticCompile): CryticCompile object to export
219
220    Returns:
221        Dict: CryticCompile converted to a json
222    """
223
224    compilation_units = {}
225    libraries_to_update = crytic_compile.libraries
226    for key, compilation_unit in crytic_compile.compilation_units.items():
227        source_unit_dict: Dict[str, Dict[str, Dict[str, Any]]] = {}
228
229        for filename, source_unit in compilation_unit.source_units.items():
230            source_unit_dict[filename.relative] = defaultdict(dict)
231            source_unit_dict[filename.relative]["ast"] = source_unit.ast
232            for contract_name in source_unit.contracts_names:
233                libraries = source_unit.libraries_names_and_patterns(contract_name)
234                source_unit_dict[filename.relative]["contracts"][contract_name] = {
235                    "abi": source_unit.abi(contract_name),
236                    "bin": source_unit.bytecode_init(contract_name, libraries_to_update),
237                    "bin-runtime": source_unit.bytecode_runtime(contract_name, libraries_to_update),
238                    "srcmap": ";".join(source_unit.srcmap_init(contract_name)),
239                    "srcmap-runtime": ";".join(source_unit.srcmap_runtime(contract_name)),
240                    "filenames": _convert_filename_to_dict(filename),
241                    "libraries": dict(libraries) if libraries else {},
242                    "is_dependency": crytic_compile.is_dependency(filename.absolute),
243                    "userdoc": source_unit.natspec[contract_name].userdoc.export(),
244                    "devdoc": source_unit.natspec[contract_name].devdoc.export(),
245                }
246
247        # Create our root object to contain the contracts and other information.
248
249        compiler: Dict = {}
250        if compilation_unit.compiler_version:
251            compiler = {
252                "compiler": compilation_unit.compiler_version.compiler,
253                "version": compilation_unit.compiler_version.version,
254                "optimized": compilation_unit.compiler_version.optimized,
255            }
256
257        compilation_units[key] = {
258            "compiler": compiler,
259            "source_units": source_unit_dict,
260            "filenames": [
261                _convert_filename_to_dict(filename) for filename in compilation_unit.filenames
262            ],
263        }
264
265    output = {
266        "compilation_units": compilation_units,
267        "package": crytic_compile.package,
268        "working_dir": str(crytic_compile.working_dir),
269        "type": int(crytic_compile.platform.platform_type_used),
270        "unit_tests": crytic_compile.platform.guessed_tests(),
271        "crytic_version": "0.0.2",
272    }
273    return output

Convert the CryticCompile object to a json

Args: crytic_compile (CryticCompile): CryticCompile object to export

Returns: Dict: CryticCompile converted to a json

def load_from_compile( crytic_compile: crytic_compile.crytic_compile.CryticCompile, loaded_json: Dict) -> Tuple[int, List[str]]:
474def load_from_compile(crytic_compile: "CryticCompile", loaded_json: Dict) -> Tuple[int, List[str]]:
475    """Load from a standard crytic compile json
476    This function must be called on well-formed json
477
478    Args:
479        crytic_compile (CryticCompile): CryticCompile object to populate
480        loaded_json (Dict): Json to load
481
482    Returns:
483        Tuple[int, List[str]]: (underlying platform types, guessed unit tests)
484    """
485    crytic_compile.package_name = loaded_json.get("package", None)
486    if "compilation_units" not in loaded_json:
487        _load_from_compile_legacy1(crytic_compile, loaded_json)
488
489    elif "crytic_version" not in loaded_json:
490        _load_from_compile_legacy2(crytic_compile, loaded_json)
491
492    elif loaded_json["crytic_version"] == "0.0.1":
493        _load_from_compile_0_0_1(crytic_compile, loaded_json)
494    else:
495        _load_from_compile_current(crytic_compile, loaded_json)
496
497    crytic_compile.working_dir = loaded_json["working_dir"]
498
499    return loaded_json["type"], loaded_json.get("unit_tests", [])

Load from a standard crytic compile json This function must be called on well-formed json

Args: crytic_compile (CryticCompile): CryticCompile object to populate loaded_json (Dict): Json to load

Returns: Tuple[int, List[str]]: (underlying platform types, guessed unit tests)