Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax ethpm canonical address requirement #1380

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions docs/ethpm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ LinkableContract

.. doctest::

>>> from eth_utils import is_address, to_canonical_address
>>> from eth_utils import is_address
>>> from web3 import Web3
>>> from ethpm import Package, ASSETS_DIR

Expand All @@ -104,7 +104,7 @@ LinkableContract
>>> safe_send_tx_receipt = w3.eth.waitForTransactionReceipt(safe_send_tx_hash)

>>> # Link Escrow factory to deployed SafeSendLib instance
>>> LinkedEscrowFactory = EscrowFactory.link_bytecode({"SafeSendLib": to_canonical_address(safe_send_tx_receipt.contractAddress)})
>>> LinkedEscrowFactory = EscrowFactory.link_bytecode({"SafeSendLib": safe_send_tx_receipt.contractAddress})
>>> assert LinkedEscrowFactory.needs_bytecode_linking is False
>>> escrow_tx_hash = LinkedEscrowFactory.constructor(w3.eth.accounts[0]).transact()
>>> escrow_tx_receipt = w3.eth.waitForTransactionReceipt(escrow_tx_hash)
Expand Down Expand Up @@ -725,7 +725,6 @@ This is the simplest builder function for adding a deployment to a manifest. All

.. doctest::

>>> from eth_utils import to_canonical_address
>>> expected_manifest = {
... 'package_name': 'owned',
... 'manifest_version': '2',
Expand All @@ -734,7 +733,7 @@ This is the simplest builder function for adding a deployment to a manifest. All
... 'blockchain://1234567890123456789012345678901234567890123456789012345678901234/block/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef': {
... 'Owned': {
... 'contract_type': 'Owned',
... 'address': '0x4f5b11c860b37b68de6d14fb7e7b5f18a9a1bd00',
... 'address': '0x4F5B11C860B37B68De6d14FB7e7b5f18A9a1BD00',
... }
... }
... }
Expand All @@ -745,7 +744,7 @@ This is the simplest builder function for adding a deployment to a manifest. All
... block_uri='blockchain://1234567890123456789012345678901234567890123456789012345678901234/block/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
... contract_instance='Owned',
... contract_type='Owned',
... address=to_canonical_address('0x4f5b11c860b37b68de6d14fb7e7b5f18a9a1bd00'),
... address='0x4F5B11C860B37B68De6d14FB7e7b5f18A9a1BD00',
... ),
... )
>>> assert expected_manifest == built_manifest
Expand Down
20 changes: 8 additions & 12 deletions ethpm/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
combomethod,
is_canonical_address,
to_bytes,
to_checksum_address,
to_canonical_address,
)
from eth_utils.toolz import (
assoc,
Expand All @@ -24,10 +24,12 @@
ValidationError,
)
from ethpm.validation.misc import (
validate_address,
validate_empty_bytes,
)
from web3 import Web3
from web3._utils.validation import (
validate_address,
)
from web3.contract import (
Contract,
)
Expand All @@ -49,10 +51,7 @@ def __init__(self, address: bytes, **kwargs: Any) -> None:
"Contract cannot be instantiated until its bytecode is linked."
)
validate_address(address)
# todo: remove automatic checksumming of address once web3 dep is updated in pytest-ethereum
super(LinkableContract, self).__init__(
address=to_checksum_address(address), **kwargs
)
super(LinkableContract, self).__init__(address=address, **kwargs)

@classmethod
def factory(
Expand Down Expand Up @@ -125,11 +124,7 @@ def validate_attr_dict(self, attr_dict: Dict[str, str]) -> None:
"`link_bytecode` on a contract factory."
)
for address in attr_dict.values():
if not is_canonical_address(address):
raise BytecodeLinkingError(
f"Address: {address} as specified in the attr_dict is not "
"a valid canoncial address."
)
validate_address(address)


def is_prelinked_bytecode(bytecode: bytes, link_refs: List[Dict[str, Any]]) -> bool:
Expand Down Expand Up @@ -173,8 +168,9 @@ def apply_link_ref(offset: int, length: int, value: bytes, bytecode: bytes) -> b
except ValidationError:
raise BytecodeLinkingError("Link references cannot be applied to bytecode")

address = value if is_canonical_address(value) else to_canonical_address(value)
new_bytes = (
# Ignore linting error b/c conflict b/w black & flake8
bytecode[:offset] + value + bytecode[offset + length:] # noqa: E201, E203
bytecode[:offset] + address + bytecode[offset + length:] # noqa: E201, E203
)
return new_bytes
6 changes: 1 addition & 5 deletions ethpm/deployments.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
List,
)

from eth_utils import (
to_canonical_address,
)

from ethpm.exceptions import (
ValidationError,
)
Expand Down Expand Up @@ -64,7 +60,7 @@ def get_instance(self, contract_name: str) -> None:
# in case the deployment uses a contract alias
contract_type = self.deployment_data[contract_name]["contract_type"]
factory = self.contract_factories[contract_type]
address = to_canonical_address(self.deployment_data[contract_name]["address"])
address = self.deployment_data[contract_name]["address"]
contract_kwargs = {
"abi": factory.abi,
"bytecode": factory.bytecode,
Expand Down
9 changes: 5 additions & 4 deletions ethpm/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
validate_raw_manifest_format,
)
from ethpm.validation.misc import (
validate_address,
validate_w3_instance,
)
from ethpm.validation.package import (
Expand All @@ -73,6 +72,9 @@
validate_single_matching_uri,
)
from web3 import Web3
from web3._utils.validation import (
validate_address,
)
from web3.eth import (
Contract,
)
Expand Down Expand Up @@ -275,9 +277,8 @@ def get_contract_instance(self, name: ContractName, address: Address) -> Contrac
contract_kwargs = generate_contract_factory_kwargs(
self.manifest["contract_types"][name]
)
canonical_address = to_canonical_address(address)
contract_instance = self.w3.eth.contract(
address=canonical_address, **contract_kwargs
address=address, **contract_kwargs
)
return contract_instance

Expand Down Expand Up @@ -347,7 +348,7 @@ def deployments(self) -> Union["Deployments", Dict[None, None]]:
if linked_deployments:
for deployment_data in linked_deployments.values():
on_chain_bytecode = self.w3.eth.getCode(
to_canonical_address(deployment_data["address"])
deployment_data["address"]
)
unresolved_linked_refs = normalize_linked_references(
deployment_data["runtime_bytecode"]["link_dependencies"]
Expand Down
10 changes: 5 additions & 5 deletions ethpm/tools/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
is_hex,
is_string,
to_bytes,
to_checksum_address,
to_dict,
to_hex,
to_list,
)
from eth_utils.toolz import (
Expand Down Expand Up @@ -62,13 +62,13 @@
from ethpm.validation.manifest import (
validate_manifest_against_schema,
)
from ethpm.validation.misc import (
validate_address,
)
from ethpm.validation.package import (
validate_package_name,
)
from web3 import Web3
from web3._utils.validation import (
validate_address,
)


def build(obj: Dict[str, Any], *fns: Callable[..., Any]) -> Dict[str, Any]:
Expand Down Expand Up @@ -705,7 +705,7 @@ def _build_deployments_object(
Returns a dict with properly formatted deployment data.
"""
yield "contract_type", contract_type
yield "address", to_hex(address)
yield "address", to_checksum_address(address)
if deployment_bytecode:
yield "deployment_bytecode", deployment_bytecode
if compiler:
Expand Down
22 changes: 0 additions & 22 deletions ethpm/validation/misc.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,9 @@
from typing import (
Any,
)

from eth_utils import (
is_address,
is_canonical_address,
)

from ethpm.exceptions import (
ValidationError,
)
from web3 import Web3


def validate_address(address: Any) -> None:
"""
Raise a ValidationError if an address is not canonicalized.
"""
if not is_address(address):
raise ValidationError(f"Expected an address, got: {address}")
if not is_canonical_address(address):
raise ValidationError(
"Py-EthPM library only accepts canonicalized addresses. "
f"{address} is not in the accepted format."
)


def validate_w3_instance(w3: Web3) -> None:
if w3 is None or not isinstance(w3, Web3):
raise ValueError("Package does not have valid web3 instance.")
Expand Down
5 changes: 2 additions & 3 deletions tests/core/pm-module/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from eth_utils import (
function_abi_to_4byte_selector,
to_bytes,
to_canonical_address,
)

from ethpm import (
Expand Down Expand Up @@ -160,7 +159,7 @@ def sol_registry(w3):
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)
return SolidityReferenceRegistry(registry.address, w3)


def vy_registry(w3):
Expand All @@ -171,7 +170,7 @@ def vy_registry(w3):
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)
return VyperReferenceRegistry(registry_instance.address, w3)


def release_packages(registry):
Expand Down
14 changes: 5 additions & 9 deletions tests/core/pm-module/test_pm_init.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import json
import pytest

from eth_utils import (
to_canonical_address,
)

from ethpm import (
Package,
)
Expand Down Expand Up @@ -38,7 +34,7 @@ def test_get_contract_factory_with_valid_owned_manifest(w3):
owned_factory = owned_package.get_contract_factory('Owned')
tx_hash = owned_factory.constructor().transact()
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
owned_address = to_canonical_address(tx_receipt.contractAddress)
owned_address = tx_receipt.contractAddress
owned_instance = owned_package.get_contract_instance("Owned", owned_address)
assert owned_instance.abi == owned_factory.abi

Expand All @@ -49,7 +45,7 @@ def test_get_contract_factory_with_valid_safe_math_lib_manifest(w3):
safe_math_factory = safe_math_package.get_contract_factory("SafeMathLib")
tx_hash = safe_math_factory.constructor().transact()
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
safe_math_address = to_canonical_address(tx_receipt.contractAddress)
safe_math_address = tx_receipt.contractAddress
safe_math_instance = safe_math_package.get_contract_instance("SafeMathLib", safe_math_address)
assert safe_math_instance.functions.safeAdd(1, 2).call() == 3

Expand All @@ -62,12 +58,12 @@ def test_get_contract_factory_with_valid_escrow_manifest(w3):
safe_send_factory = escrow_package.get_contract_factory('SafeSendLib')
safe_send_tx_hash = safe_send_factory.constructor().transact()
safe_send_tx_receipt = w3.eth.waitForTransactionReceipt(safe_send_tx_hash)
safe_send_address = to_canonical_address(safe_send_tx_receipt.contractAddress)
safe_send_address = safe_send_tx_receipt.contractAddress
linked_escrow_factory = escrow_factory.link_bytecode({"SafeSendLib": safe_send_address})
assert linked_escrow_factory.needs_bytecode_linking is False
escrow_tx_hash = linked_escrow_factory.constructor(w3.eth.accounts[0]).transact()
escrow_tx_receipt = w3.eth.waitForTransactionReceipt(escrow_tx_hash)
escrow_address = to_canonical_address(escrow_tx_receipt.contractAddress)
escrow_address = escrow_tx_receipt.contractAddress
escrow_instance = linked_escrow_factory(address=escrow_address)
assert escrow_instance.functions.sender().call() == w3.eth.accounts[0]

Expand All @@ -80,7 +76,7 @@ def test_deploy_a_standalone_package_integration(w3):
# totalSupply = 100
tx_hash = ERC20.constructor(100).transact()
tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
address = to_canonical_address(tx_receipt["contractAddress"])
address = tx_receipt["contractAddress"]
erc20 = w3.eth.contract(address=address, abi=ERC20.abi)
total_supply = erc20.functions.totalSupply().call()
assert total_supply == 100
Expand Down
12 changes: 5 additions & 7 deletions tests/ethpm/integration/test_escrow_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_deployed_escrow_and_safe_send(escrow_manifest, w3):
"0x4F5B11c860b37b68DE6D14Fb7e7b5f18A9A1bdC0"
).transact()
escrow_tx_receipt = w3.eth.waitForTransactionReceipt(escrow_tx_hash)
escrow_address = to_canonical_address(escrow_tx_receipt.contractAddress)
escrow_address = escrow_tx_receipt.contractAddress

# Cannot deploy with an unlinked factory
with pytest.raises(BytecodeLinkingError):
Expand All @@ -53,9 +53,7 @@ def test_deployed_escrow_and_safe_send(escrow_manifest, w3):
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
assert safe_send_address in LinkedEscrowFactory.bytecode
assert safe_send_address in LinkedEscrowFactory.bytecode_runtime
assert safe_send_address not in EscrowFactory.bytecode
assert safe_send_address not in EscrowFactory.bytecode_runtime
8 changes: 2 additions & 6 deletions tests/ethpm/test_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,14 @@
"escrow",
"Escrow",
{
"SafeSendLib": to_canonical_address(
"0x4F5B11c860b37b68DE6D14Fb7e7b5f18A9A1bdC0"
)
"SafeSendLib": "0x4F5B11c860b37b68DE6D14Fb7e7b5f18A9A1bdC0"
},
),
(
"wallet",
"Wallet",
{
"SafeMathLib": to_canonical_address(
"0xa66A05D6AB5c1c955F4D2c3FCC166AE6300b452B"
)
"SafeMathLib": "0xa66A05D6AB5c1c955F4D2c3FCC166AE6300b452B"
},
),
),
Expand Down
3 changes: 1 addition & 2 deletions tests/ethpm/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from eth_utils import (
is_same_address,
to_canonical_address,
)

from ethpm.exceptions import (
Expand All @@ -26,7 +25,7 @@ def deployed_safe_math(safe_math_package, w3):
SafeMath = safe_math_package.get_contract_factory("SafeMathLib")
tx_hash = SafeMath.constructor().transact()
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
return safe_math_package, to_canonical_address(tx_receipt.contractAddress)
return safe_math_package, tx_receipt.contractAddress


def test_package_object_instantiates_with_a_web3_object(all_manifests, w3):
Expand Down
Loading