def _get_version(truffle_call: List[str], cwd: str) -> Tuple[str, str]: cmd = truffle_call + ["version"] try: with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) as process: sstdout, _ = process.communicate() ssstdout = sstdout.decode( ) # convert bytestrings to unicode strings if not ssstdout: raise InvalidCompilation( "Truffle failed to run: 'truffle version'") stdout = ssstdout.split("\n") for line in stdout: if "Solidity" in line: if "native" in line: return solc.get_version("solc", dict()), "solc-native" version = re.findall(r"\d+\.\d+\.\d+", line)[0] compiler = re.findall(r"(solc[a-z\-]*)", line) if len(compiler) > 0: return version, compiler[0] raise InvalidCompilation(f"Solidity version not found {stdout}") except OSError as error: # pylint: disable=raise-missing-from raise InvalidCompilation(f"Truffle failed: {error}")
def _get_version(truffle_call, cwd): cmd = truffle_call + ["version"] process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) stdout, _ = process.communicate() stdout = stdout.decode() # convert bytestrings to unicode strings stdout = stdout.split("\n") for line in stdout: if "Solidity" in line: if "native" in line: return solc.get_version("solc"), "solc-native" version = re.findall(r"\d+\.\d+\.\d+", line)[0] compiler = re.findall(r"(solc[a-z\-]*)", line) if len(compiler) > 0: return version, compiler raise InvalidCompilation(f"Solidity version not found {stdout}")
def compile(self, crytic_compile: "CryticCompile", **kwargs: Any) -> None: """[summary] Args: crytic_compile (CryticCompile): Associated CryticCompile object **kwargs: optional arguments. Used: "solc", "solc_disable_warnings", "solc_args", "solc_working_dir", "solc_remaps" """ solc: str = kwargs.get("solc", "solc") solc_disable_warnings: bool = kwargs.get("solc_disable_warnings", False) solc_arguments: str = kwargs.get("solc_args", "") solc_remaps: Optional[Union[str, List[str]]] = kwargs.get( "solc_remaps", None) solc_working_dir: Optional[str] = kwargs.get("solc_working_dir", None) compilation_unit = CompilationUnit(crytic_compile, "standard_json") compilation_unit.compiler_version = CompilerVersion( compiler="solc", version=get_version(solc, None), optimized=is_optimized(solc_arguments), ) # Add all remappings if solc_remaps: if isinstance(solc_remaps, str): solc_remaps = solc_remaps.split(" ") for solc_remap in solc_remaps: self.add_remapping(solc_remap) # Invoke solc targets_json = run_solc_standard_json( self.to_dict(), compilation_unit.compiler_version, solc_disable_warnings=solc_disable_warnings, ) parse_standard_json_output(targets_json, compilation_unit, solc_working_dir=solc_working_dir)
def _get_version(truffle_call: List[str], cwd: str) -> Tuple[str, str]: """Get the compiler version Args: truffle_call (List[str]): Command to run truffle cwd (str): Working directory to run truffle Raises: InvalidCompilation: If truffle failed, or the solidity version was not found Returns: Tuple[str, str]: (compiler version, compiler name) """ cmd = truffle_call + ["version"] try: with subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, executable=shutil.which(cmd[0]), ) as process: sstdout, _ = process.communicate() ssstdout = sstdout.decode( ) # convert bytestrings to unicode strings if not ssstdout: raise InvalidCompilation( "Truffle failed to run: 'truffle version'") stdout = ssstdout.split("\n") for line in stdout: if "Solidity" in line: if "native" in line: return solc.get_version("solc", {}), "solc-native" version = re.findall(r"\d+\.\d+\.\d+", line)[0] compiler = re.findall(r"(solc[a-z\-]*)", line) if len(compiler) > 0: return version, compiler[0] raise InvalidCompilation(f"Solidity version not found {stdout}") except OSError as error: # pylint: disable=raise-missing-from raise InvalidCompilation(f"Truffle failed: {error}")
def compile( crytic_compile: "CryticCompile", target: Union[str, dict, "SolcStandardJson"], **kwargs: str ): """ Compile the target :param crytic_compile: :param target: :param kwargs: :return: """ crytic_compile.type = Type.SOLC_STANDARD_JSON solc = kwargs.get("solc", "solc") solc_disable_warnings = kwargs.get("solc_disable_warnings", False) solc_arguments = kwargs.get("solc_args", "") solc_remaps: Optional[Union[str, List[str]]] = kwargs.get("solc_remaps", None) solc_working_dir = kwargs.get("solc_working_dir", None) crytic_compile.compiler_version = CompilerVersion( compiler="solc", version=get_version(solc), optimized=_is_optimized(solc_arguments) ) skip_filename = crytic_compile.compiler_version.version in [f"0.4.{x}" for x in range(0, 10)] # Initialize our solc input target = SolcStandardJson(target) # Add all remappings if solc_remaps: if isinstance(solc_remaps, str): solc_remaps = solc_remaps.split(" ") for solc_remap in solc_remaps: target.add_remapping(solc_remap) # Invoke solc targets_json = _run_solc_standard_json( target.to_dict(), solc, solc_disable_warnings=solc_disable_warnings ) if "contracts" in targets_json: for file_path, file_contracts in targets_json["contracts"].items(): for contract_name, info in file_contracts.items(): # for solc < 0.4.10 we cant retrieve the filename from the ast if skip_filename: # TODO investigate the mypy type issue contract_filename = convert_filename( target, _relative_to_short, crytic_compile, working_dir=solc_working_dir ) else: contract_filename = convert_filename( file_path, _relative_to_short, crytic_compile, working_dir=solc_working_dir ) crytic_compile.contracts_names.add(contract_name) crytic_compile.contracts_filenames[contract_name] = contract_filename crytic_compile.abis[contract_name] = info["abi"] crytic_compile.bytecodes_init[contract_name] = info["evm"]["bytecode"]["object"] crytic_compile.bytecodes_runtime[contract_name] = info["evm"]["deployedBytecode"][ "object" ] crytic_compile.srcmaps_init[contract_name] = info["evm"]["bytecode"][ "sourceMap" ].split(";") crytic_compile.srcmaps_runtime[contract_name] = info["evm"]["deployedBytecode"][ "sourceMap" ].split(";") if "sources" in targets_json: for path, info in targets_json["sources"].items(): if skip_filename: path = convert_filename( target, _relative_to_short, crytic_compile, working_dir=solc_working_dir ) else: path = convert_filename( path, _relative_to_short, crytic_compile, working_dir=solc_working_dir ) crytic_compile.filenames.add(path) crytic_compile.asts[path.absolute] = info["ast"]
def compile(self, crytic_compile: "CryticCompile", **kwargs: str): """ Compile the target :param crytic_compile: :param target: :param kwargs: :return: """ solc = kwargs.get("solc", "solc") solc_disable_warnings = kwargs.get("solc_disable_warnings", False) solc_arguments = kwargs.get("solc_args", "") solc_remaps: Optional[Union[str, List[str]]] = kwargs.get( "solc_remaps", None) solc_working_dir = kwargs.get("solc_working_dir", None) crytic_compile.compiler_version = CompilerVersion( compiler="solc", version=get_version(solc), optimized=is_optimized(solc_arguments)) skip_filename = crytic_compile.compiler_version.version in [ f"0.4.{x}" for x in range(0, 10) ] # Add all remappings if solc_remaps: if isinstance(solc_remaps, str): solc_remaps = solc_remaps.split(" ") for solc_remap in solc_remaps: self.add_remapping(solc_remap) # Invoke solc targets_json = _run_solc_standard_json( self.to_dict(), solc, solc_disable_warnings=solc_disable_warnings) if "contracts" in targets_json: for file_path, file_contracts in targets_json["contracts"].items(): for contract_name, info in file_contracts.items(): # for solc < 0.4.10 we cant retrieve the filename from the ast if skip_filename: contract_filename = convert_filename( self._target, relative_to_short, crytic_compile, working_dir=solc_working_dir, ) else: contract_filename = convert_filename( file_path, relative_to_short, crytic_compile, working_dir=solc_working_dir, ) crytic_compile.contracts_names.add(contract_name) crytic_compile.contracts_filenames[ contract_name] = contract_filename crytic_compile.abis[contract_name] = info["abi"] userdoc = info.get("userdoc", {}) devdoc = info.get("devdoc", {}) natspec = Natspec(userdoc, devdoc) crytic_compile.natspec[contract_name] = natspec crytic_compile.bytecodes_init[contract_name] = info["evm"][ "bytecode"]["object"] crytic_compile.bytecodes_runtime[contract_name] = info[ "evm"]["deployedBytecode"]["object"] crytic_compile.srcmaps_init[contract_name] = info["evm"][ "bytecode"]["sourceMap"].split(";") crytic_compile.srcmaps_runtime[contract_name] = info[ "evm"]["deployedBytecode"]["sourceMap"].split(";") if "sources" in targets_json: for path, info in targets_json["sources"].items(): if skip_filename: path = convert_filename( self._target, relative_to_short, crytic_compile, working_dir=solc_working_dir, ) else: path = convert_filename(path, relative_to_short, crytic_compile, working_dir=solc_working_dir) crytic_compile.filenames.add(path) crytic_compile.asts[path.absolute] = info["ast"]