def compile_and_format( contract_sources: Dict[str, str], solc_version: Optional[str] = None, vyper_version: Optional[str] = None, optimize: bool = True, runs: int = 200, evm_version: Optional[str] = None, silent: bool = True, allow_paths: Optional[str] = None, interface_sources: Optional[Dict[str, str]] = None, remappings: Optional[list] = None, optimizer: Optional[Dict] = None, ) -> Dict: """Compiles contracts and returns build data. Args: contract_sources: a dictionary in the form of {'path': "source code"} solc_version: solc version to compile with (use None to set via pragmas) optimize: (deprecated) enable solc optimizer runs: (deprecated) optimizer runs evm_version: evm version to compile for silent: verbose reporting allow_paths: compiler allowed filesystem import path interface_sources: dictionary of interfaces as {'path': "source code"} remappings: list of solidity path remappings optimizer: dictionary of solidity optimizer settings Returns: build data dict """ if not contract_sources: return {} if interface_sources is None: interface_sources = {} if [i for i in contract_sources if Path(i).suffix not in (".sol", ".vy")]: raise UnsupportedLanguage( "Source suffixes must be one of ('.sol', '.vy')") if [ i for i in interface_sources if Path(i).suffix not in (".sol", ".vy", ".json") ]: raise UnsupportedLanguage( "Interface suffixes must be one of ('.sol', '.vy', '.json')") build_json: Dict = {} compiler_targets = {} vyper_sources = { k: v for k, v in contract_sources.items() if Path(k).suffix == ".vy" } if vyper_sources: # TODO add `vyper_version` input arg to manually specify, support in config file if vyper_version is None: compiler_targets.update( find_vyper_versions(vyper_sources, install_needed=True, silent=silent)) else: compiler_targets[vyper_version] = list(vyper_sources) solc_sources = { k: v for k, v in contract_sources.items() if Path(k).suffix == ".sol" } if solc_sources: if solc_version is None: compiler_targets.update( find_solc_versions(solc_sources, install_needed=True, silent=silent)) else: compiler_targets[solc_version] = list(solc_sources) if optimizer is None: optimizer = {"enabled": optimize, "runs": runs if optimize else 0} for version, path_list in compiler_targets.items(): compiler_data: Dict = {} if path_list[0].endswith(".vy"): set_vyper_version(version) language = "Vyper" compiler_data["version"] = str(vyper.get_version()) interfaces = { k: v for k, v in interface_sources.items() if Path(k).suffix != ".sol" } else: set_solc_version(version) language = "Solidity" compiler_data["version"] = str(solidity.get_version()) interfaces = { k: v for k, v in interface_sources.items() if Path(k).suffix == ".sol" and Version(version) in sources.get_pragma_spec(v, k) } to_compile = { k: v for k, v in contract_sources.items() if k in path_list } input_json = generate_input_json( to_compile, evm_version=evm_version, language=language, interface_sources=interfaces, remappings=remappings, optimizer=optimizer, ) output_json = compile_from_input_json(input_json, silent, allow_paths) output_json["contracts"] = { k: v for k, v in output_json["contracts"].items() if k in path_list } build_json.update( generate_build_json(input_json, output_json, compiler_data, silent)) return build_json
def get_abi( contract_sources: Dict[str, str], allow_paths: Optional[str] = None, remappings: Optional[list] = None, silent: bool = True, ) -> Dict: """ Generate ABIs from contract interfaces. Arguments --------- contract_sources : dict a dictionary in the form of {'path': "source code"} allow_paths : str, optional Compiler allowed filesystem import path remappings : list, optional List of solidity path remappings silent : bool, optional Disable verbose reporting Returns ------- dict Compiled ABIs in the format `{'contractName': [ABI]}` """ final_output = { Path(k).stem: { "abi": json.loads(v), "contractName": Path(k).stem, "type": "interface", "sha1": sha1(v.encode()).hexdigest(), } for k, v in contract_sources.items() if Path(k).suffix == ".json" } for path, source in [(k, v) for k, v in contract_sources.items() if Path(k).suffix == ".vy"]: input_json = generate_input_json({path: source}, language="Vyper") input_json["settings"]["outputSelection"]["*"] = {"*": ["abi"]} try: output_json = compile_from_input_json(input_json, silent, allow_paths) except Exception: # vyper interfaces do not convert to ABIs # https://github.com/vyperlang/vyper/issues/1944 continue name = Path(path).stem final_output[name] = { "abi": output_json["contracts"][path][name], "contractName": name, "type": "interface", "sha1": sha1(contract_sources[path].encode()).hexdigest(), } solc_sources = { k: v for k, v in contract_sources.items() if Path(k).suffix == ".sol" } if solc_sources: compiler_targets = find_solc_versions(solc_sources, install_needed=True, silent=silent) for version, path_list in compiler_targets.items(): to_compile = { k: v for k, v in contract_sources.items() if k in path_list } set_solc_version(version) input_json = generate_input_json( to_compile, language="Vyper" if version == "vyper" else "Solidity", remappings=remappings, ) input_json["settings"]["outputSelection"]["*"] = {"*": ["abi"]} output_json = compile_from_input_json(input_json, silent, allow_paths) output_json = { k: v for k, v in output_json["contracts"].items() if k in path_list } final_output.update({ name: { "abi": data["abi"], "contractName": name, "type": "interface", "sha1": sha1(contract_sources[path].encode()).hexdigest(), } for path, v in output_json.items() for name, data in v.items() }) return final_output
def compile_and_format( contract_sources: Dict[str, str], solc_version: Optional[str] = None, optimize: bool = True, runs: int = 200, evm_version: int = None, minify: bool = False, silent: bool = True, allow_paths: Optional[str] = None, interface_sources: Optional[Dict[str, str]] = None, ) -> Dict: """Compiles contracts and returns build data. Args: contracts: a dictionary in the form of {'path': "source code"} solc_version: solc version to compile with (use None to set via pragmas) optimize: enable solc optimizer runs: optimizer runs evm_version: evm version to compile for minify: minify source files silent: verbose reporting allow_paths: compiler allowed filesystem import path Returns: build data dict """ if not contract_sources: return {} if interface_sources is None: interface_sources = {} if [i for i in contract_sources if Path(i).suffix not in (".sol", ".vy")]: raise UnsupportedLanguage( "Source suffixes must be one of ('.sol', '.vy')") if [ i for i in interface_sources if Path(i).suffix not in (".sol", ".vy", ".json") ]: raise UnsupportedLanguage( "Interface suffixes must be one of ('.sol', '.vy', '.json')") build_json: Dict = {} compiler_targets = {} vyper_paths = [i for i in contract_sources if Path(i).suffix == ".vy"] if vyper_paths: compiler_targets["vyper"] = vyper_paths solc_sources = { k: v for k, v in contract_sources.items() if Path(k).suffix == ".sol" } if solc_sources: if solc_version is None: compiler_targets.update( find_solc_versions(solc_sources, install_needed=True, silent=silent)) else: compiler_targets[solc_version] = list(solc_sources) for version, path_list in compiler_targets.items(): compiler_data: Dict = {"minify_source": minify} if version == "vyper": language = "Vyper" compiler_data["version"] = str(vyper.get_version()) interfaces = { k: v for k, v in interface_sources.items() if Path(k).suffix != ".sol" } else: set_solc_version(version) language = "Solidity" compiler_data["version"] = str(solidity.get_version()) interfaces = { k: v for k, v in interface_sources.items() if Path(k).suffix == ".sol" and Version(version) in sources.get_pragma_spec(v, k) } to_compile = { k: v for k, v in contract_sources.items() if k in path_list } input_json = generate_input_json(to_compile, optimize, runs, evm_version, minify, language, interfaces) output_json = compile_from_input_json(input_json, silent, allow_paths) output_json["contracts"] = { k: v for k, v in output_json["contracts"].items() if k in path_list } build_json.update( generate_build_json(input_json, output_json, compiler_data, silent)) return build_json
def get_abi( contract_sources: Dict[str, str], allow_paths: Optional[str] = None, remappings: Optional[list] = None, silent: bool = True, ) -> Dict: """ Generate ABIs from contract interfaces. Arguments --------- contract_sources : dict a dictionary in the form of {'path': "source code"} allow_paths : str, optional Compiler allowed filesystem import path remappings : list, optional List of solidity path remappings silent : bool, optional Disable verbose reporting Returns ------- dict Compiled ABIs in the format `{'contractName': [ABI]}` """ final_output = { Path(k).stem: { "abi": json.loads(v), "contractName": Path(k).stem, "type": "interface", "source": None, "offset": None, "sha1": sha1(v.encode()).hexdigest(), } for k, v in contract_sources.items() if Path(k).suffix == ".json" } for path, source in [(k, v) for k, v in contract_sources.items() if Path(k).suffix == ".vy"]: input_json = generate_input_json({path: source}, language="Vyper") input_json["settings"]["outputSelection"]["*"] = {"*": ["abi"]} try: output_json = compile_from_input_json(input_json, silent, allow_paths) except Exception: # vyper interfaces do not convert to ABIs # https://github.com/vyperlang/vyper/issues/1944 continue name = Path(path).stem final_output[name] = { "abi": output_json["contracts"][path][name]["abi"], "contractName": name, "type": "interface", "source": source, "offset": [0, len(source)], "sha1": sha1(contract_sources[path].encode()).hexdigest(), } solc_sources = { k: v for k, v in contract_sources.items() if Path(k).suffix == ".sol" } if not solc_sources: return final_output compiler_targets = find_solc_versions(solc_sources, install_needed=True, silent=silent) for version, path_list in compiler_targets.items(): to_compile = { k: v for k, v in contract_sources.items() if k in path_list } set_solc_version(version) input_json = generate_input_json(to_compile, language="Solidity", remappings=remappings) input_json["settings"]["outputSelection"]["*"] = { "*": ["abi"], "": ["ast"] } output_json = compile_from_input_json(input_json, silent, allow_paths) source_nodes = solcast.from_standard_output(output_json) abi_json = { k: v for k, v in output_json["contracts"].items() if k in path_list } for path, name, data in [(k, x, y) for k, v in abi_json.items() for x, y in v.items()]: contract_node = next(i[name] for i in source_nodes if i.absolutePath == path) dependencies = [] for node in [ i for i in contract_node.dependencies if i.nodeType == "ContractDefinition" ]: dependency_name = node.name path_str = node.parent().absolutePath dependencies.append(_get_alias(dependency_name, path_str)) final_output[name] = { "abi": data["abi"], "ast": output_json["sources"][path]["ast"], "contractName": name, "dependencies": dependencies, "type": "interface", "source": contract_sources[path], "offset": contract_node.offset, "sha1": sha1(contract_sources[path].encode()).hexdigest(), } return final_output
def compile_and_format( contract_sources: Dict[str, str], solc_version: Optional[str] = None, optimize: bool = True, runs: int = 200, evm_version: int = None, minify: bool = False, silent: bool = True, allow_paths: Optional[str] = None, ) -> Dict: """Compiles contracts and returns build data. Args: contracts: a dictionary in the form of {'path': "source code"} solc_version: solc version to compile with (use None to set via pragmas) optimize: enable solc optimizer runs: optimizer runs evm_version: evm version to compile for minify: minify source files silent: verbose reporting allow_paths: compiler allowed filesystem import path Returns: build data dict """ if not contract_sources: return {} if [ i for i in contract_sources if not i.endswith(".sol") and not i.endswith(".vy") ]: raise UnsupportedLanguage("Source filenames must end in .sol or .vy") build_json: Dict = {} compiler_targets = {} vyper_paths = [i for i in contract_sources if i.endswith(".vy")] if vyper_paths: compiler_targets["vyper"] = vyper_paths solc_sources = dict( (k, v) for k, v in contract_sources.items() if k.endswith(".sol")) if solc_sources: if solc_version is None: compiler_targets.update( find_solc_versions(solc_sources, install_needed=True, silent=silent)) else: compiler_targets[solc_version] = list(solc_sources) compiler_data: Dict = {"minify_source": minify} for version, path_list in compiler_targets.items(): if version == "vyper": language = "Vyper" compiler_data["version"] = str(vyper.get_version()) else: set_solc_version(version) language = "Solidity" compiler_data["version"] = str(solidity.get_version()) to_compile = dict( (k, v) for k, v in contract_sources.items() if k in path_list) input_json = generate_input_json(to_compile, optimize, runs, evm_version, minify, language) output_json = compile_from_input_json(input_json, silent, allow_paths) build_json.update( generate_build_json(input_json, output_json, compiler_data, silent)) return build_json