def compile_solfiles(files, proj_dir, solc_version=None, output_values=OUTPUT_VALUES): remappings = [] node_modules_dir = find_node_modules_dir(proj_dir) if node_modules_dir is not None: zeppelin_path = os.path.abspath(os.path.join( node_modules_dir, 'zeppelin-solidity')) open_zeppelin_path = os.path.abspath( os.path.join(node_modules_dir, 'openzeppelin-solidity')) if os.path.isdir(zeppelin_path): remappings.append(f'zeppelin-solidity={zeppelin_path}') if os.path.isdir(open_zeppelin_path): remappings.append(f'openzeppelin-solidity={open_zeppelin_path}') if solc_version is None: solc_version = min(map(parse_version, files), key=_version_to_tuple) binary = os.path.join(get_solc_folder(), f'solc-v{solc_version}') combined_json = ','.join(output_values) compiler_kwargs = {'import_remappings': remappings, 'allow_paths': proj_dir, 'source_files': files, 'solc_binary': binary, 'combined_json': combined_json} try: stdoutdata, _, _, _ = solc_wrapper(**compiler_kwargs) return _parse_compiler_output(stdoutdata) except SolcError as e: raise SolidityCompilationException(e, files)
def _compile_combined_json( output_values: Optional[List], solc_binary: Union[str, Path, None], solc_version: Optional[Version], output_dir: Union[str, Path, None], overwrite: Optional[bool], allow_empty: Optional[bool], **kwargs: Any, ) -> Dict: if output_values is None: combined_json = _get_combined_json_outputs() else: combined_json = ",".join(output_values) if solc_binary is None: solc_binary = get_executable(solc_version) if output_dir: output_dir = Path(output_dir) if output_dir.is_file(): raise FileExistsError( "`output_dir` must be as a directory, not a file") if output_dir.joinpath("combined.json").exists() and not overwrite: target_path = output_dir.joinpath("combined.json") raise FileExistsError( f"Target output file {target_path} already exists - use overwrite=True to overwrite" ) stdoutdata, stderrdata, command, proc = wrapper.solc_wrapper( solc_binary=solc_binary, combined_json=combined_json, output_dir=output_dir, overwrite=overwrite, **kwargs, ) if output_dir: output_path = Path(output_dir).joinpath("combined.json") if stdoutdata: output_path.parent.mkdir(parents=True, exist_ok=True) with output_path.open("w") as fp: fp.write(stdoutdata) else: with output_path.open() as fp: stdoutdata = fp.read() contracts = _parse_compiler_output(stdoutdata) if not contracts and not allow_empty: raise ContractsNotFound( command=command, return_code=proc.returncode, stdout_data=stdoutdata, stderr_data=stderrdata, ) return contracts
def _get_combined_json_outputs(solc_binary: Union[Path, str] = None) -> str: if solc_binary is None: solc_binary = get_executable() help_str = wrapper.solc_wrapper(solc_binary=solc_binary, help=True)[0].split("\n") combined_json_args = next(i for i in help_str if i.startswith(" --combined-json")) return combined_json_args.split(" ")[-1]
def compile_solfiles(files, proj_dir, solc_version=None, output_values=OUTPUT_VALUES, remappings=None): def complete_remapping(remapping): name, old_path = remapping.split('=') new_path = os.path.join(proj_dir, old_path) return f'{name}={new_path}' if remappings is None: remappings = [] remappings = [complete_remapping(remapping) for remapping in remappings] node_modules_dir = find_node_modules_dir(proj_dir) if node_modules_dir is not None: zeppelin_path = os.path.abspath( os.path.join(node_modules_dir, 'zeppelin-solidity')) open_zeppelin_path = os.path.abspath( os.path.join(node_modules_dir, 'openzeppelin-solidity')) if os.path.isdir(zeppelin_path): remappings.append(f'zeppelin-solidity={zeppelin_path}') if os.path.isdir(open_zeppelin_path): remappings.append(f'openzeppelin-solidity={open_zeppelin_path}') if solc_version is None: if len(get_supported_solc_versions()) == 0: raise CompilerVersionNotSupported( "No compiler available. No connection to GitHub?") all_conditions = [] for source in files: all_conditions.extend(_parse_conditions(source)) solc_version = _find_version_for_conditions(all_conditions) try: install_solc(f'v{solc_version}') except (requests.exceptions.ConnectionError, subprocess.CalledProcessError): raise CompilerVersionNotSupported( f'Failed to install v{solc_version} compiler.') binary = _get_binary(solc_version) combined_json = ','.join(output_values) compiler_kwargs = { 'import_remappings': remappings, 'allow_paths': proj_dir, 'source_files': files, 'solc_binary': binary, 'combined_json': combined_json } try: stdoutdata, _, _, _ = solc_wrapper(**compiler_kwargs) return _parse_compiler_output(stdoutdata) except SolcError as e: raise SolidityCompilationException(e, solc_version, files)
def compile_solfiles(files, proj_dir, solc_version=None, output_values=OUTPUT_VALUES, remappings=None): def complete_remapping(remapping): name, old_path = remapping.split('=') new_path = os.path.join(proj_dir, old_path) return f'{name}={new_path}' if remappings is None: remappings = [] remappings = [complete_remapping(remapping) for remapping in remappings] node_modules_dir = find_node_modules_dir(proj_dir) if node_modules_dir is not None: zeppelin_path = os.path.abspath( os.path.join(node_modules_dir, 'zeppelin-solidity')) open_zeppelin_path = os.path.abspath( os.path.join(node_modules_dir, 'openzeppelin-solidity')) if os.path.isdir(zeppelin_path): remappings.append(f'zeppelin-solidity={zeppelin_path}') if os.path.isdir(open_zeppelin_path): remappings.append(f'openzeppelin-solidity={open_zeppelin_path}') if solc_version is None: solc_version = max(map(parse_version, files)) binary = _get_binary(solc_version) combined_json = ','.join(output_values) compiler_kwargs = { 'import_remappings': remappings, 'allow_paths': proj_dir, 'source_files': files, 'solc_binary': binary, 'combined_json': combined_json } try: stdoutdata, _, _, _ = solc_wrapper(**compiler_kwargs) return _parse_compiler_output(stdoutdata) except SolcError as e: raise SolidityCompilationException(e, files)
def _compile_solfiles(self, files, solc_version=None, output_values=utils.OUTPUT_VALUES): """Compiles the files using the solc compiler. """ node_modules_dir = utils.find_node_modules_dir(self.project_root) remappings = [] if node_modules_dir is not None: zeppelin_path = os.path.abspath( os.path.join(node_modules_dir, 'zeppelin-solidity')) open_zeppelin_path = os.path.abspath( os.path.join(node_modules_dir, 'openzeppelin-solidity')) if os.path.isdir(zeppelin_path): remappings.append(f'zeppelin-solidity={zeppelin_path}') if os.path.isdir(open_zeppelin_path): remappings.append( f'openzeppelin-solidity={open_zeppelin_path}') if solc_version is None: solc_version = min(map(utils.parse_sol_version, files), key=utils.version_to_tuple) binary = _get_binary(solc_version) combined_json = ','.join(output_values) compiler_kwargs = { 'import_remappings': remappings, 'allow_paths': self.project_root, 'source_files': files, 'solc_binary': binary, 'combined_json': combined_json } try: stdoutdata, _, _, _ = solc_wrapper(**compiler_kwargs) return _parse_compiler_output(stdoutdata) except SolcError as e: raise utils.SolidityCompilationException(e, files)
def link_code( unlinked_bytecode: str, libraries: Dict, solc_binary: Union[str, Path] = None, solc_version: Version = None, ) -> str: """ Add library addresses into unlinked bytecode. Arguments --------- unlinked_bytecode : str Compiled bytecode containing one or more library placeholders. libraries : Dict Library addresses given as {"library name": "address"} solc_binary : str | Path, optional Path of the `solc` binary to use. If not given, the currently active version is used (as set by `solcx.set_solc_version`) solc_version: Version, optional `solc` version to use. If not given, the currently active version is used. Ignored if `solc_binary` is also given. Returns ------- str Linked bytecode """ if solc_binary is None: solc_binary = get_executable(solc_version) library_list = [f"{name}:{address}" for name, address in libraries.items()] stdoutdata = wrapper.solc_wrapper(solc_binary=solc_binary, stdin=unlinked_bytecode, link=True, libraries=library_list)[0] return stdoutdata.replace("Linking completed.", "").strip()
def compile_standard( input_data: Dict, base_path: str = None, allow_paths: List = None, output_dir: str = None, overwrite: bool = False, solc_binary: Union[str, Path] = None, solc_version: Version = None, allow_empty: bool = False, ) -> Dict: """ Compile Solidity contracts using the JSON-input-output interface. See the Solidity documentation for details on the expected JSON input and output formats. Arguments --------- input_data : Dict Compiler JSON input. base_path : Path | str, optional Use the given path as the root of the source tree instead of the root of the filesystem. allow_paths : List | Path | str, optional A path, or list of paths, to allow for imports. output_dir : str, optional Creates one file per component and contract/file at the specified directory. overwrite : bool, optional Overwrite existing files (used in combination with `output_dir`) solc_binary : str | Path, optional Path of the `solc` binary to use. If not given, the currently active version is used (as set by `solcx.set_solc_version`) solc_version: Version, optional `solc` version to use. If not given, the currently active version is used. Ignored if `solc_binary` is also given. allow_empty : bool, optional If `True`, do not raise when no compiled contracts are returned. Returns ------- Dict Compiler JSON output. """ if not input_data.get("sources") and not allow_empty: raise ContractsNotFound( "Input JSON does not contain any sources", stdin_data=json.dumps(input_data, sort_keys=True, indent=2), ) if solc_binary is None: solc_binary = get_executable(solc_version) stdoutdata, stderrdata, command, proc = wrapper.solc_wrapper( solc_binary=solc_binary, stdin=json.dumps(input_data), standard_json=True, base_path=base_path, allow_paths=allow_paths, output_dir=output_dir, overwrite=overwrite, ) compiler_output = json.loads(stdoutdata) if "errors" in compiler_output: has_errors = any(error["severity"] == "error" for error in compiler_output["errors"]) if has_errors: error_message = "\n".join( tuple(error["formattedMessage"] for error in compiler_output["errors"] if error["severity"] == "error")) raise SolcError( error_message, command=command, return_code=proc.returncode, stdin_data=json.dumps(input_data), stdout_data=stdoutdata, stderr_data=stderrdata, error_dict=compiler_output["errors"], ) return compiler_output
def _get_combined_json_outputs() -> str: help_str = wrapper.solc_wrapper(help=True)[0].split("\n") combined_json_args = next(i for i in help_str if i.startswith(" --combined-json")) return combined_json_args.split(" ")[-1]