def _compare_build_json(self, contract_name: str) -> bool: config = self._compiler_config # confirm that this contract was previously compiled try: source = self._sources.get(contract_name) build_json = self._build.get(contract_name) except KeyError: return True # compare source hashes if build_json["sha1"] != sha1(source.encode()).hexdigest(): return True # compare compiler settings if _compare_settings(config, build_json["compiler"]): return True if build_json["language"] == "Solidity": # compare solc-specific compiler settings solc_config = config["solc"].copy() solc_config["remappings"] = None if _compare_settings(solc_config, build_json["compiler"]): return True # compare solc pragma against compiled version if Version(build_json["compiler"] ["version"]) not in get_pragma_spec(source): return True return False
def _compare_build_json(self, contract_name: str) -> bool: config = self._compiler_config # confirm that this contract was previously compiled try: source = self._sources.get(contract_name) build_json = self._build.get(contract_name) except KeyError: return True # compare source hashes hash_ = get_hash(source, contract_name, config["minify_source"], build_json["language"]) if build_json["sha1"] != hash_: return True # compare compiler settings if _compare_settings(config, build_json["compiler"]): return True if build_json["language"] == "Solidity": # compare solc-specific compiler settings if _compare_settings(config["solc"], build_json["compiler"]): return True # compare solc pragma against compiled version if Version(build_json["compiler"] ["version"]) not in get_pragma_spec(source): return True return False
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 test_get_pragma_spec(): assert sources.get_pragma_spec(MESSY_SOURCE) == NpmSpec(">=0.4.22 <0.7.0")
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