def _handle_bytecode(crytic_compile: "CryticCompile", target: str, result_b: bytes): # There is no direct API to get the bytecode from etherscan # The page changes from time to time, we use for now a simple parsing, it will not be robust begin = """Search Algorithm">\nSimilar Contracts</button>\n""" begin += """<div id="dividcode">\n<pre class=\'wordwrap\' style=\'height: 15pc;\'>0x""" result = result_b.decode("utf8") # Removing everything before the begin string result = result[result.find(begin) + len(begin):] bytecode = result[:result.find("<")] contract_name = f"Contract_{target}" contract_filename = Filename(absolute="", relative="", short="", used="") crytic_compile.contracts_names.add(contract_name) crytic_compile.contracts_filenames[contract_name] = contract_filename crytic_compile.abis[contract_name] = {} crytic_compile.bytecodes_init[contract_name] = bytecode crytic_compile.bytecodes_runtime[contract_name] = "" crytic_compile.srcmaps_init[contract_name] = [] crytic_compile.srcmaps_runtime[contract_name] = [] crytic_compile.compiler_version = CompilerVersion(compiler="unknown", version="", optimized=None) crytic_compile.bytecode_only = True
def load_from_compile(crytic_compile, loaded_json): crytic_compile._asts = loaded_json['asts'] crytic_compile._compiler_version = CompilerVersion( compiler=loaded_json['compiler']['compiler'], version=loaded_json['compiler']['version'], optimized=loaded_json['compiler']['optimized']) for contract_name, contract in loaded_json['contracts'].items(): crytic_compile._contracts_name.add(contract_name) filename = Filename(absolute=contract['filenames']['absolute'], relative=contract['filenames']['relative'], short=contract['filenames']['short'], used=contract['filenames']['used']) crytic_compile._contracts_filenames[contract_name] = filename crytic_compile._abis[contract_name] = contract['abi'] crytic_compile._init_bytecodes[contract_name] = contract['bin'] crytic_compile._runtime_bytecodes[contract_name] = contract[ 'bin-runtime'] crytic_compile._srcmaps[contract_name] = contract['srcmap'].split(';') crytic_compile._srcmaps_runtime[contract_name] = contract[ 'srcmap-runtime'].split(';') crytic_compile._libraries[contract_name] = contract['libraries'] if contract['is_dependency']: crytic_compile._dependencies.add(filename.absolute) crytic_compile._dependencies.add(filename.relative) crytic_compile._dependencies.add(filename.short) crytic_compile._dependencies.add(filename.used) # Set our filenames crytic_compile._filenames = set( crytic_compile._contracts_filenames.values()) crytic_compile._working_dir = loaded_json['working_dir'] crytic_compile._type = loaded_json['type']
def _load_from_compile_legacy2(crytic_compile: "CryticCompile", loaded_json: Dict) -> None: """Load from old (old) export Args: crytic_compile (CryticCompile): CryticCompile object to populate loaded_json (Dict): Json representation of the CryticCompile object """ for key, compilation_unit_json in loaded_json["compilation_units"].items(): compilation_unit = CompilationUnit(crytic_compile, key) compilation_unit.compiler_version = CompilerVersion( compiler=compilation_unit_json["compiler"]["compiler"], version=compilation_unit_json["compiler"]["version"], optimized=compilation_unit_json["compiler"]["optimized"], ) for contract_name, contract in compilation_unit_json["contracts"].items(): compilation_unit.contracts_names.add(contract_name) filename = Filename( absolute=contract["filenames"]["absolute"], relative=contract["filenames"]["relative"], short=contract["filenames"]["short"], used=contract["filenames"]["used"], ) compilation_unit.filename_to_contracts[filename].add(contract_name) compilation_unit.abis[contract_name] = contract["abi"] compilation_unit.bytecodes_init[contract_name] = contract["bin"] compilation_unit.bytecodes_runtime[contract_name] = contract["bin-runtime"] compilation_unit.srcmaps_init[contract_name] = contract["srcmap"].split(";") compilation_unit.srcmaps_runtime[contract_name] = contract["srcmap-runtime"].split(";") compilation_unit.libraries[contract_name] = contract["libraries"] userdoc = contract.get("userdoc", {}) devdoc = contract.get("devdoc", {}) compilation_unit.natspec[contract_name] = Natspec(userdoc, devdoc) if contract["is_dependency"]: crytic_compile.dependencies.add(filename.absolute) crytic_compile.dependencies.add(filename.relative) crytic_compile.dependencies.add(filename.short) crytic_compile.dependencies.add(filename.used) compilation_unit.asts = compilation_unit_json["asts"] if "filenames" in compilation_unit_json: compilation_unit.filenames = { _convert_dict_to_filename(filename) for filename in compilation_unit_json["filenames"] } else: # For legay code, we recover the filenames from the contracts list # This is not perfect, as a filename might not be associated to any contract for contract_name, contract in compilation_unit_json["contracts"].items(): filename = _convert_dict_to_filename(contract["filenames"]) compilation_unit.filenames.add(filename)
def load_from_compile(crytic_compile: "CryticCompile", loaded_json: Dict) -> Tuple[int, List[str]]: """ Load from json :param crytic_compile: :param loaded_json: :return: """ crytic_compile.package_name = loaded_json.get("package", None) crytic_compile.asts = loaded_json["asts"] crytic_compile.compiler_version = CompilerVersion( compiler=loaded_json["compiler"]["compiler"], version=loaded_json["compiler"]["version"], optimized=loaded_json["compiler"]["optimized"], ) for contract_name, contract in loaded_json["contracts"].items(): crytic_compile.contracts_names.add(contract_name) filename = Filename( absolute=contract["filenames"]["absolute"], relative=contract["filenames"]["relative"], short=contract["filenames"]["short"], used=contract["filenames"]["used"], ) crytic_compile.contracts_filenames[contract_name] = filename crytic_compile.abis[contract_name] = contract["abi"] crytic_compile.bytecodes_init[contract_name] = contract["bin"] crytic_compile.bytecodes_runtime[contract_name] = contract[ "bin-runtime"] crytic_compile.srcmaps_init[contract_name] = contract["srcmap"].split( ";") crytic_compile.srcmaps_runtime[contract_name] = contract[ "srcmap-runtime"].split(";") crytic_compile.libraries[contract_name] = contract["libraries"] userdoc = contract.get("userdoc", {}) devdoc = contract.get("devdoc", {}) crytic_compile.natspec[contract_name] = Natspec(userdoc, devdoc) if contract["is_dependency"]: crytic_compile.dependencies.add(filename.absolute) crytic_compile.dependencies.add(filename.relative) crytic_compile.dependencies.add(filename.short) crytic_compile.dependencies.add(filename.used) # Set our filenames crytic_compile.filenames = set(crytic_compile.contracts_filenames.values()) crytic_compile.working_dir = loaded_json["working_dir"] return loaded_json["type"], loaded_json.get("unit_tests", [])
def _load_from_compile_current(crytic_compile: "CryticCompile", loaded_json: Dict) -> None: for key, compilation_unit_json in loaded_json["compilation_units"].items(): compilation_unit = CompilationUnit(crytic_compile, key) compilation_unit.compiler_version = CompilerVersion( compiler=compilation_unit_json["compiler"]["compiler"], version=compilation_unit_json["compiler"]["version"], optimized=compilation_unit_json["compiler"]["optimized"], ) for contracts_data in compilation_unit_json["contracts"].values(): for contract_name, contract in contracts_data.items(): compilation_unit.contracts_names.add(contract_name) filename = Filename( absolute=contract["filenames"]["absolute"], relative=contract["filenames"]["relative"], short=contract["filenames"]["short"], used=contract["filenames"]["used"], ) compilation_unit.filename_to_contracts[filename].add(contract_name) compilation_unit.abis[contract_name] = contract["abi"] compilation_unit.bytecodes_init[contract_name] = contract["bin"] compilation_unit.bytecodes_runtime[contract_name] = contract["bin-runtime"] compilation_unit.srcmaps_init[contract_name] = contract["srcmap"].split(";") compilation_unit.srcmaps_runtime[contract_name] = contract["srcmap-runtime"].split( ";" ) compilation_unit.libraries[contract_name] = contract["libraries"] userdoc = contract.get("userdoc", {}) devdoc = contract.get("devdoc", {}) compilation_unit.natspec[contract_name] = Natspec(userdoc, devdoc) if contract["is_dependency"]: crytic_compile.dependencies.add(filename.absolute) crytic_compile.dependencies.add(filename.relative) crytic_compile.dependencies.add(filename.short) crytic_compile.dependencies.add(filename.used) compilation_unit.asts = compilation_unit_json["asts"] compilation_unit.filenames = { _convert_dict_to_filename(filename) for filename in compilation_unit_json["filenames"] }
def _convert_dict_to_filename(filename: Dict) -> Filename: """Convert a dict to a Filename This function should be called only on well formed json Args: filename (Dict): Json to convert Returns: Filename: Filename converted """ assert "absolute" in filename assert "used" in filename assert "short" in filename assert "relative" in filename return Filename( absolute=filename["absolute"], relative=filename["relative"], short=filename["short"], used=filename["used"], )
def _handle_bytecode(crytic_compile: "CryticCompile", target: str, result_b: bytes) -> None: """Parse the bytecode and populate CryticCompile info Args: crytic_compile (CryticCompile): Associate CryticCompile object target (str): path to the target result_b (bytes): text containing the bytecode """ # There is no direct API to get the bytecode from etherscan # The page changes from time to time, we use for now a simple parsing, it will not be robust begin = """Search Algorithm">\nSimilar Contracts</button>\n""" begin += """<div id="dividcode">\n<pre class=\'wordwrap\' style=\'height: 15pc;\'>0x""" result = result_b.decode("utf8") # Removing everything before the begin string result = result[result.find(begin) + len(begin):] bytecode = result[:result.find("<")] contract_name = f"Contract_{target}" contract_filename = Filename(absolute="", relative="", short="", used="") compilation_unit = CompilationUnit(crytic_compile, str(target)) compilation_unit.contracts_names.add(contract_name) compilation_unit.filename_to_contracts[contract_filename].add( contract_name) compilation_unit.abis[contract_name] = {} compilation_unit.bytecodes_init[contract_name] = bytecode compilation_unit.bytecodes_runtime[contract_name] = "" compilation_unit.srcmaps_init[contract_name] = [] compilation_unit.srcmaps_runtime[contract_name] = [] compilation_unit.compiler_version = CompilerVersion(compiler="unknown", version="", optimized=False) crytic_compile.bytecode_only = True
def load_from_compile(crytic_compile, loaded_json): crytic_compile._asts = loaded_json["asts"] crytic_compile._compiler_version = CompilerVersion( compiler=loaded_json["compiler"]["compiler"], version=loaded_json["compiler"]["version"], optimized=loaded_json["compiler"]["optimized"], ) for contract_name, contract in loaded_json["contracts"].items(): crytic_compile._contracts_name.add(contract_name) filename = Filename( absolute=contract["filenames"]["absolute"], relative=contract["filenames"]["relative"], short=contract["filenames"]["short"], used=contract["filenames"]["used"], ) crytic_compile._contracts_filenames[contract_name] = filename crytic_compile._abis[contract_name] = contract["abi"] crytic_compile._init_bytecodes[contract_name] = contract["bin"] crytic_compile._runtime_bytecodes[contract_name] = contract[ "bin-runtime"] crytic_compile._srcmaps[contract_name] = contract["srcmap"].split(";") crytic_compile._srcmaps_runtime[contract_name] = contract[ "srcmap-runtime"].split(";") crytic_compile._libraries[contract_name] = contract["libraries"] if contract["is_dependency"]: crytic_compile._dependencies.add(filename.absolute) crytic_compile._dependencies.add(filename.relative) crytic_compile._dependencies.add(filename.short) crytic_compile._dependencies.add(filename.used) # Set our filenames crytic_compile._filenames = set( crytic_compile._contracts_filenames.values()) crytic_compile._working_dir = loaded_json["working_dir"] crytic_compile._type = loaded_json["type"]
def _load_from_compile_legacy(crytic_compile: "CryticCompile", loaded_json: Dict): compilation_unit = CompilationUnit(crytic_compile, "legacy") compilation_unit.asts = loaded_json["asts"] compilation_unit.compiler_version = CompilerVersion( compiler=loaded_json["compiler"]["compiler"], version=loaded_json["compiler"]["version"], optimized=loaded_json["compiler"]["optimized"], ) for contract_name, contract in loaded_json["contracts"].items(): compilation_unit.contracts_names.add(contract_name) filename = Filename( absolute=contract["filenames"]["absolute"], relative=contract["filenames"]["relative"], short=contract["filenames"]["short"], used=contract["filenames"]["used"], ) compilation_unit.contracts_filenames[contract_name] = filename compilation_unit.abis[contract_name] = contract["abi"] compilation_unit.bytecodes_init[contract_name] = contract["bin"] compilation_unit.bytecodes_runtime[contract_name] = contract[ "bin-runtime"] compilation_unit.srcmaps_init[contract_name] = contract[ "srcmap"].split(";") compilation_unit.srcmaps_runtime[contract_name] = contract[ "srcmap-runtime"].split(";") compilation_unit.libraries[contract_name] = contract["libraries"] userdoc = contract.get("userdoc", {}) devdoc = contract.get("devdoc", {}) compilation_unit.natspec[contract_name] = Natspec(userdoc, devdoc) if contract["is_dependency"]: compilation_unit.crytic_compile.dependencies.add(filename.absolute) compilation_unit.crytic_compile.dependencies.add(filename.relative) compilation_unit.crytic_compile.dependencies.add(filename.short) compilation_unit.crytic_compile.dependencies.add(filename.used)