diff --git a/brownie/network/contract.py b/brownie/network/contract.py index 004a05935..86e872593 100644 --- a/brownie/network/contract.py +++ b/brownie/network/contract.py @@ -33,8 +33,7 @@ UndeployedLibrary, VirtualMachineError, ) -from brownie.project import ethpm -from brownie.project.compiler import compile_and_format +from brownie.project import compiler, ethpm from brownie.typing import AccountsType, TransactionReceiptType from brownie.utils import color @@ -672,32 +671,48 @@ def from_explorer( ) return cls.from_abi(name, address, abi, owner) - sources = {f"{name}-flattened.sol": data["result"][0]["SourceCode"]} 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 - build = compile_and_format( - sources, solc_version=str(version), optimizer=optimizer, evm_version=evm_version - ) - build = build[name] + 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.update(abi=abi, natspec=implementation_contract._build.get("natspec")) + build_json.update(abi=abi, natspec=implementation_contract._build.get("natspec")) - if not _verify_deployed_code(address, build["deployedBytecode"], build["language"]): + 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["pcMap"] + del build_json["pcMap"] self = cls.__new__(cls) - _ContractBase.__init__(self, None, build, sources) # type: ignore + _ContractBase.__init__(self, None, build_json, sources) # type: ignore _DeployedContractBase.__init__(self, address, owner) _add_deployment(self) return self diff --git a/tests/network/contract/test_contract.py b/tests/network/contract/test_contract.py index 229a2a099..df080b296 100644 --- a/tests/network/contract/test_contract.py +++ b/tests/network/contract/test_contract.py @@ -287,9 +287,9 @@ def test_as_proxy_for(network): original = Contract.from_explorer("0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b") proxy = Contract.from_explorer( "0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b", - as_proxy_for="0x97BD4Cc841FC999194174cd1803C543247a014fe", + as_proxy_for="0x9d0a0443ff4bb04391655b8cd205683d9fa75550", ) - implementation = Contract("0x97BD4Cc841FC999194174cd1803C543247a014fe") + implementation = Contract("0x9d0a0443ff4bb04391655b8cd205683d9fa75550") assert original.abi == proxy.abi assert original.address == proxy.address