def test_set_solc_version(): compiler.set_solc_version("0.5.7") assert solcx.get_solc_version().truncate() == compiler.solidity.get_version() assert solcx.get_solc_version().truncate() == Version("0.5.7") compiler.set_solc_version("0.4.25") assert solcx.get_solc_version().truncate() == compiler.solidity.get_version() assert solcx.get_solc_version().truncate() == Version("0.4.25")
def test_unlinked_libraries(version): source = _solc_5_source() build_json = sources.compile_source(source) assert '__TestLib__' in build_json['TempTester']['bytecode'] compiler.set_solc_version("v0.4.25") source = _solc_4_source() build_json = sources.compile_source(source) assert '__TestLib__' in build_json['TempTester']['bytecode']
def test_compiler_errors(version): with pytest.raises(CompilerError): sources.compile_paths(["contracts/Token.sol"]) sources.compile_paths(["contracts/Token.sol", "contracts/SafeMath.sol"]) source = _solc_4_source() with pytest.raises(CompilerError): sources.compile_source(source) compiler.set_solc_version("v0.4.25") sources.compile_source(source)
def test_set_solc_version(): compiler.set_solc_version("0.5.7") assert solcx.get_solc_version( with_commit_hash=True) == compiler.solidity.get_version() assert solcx.get_solc_version( with_commit_hash=True).truncate() == Version("0.5.7") compiler.set_solc_version("0.4.25") assert solcx.get_solc_version( with_commit_hash=True) == compiler.solidity.get_version() assert solcx.get_solc_version( with_commit_hash=True).truncate() == Version("0.4.25")
def load(self) -> None: """Compiles the project contracts, creates ContractContainer objects and populates the namespace.""" if self._active: raise ProjectAlreadyLoaded("Project is already active") self._compiler_config = _load_project_compiler_config(self._path, "solc") solc_version = self._compiler_config["version"] if solc_version: self._compiler_config["version"] = compiler.set_solc_version(solc_version) # compile updated sources, update build changed = self._get_changed_contracts() self._compiler_config["version"] = solc_version self._compile(changed, self._compiler_config, False) self._create_containers() self._load_deployments() # add project to namespaces, apply import blackmagic name = self._name self.__all__ = list(self._containers) sys.modules[f"brownie.project.{name}"] = self # type: ignore sys.modules["brownie.project"].__dict__[name] = self sys.modules["brownie.project"].__all__.append(name) # type: ignore sys.modules["brownie.project"].__console_dir__.append(name) # type: ignore self._namespaces = [ sys.modules["__main__"].__dict__, sys.modules["brownie.project"].__dict__, ] self._active = True _loaded_projects.append(self)
def load(self): '''Compiles the project contracts, creates ContractContainer objects and populates the namespace.''' if self._active: raise ProjectAlreadyLoaded("Project is already active") self._compiler_config = load_project_compiler_config( self._project_path, "solc") solc_version = self._compiler_config['version'] if solc_version: self._compiler_config['version'] = compiler.set_solc_version( solc_version) # compile updated sources, update build changed = self._get_changed_contracts() self._compiler_config['version'] = solc_version self._compile(changed, self._compiler_config, False) self._create_containers() # add project to namespaces, apply import blackmagic name = self._name self.__all__ = list(self._containers) sys.modules[f'brownie.project.{name}'] = self sys.modules['brownie.project'].__dict__[name] = self sys.modules['brownie.project'].__all__.append(name) sys.modules['brownie.project'].__console_dir__.append(name) self._namespaces = [ sys.modules['__main__'].__dict__, sys.modules['brownie.project'].__dict__ ] self._active = True _loaded_projects.append(self)
def load(project_path=None): '''Loads a project and instantiates various related objects. Args: project_path: Path of the project to load. If None, will attempt to locate a project using check_for_project() Returns a list of ContractContainer objects. ''' # checks if CONFIG['folders']['project']: raise ProjectAlreadyLoaded( f"Project already loaded at {CONFIG['folders']['project']}") if project_path is None: project_path = check_for_project('.') if not project_path or not Path(project_path).joinpath( "brownie-config.json").exists(): raise ProjectNotFound("Could not find Brownie project") # paths project_path = Path(project_path).resolve() _create_folders(project_path) _add_to_sys_path(project_path) # load config load_project_config(project_path) CONFIG['solc']['version'] = compiler.set_solc_version( CONFIG['solc']['version']) # load sources and build sources.load(project_path) build.load(project_path) # compare build, erase as needed changed_paths = _get_changed_contracts() # compile sources, update build build_json = sources.compile_paths(changed_paths, optimize=CONFIG['solc']['optimize'], runs=CONFIG['solc']['runs'], minify=CONFIG['solc']['minify_source']) for data in build_json.values(): build.add(data) # create objects, add to namespace return _create_objects()
def solc5json(solc5source): compiler.set_solc_version("0.5.7") input_json = compiler.generate_input_json({"path": solc5source}, True, 200) yield compiler.compile_from_input_json(input_json)
def test_min_version(): with pytest.raises(IncompatibleSolcVersion): compiler.set_solc_version("v0.4.21")
def solc6json(solc6source): compiler.set_solc_version("0.6.2") input_json = compiler.generate_input_json({"path.sol": solc6source}, True, 200) yield compiler.compile_from_input_json(input_json)
def test_compile_input_json_evm_translates(solc5source, original, translated): compiler.set_solc_version("0.5.7") input_json = compiler.generate_input_json({"path.sol": solc5source}, True, 200, original) compiler.compile_from_input_json(input_json)
def test_build_json_unlinked_libraries(): build_json = compiler.compile_and_format({'path': _solc_5_source()}) assert '__TestLib__' in build_json['TempTester']['bytecode'] compiler.set_solc_version("v0.4.25") build_json = compiler.compile_and_format({'path': _solc_4_source()}) assert '__TestLib__' in build_json['TempTester']['bytecode']
def _solc_4_output_json(): compiler.set_solc_version("0.4.25") source = _solc_4_source() input_json = compiler.generate_input_json({'path': source}, True, 200) return compiler.compile_from_input_json(input_json)
def version(): yield compiler.set_solc_version("v0.5.7")
def test_set_solc_version(): compiler.set_solc_version("0.5.7") assert "0.5.7" in solcx.get_solc_version_string() compiler.set_solc_version("0.4.25") assert "0.4.25" in solcx.get_solc_version_string()
def from_explorer( cls, address: str, as_proxy_for: Optional[str] = None, owner: Optional[AccountsType] = None, silent: bool = False, ) -> "Contract": """ Create a new `Contract` object with source code queried from a block explorer. Arguments --------- address : str Address where the contract is deployed. as_proxy_for : str, optional Address of the implementation contract, if `address` is a proxy contract. The generated object will send transactions to `address`, but use the ABI and NatSpec of `as_proxy_for`. This field is only required when the block explorer API does not provide an implementation address. owner : Account, optional Contract owner. If set, transactions without a `from` field will be performed using this account. """ address = _resolve_address(address) data = _fetch_from_explorer(address, "getsourcecode", silent) is_verified = bool(data["result"][0].get("SourceCode")) if is_verified: abi = json.loads(data["result"][0]["ABI"]) name = data["result"][0]["ContractName"] else: # if the source is not available, try to fetch only the ABI try: data_abi = _fetch_from_explorer(address, "getabi", True) except ValueError as exc: _unverified_addresses.add(address) raise exc abi = json.loads(data_abi["result"].strip()) name = "UnknownContractName" warnings.warn( f"{address}: Was able to fetch the ABI but not the source code. " "Some functionality will not be available.", BrownieCompilerWarning, ) if as_proxy_for is None and data["result"][0].get("Implementation"): as_proxy_for = _resolve_address( data["result"][0]["Implementation"]) # if this is a proxy, fetch information for the implementation contract if as_proxy_for is not None: implementation_contract = Contract.from_explorer(as_proxy_for) abi = implementation_contract._build["abi"] if not is_verified: return cls.from_abi(name, address, abi, owner) try: version = Version( data["result"][0]["CompilerVersion"].lstrip("v")).truncate() except Exception: version = Version("0.0.0") if version < Version("0.4.22") or ( # special case for OSX because installing 0.4.x versions is problematic sys.platform == "darwin" and version < Version("0.5.0") and f"v{version}" not in solcx.get_installed_solc_versions()): if not silent: warnings.warn( f"{address}: target compiler '{data['result'][0]['CompilerVersion']}' is " "unsupported by Brownie. Some functionality will not be available.", BrownieCompilerWarning, ) return cls.from_abi(name, address, abi, owner) optimizer = { "enabled": bool(int(data["result"][0]["OptimizationUsed"])), "runs": int(data["result"][0]["Runs"]), } evm_version = data["result"][0].get("EVMVersion", "Default") if evm_version == "Default": evm_version = None if data["result"][0]["SourceCode"].startswith("{"): # source was verified using compiler standard JSON input_json = json.loads(data["result"][0]["SourceCode"][1:-1]) sources = { k: v["content"] for k, v in input_json["sources"].items() } evm_version = input_json["settings"].get("evmVersion", evm_version) compiler.set_solc_version(str(version)) input_json.update( compiler.generate_input_json(sources, optimizer=optimizer, evm_version=evm_version)) output_json = compiler.compile_from_input_json(input_json) build_json = compiler.generate_build_json(input_json, output_json) else: # source was submitted as a single flattened file sources = { f"{name}-flattened.sol": data["result"][0]["SourceCode"] } build_json = compiler.compile_and_format(sources, solc_version=str(version), optimizer=optimizer, evm_version=evm_version) build_json = build_json[name] if as_proxy_for is not None: build_json.update( abi=abi, natspec=implementation_contract._build.get("natspec")) if not _verify_deployed_code(address, build_json["deployedBytecode"], build_json["language"]): warnings.warn( f"{address}: Locally compiled and on-chain bytecode do not match!", BrownieCompilerWarning, ) del build_json["pcMap"] self = cls.__new__(cls) _ContractBase.__init__(self, None, build_json, sources) # type: ignore _DeployedContractBase.__init__(self, address, owner) _add_deployment(self) return self
def solc4json(solc4source): compiler.set_solc_version("0.4.25") input_json = compiler.generate_input_json({'path': solc4source}, True, 200) yield compiler.compile_from_input_json(input_json)