def deploy_new_instance(cls, w3: Web3) -> 'SimpleRegistry': manifest = get_simple_registry_manifest() registry_package = Package(manifest, w3) registry_factory = registry_package.get_contract_factory(ContractName("PackageRegistry")) tx_hash = registry_factory.constructor().transact() tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) return cls(tx_receipt["contractAddress"], w3)
def _deploy( contract_name: str, args: Any, transaction: Dict[str, Any], package: Package ) -> Tuple[Package, Address]: # Deploy new instance factory = package.get_contract_factory(contract_name) if not factory.linked_references and factory.unlinked_references: raise LinkerError( f"Contract factory: {contract_name} is missing runtime link references, which are " "necessary to populate manifest deployments that have a link reference. If using the " "builder tool, use `contract_type(..., runtime_bytecode=True)`." ) tx_hash = factory.constructor(*args).transact(transaction) tx_receipt = package.w3.eth.waitForTransactionReceipt(tx_hash) # Create manifest copy with new deployment instance latest_block_uri = create_latest_block_uri(package.w3, 0) deployment_data = create_deployment_data( contract_name, to_checksum_address(tx_receipt.contractAddress), tx_receipt, factory.linked_references, ) manifest = insert_deployment( package, contract_name, deployment_data, latest_block_uri ) logger.info("%s deployed." % contract_name) return Package(manifest, package.w3)
def deploy_new_instance(cls, w3): manifest = get_simple_registry_manifest() registry_package = Package(manifest, w3) registry_factory = registry_package.get_contract_factory("PackageRegistry") tx_hash = registry_factory.constructor().transact() tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) return cls(tx_receipt.contractAddress, w3)
def _get_factory(package, factory_name): manifest = get_manifest(package) # Special case to fetch escrow manifest with added deployment bytecode if package == "escrow": manifest = escrow_manifest Pkg = Package(manifest, w3) factory = Pkg.get_contract_factory(factory_name) return factory
def test_linkable_contract_class_handles_missing_link_refs(get_manifest, w3): safe_math_manifest = get_manifest("safe-math-lib") SafeMathLib = Package(safe_math_manifest, w3) safe_math_lib = SafeMathLib.get_contract_factory("SafeMathLib") assert safe_math_lib.needs_bytecode_linking is False with pytest.raises(BytecodeLinkingError): safe_math_lib.link_bytecode( {"SafeMathLib": "0xa66A05D6AB5c1c955F4D2c3FCC166AE6300b452B"})
def test_from_file_fails_with_missing_filepath(tmpdir): path = os.path.join( str(tmpdir.mkdir('invalid')), 'package.json', ) assert not os.path.exists(path) with pytest.raises(FileNotFoundError): Package.from_file(path)
def deploy_new_instance(cls, w3: Web3) -> "VyperReferenceRegistry": """ Returns a new instance of ```VyperReferenceRegistry`` representing a freshly deployed instance on the given ``web3`` instance of the Vyper Reference Registry implementation. """ manifest = get_vyper_registry_manifest() registry_package = Package(manifest, w3) registry_factory = registry_package.get_contract_factory("registry") tx_hash = registry_factory.constructor().transact() tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) return cls(tx_receipt.contractAddress, w3)
def test_get_build_dependencies_with_empty_dependencies_raises_exception( dummy_ipfs_backend, piper_coin_manifest, w3 ): piper_coin_manifest["buildDependencies"] = {} pkg = Package(piper_coin_manifest, w3) with pytest.raises(EthPMValidationError, match="Manifest's build dependencies key is empty"): pkg.build_dependencies
def test_github_over_https_backend_fetch_uri_contents(uri, owned_contract, w3): # these tests may occassionally fail CI as a result of their network requests backend = GithubOverHTTPSBackend() assert backend.base_uri == GITHUB_API_AUTHORITY # integration with Package.from_uri owned_package = Package.from_uri(uri, w3) assert owned_package.name == "owned"
def generate_deployments(pkg: ethpmPackage, config: Config) -> Iterable[Tuple[str, Contract]]: for chain in pkg.manifest["deployments"]: w3, chain_name = get_matching_w3(chain, config) new_pkg = pkg.update_w3(w3) for dep in pkg.manifest["deployments"][chain].keys(): yield f"{chain_name}_{dep}", new_pkg.deployments.get_instance(dep)
def test_get_build_dependencies_without_dependencies_raises_exception( piper_coin_manifest, w3 ): piper_coin_manifest.pop("buildDependencies", None) pkg = Package(piper_coin_manifest, w3) with pytest.raises(EthPMValidationError, match="Manifest doesn't have any build dependencies"): pkg.build_dependencies
def test_init_from_valid_package_data(): minimal_package = { "package_name": "foo", "manifest_version": "2", "version": "1.0.0", } Package(minimal_package)
def test_init_from_minimal_valid_manifest(w3): minimal_manifest = { "package_name": "foo", "manifest_version": "2", "version": "1.0.0", } Package(minimal_manifest, w3)
def test_package_init_from_registry(w3_with_registry, monkeypatch): monkeypatch.setenv("ETHPM_IPFS_BACKEND_CLASS", "ethpm.backends.ipfs.DummyIPFSBackend") w3, address, registry = w3_with_registry valid_registry_uri = "ercXXX://%s/owned?version=1.0.0" % address pkg = Package.from_registry(valid_registry_uri, w3) assert isinstance(pkg, Package) assert pkg.name == "safe-math-lib"
def test_init_with_outdated_ethpm_manifest(w3): v2_manifest = { "package_name": "foo", "manifest_version": "2", "version": "1.0.0", } with pytest.raises(EthPMValidationError): Package(v2_manifest, w3)
def test_init_from_minimal_valid_manifest(w3): minimal_manifest = { "name": "foo", "manifest": "ethpm/3", "version": "1.0.0", } Package(minimal_manifest, w3)
def sol_registry(w3): manifest = get_ethpm_local_manifest("simple-registry", "v3.json") registry_package = Package(manifest, w3) registry_deployer = Deployer(registry_package) deployed_registry_package = registry_deployer.deploy("PackageRegistry") assert isinstance(registry_package, Package) registry = deployed_registry_package.deployments.get_instance("PackageRegistry") return SimpleRegistry(registry.address, w3)
def test_deployed_escrow_and_safe_send(escrow_manifest, w3): # Deploy a SafeSendLib safe_send_manifest = json.loads( (ASSETS_DIR / "escrow" / "1.0.3.json").read_text()) safe_send_contract_type = safe_send_manifest["contract_types"][ "SafeSendLib"] SafeSend = w3.eth.contract( abi=safe_send_contract_type["abi"], bytecode=safe_send_contract_type["deployment_bytecode"]["bytecode"], ) tx_hash = SafeSend.constructor().transact() tx_receipt = w3.eth.getTransactionReceipt(tx_hash) safe_send_address = to_canonical_address(tx_receipt["contractAddress"]) EscrowPackage = Package(escrow_manifest, w3) EscrowFactory = EscrowPackage.get_contract_factory("Escrow") LinkedEscrowFactory = EscrowFactory.link_bytecode( {"SafeSendLib": safe_send_address}) # Deploy an Escrow Contract escrow_tx_hash = LinkedEscrowFactory.constructor( "0x4F5B11c860b37b68DE6D14Fb7e7b5f18A9A1bdC0").transact() escrow_tx_receipt = w3.eth.waitForTransactionReceipt(escrow_tx_hash) escrow_address = to_canonical_address(escrow_tx_receipt.contractAddress) # Cannot deploy with an unlinked factory with pytest.raises(BytecodeLinkingError): escrow_tx_hash = EscrowFactory.constructor( "0x4F5B11c860b37b68DE6D14Fb7e7b5f18A9A1bdC0").transact() # Cannot instantiate a contract instance from an unlinked factory with pytest.raises(BytecodeLinkingError): EscrowFactory(escrow_address) contract_instance = LinkedEscrowFactory(escrow_address) assert EscrowFactory.needs_bytecode_linking is True assert LinkedEscrowFactory.needs_bytecode_linking is False assert isinstance(contract_instance, web3.contract.Contract) assert to_canonical_address( safe_send_address) in LinkedEscrowFactory.bytecode assert (to_canonical_address(safe_send_address) in LinkedEscrowFactory.bytecode_runtime) assert to_canonical_address( safe_send_address) not in EscrowFactory.bytecode assert to_canonical_address( safe_send_address) not in EscrowFactory.bytecode_runtime
def generate_contract_factories(pkg: ethpmPackage): for ctype in pkg.contract_types: try: factory = pkg.get_contract_factory(ctype) yield f"{ctype}_factory", factory except InsufficientAssetsError: cli_logger.info( f"Insufficient assets to generate factory for {ctype} " "(requires ABI & deployment_bytecode).")
def vy_registry(w3): registry_path = ASSETS_DIR / "vyper_registry" manifest = json.loads((registry_path / "1.0.0.json").read_text().rstrip('\n')) registry_package = Package(manifest, w3) registry_deployer = Deployer(registry_package) deployed_registry_package = registry_deployer.deploy("registry") registry_instance = deployed_registry_package.deployments.get_instance("registry") assert registry_instance.functions.owner().call() == w3.eth.defaultAccount return VyperReferenceRegistry(to_canonical_address(registry_instance.address), w3)
def get_package_from_manifest(self, manifest: Manifest) -> Package: """ Returns a `Package <https://github.com/ethpm/py-ethpm/blob/master/ethpm/package.py>`__ instance built with the given manifest. * Parameters: * ``manifest``: A dict representing a valid manifest """ return Package(manifest, self.web3)
def sol_registry(w3): manifest = json.loads((ASSETS_DIR / "registry" / "1.0.0.json").read_text()) strategy = solidity_registry_strategy() registry_package = Package(manifest, w3) registry_deployer = Deployer(registry_package) registry_deployer.register_strategy("PackageRegistry", strategy) deployed_registry_package = registry_deployer.deploy("PackageRegistry") assert isinstance(registry_package, Package) registry = deployed_registry_package.deployments.get_instance("PackageRegistry") return SolidityReferenceRegistry(to_canonical_address(registry.address), w3)
def sol_registry(w3): manifest = json.loads( (ASSETS_DIR / "registry" / "2.0.0a1.json").read_text()) registry_package = Package(manifest, w3) registry_deployer = Deployer(registry_package) deployed_registry_package = registry_deployer.deploy("PackageRegistry") assert isinstance(registry_package, Package) registry = deployed_registry_package.deployments.get_instance( "PackageRegistry") return SimpleRegistry(registry.address, w3)
def get_package_from_uri(self, manifest_uri: URI) -> Package: """ Returns a `Package <https://github.com/ethpm/py-ethpm/blob/master/ethpm/package.py>`__ instance built with the Manifest stored at the URI. If you want to use a specific IPFS backend, set ``ETHPM_IPFS_BACKEND_CLASS`` to your desired backend. Defaults to Infura IPFS backend. * Parameters: * ``uri``: Must be a valid content-addressed URI """ return Package.from_uri(manifest_uri, self.web3)
def install(self, uri: str): """ Install packages from chain or files and put it in packages directory. """ self._create_ethpm_packages_dir() self._initialize_w3() is_file = True for prefix in ("ipfs://", "https://", "ethpm://", "erc1319://"): if uri.startswith(prefix): is_file = False break if is_file: package = Package.from_file(Path(uri), self.w3) else: package = Package.from_uri(uri, self.w3) self._write_manifests_to_filesystem(package.name, package.version, package.manifest) self.package = package
def safe_math_lib_package_with_alias(deployer, w3): safe_math_lib_manifest = ASSETS_DIR / "safe-math-lib" / "1.0.1.json" safe_math_deployer = deployer(safe_math_lib_manifest) pkg = safe_math_deployer.deploy("SafeMathLib") blockchain_uri = list(pkg.manifest["deployments"].keys())[0] deployment_data = pkg.manifest["deployments"][blockchain_uri]["SafeMathLib"] aliased_manifest = assoc_in( pkg.manifest, ["deployments", blockchain_uri], {"safe-math-lib-alias": deployment_data}, ) return Package(aliased_manifest, w3)
def link(contract: str, linked_type: str, package: Package) -> Package: """ Return a new package, created with a new manifest after applying the linked type reference to the contract factory. """ deployment_address = get_deployment_address(linked_type, package) unlinked_factory = package.get_contract_factory(contract) if not unlinked_factory.needs_bytecode_linking: raise LinkerError( f"Contract factory: {unlinked_factory.__repr__()} does not need bytecode linking, " "so it is not a valid contract type for link()") linked_factory = unlinked_factory.link_bytecode( {linked_type: deployment_address}) # todo replace runtime_bytecode in manifest manifest = assoc_in( package.manifest, ("contract_types", contract, "deployment_bytecode", "bytecode"), to_hex(linked_factory.bytecode), ) logger.info( "%s linked to %s at address %s." % (contract, linked_type, to_checksum_address(deployment_address))) return Package(manifest, package.w3)
def load(self, contract_factory: str, package: Path, version: str = ""): """ Load an installed package. """ package_path = self.packages_dir / Path(package) versions = list(map(lambda p: p.name, package_path.iterdir())) if not version: version = self.find_max_version(versions) manifest_path = package_path / Path(version) / Path("manifest.json") self._initialize_w3() self.package = Package.from_file(manifest_path, self.w3) factory = self.package.get_contract_factory(contract_factory) factory.web3 = self.w3 return factory
def test_get_deployments_with_multiple_matches_raises_exception( w3, package_with_multiple_matches): package = Package(package_with_multiple_matches) with pytest.raises(ValidationError): package.get_deployments(w3)
def test_get_deployments_with_no_match_raises_exception( w3, package_with_no_matching_deployments): package = Package(package_with_no_matching_deployments) with pytest.raises(ValidationError): package.get_deployments(w3)