diff --git a/docs/middleware.rst b/docs/middleware.rst index e094792a0e..82a171da83 100644 --- a/docs/middleware.rst +++ b/docs/middleware.rst @@ -40,6 +40,11 @@ AttributeDict address that the name points to. For example :meth:`~web3.Eth.sendTransaction` will accept .eth names in the 'from' and 'to' fields. +.. note:: + This middleware only converts ENS names if invoked with the mainnet + (where the ENS contract is deployed), for all other cases will result in an + ``InvalidAddress`` error + Pythonic ~~~~~~~~~~~~ diff --git a/tests/core/middleware/test_name_to_address_middleware.py b/tests/core/middleware/test_name_to_address_middleware.py new file mode 100644 index 0000000000..b6e4408893 --- /dev/null +++ b/tests/core/middleware/test_name_to_address_middleware.py @@ -0,0 +1,56 @@ +import pytest + +from web3 import Web3 +from web3.exceptions import ( + InvalidAddress, +) +from web3.middleware import ( # noqa: F401 + construct_fixture_middleware, + name_to_address_middleware, +) +from web3.providers.base import ( + BaseProvider, +) + +NAME = "dump.eth" +ADDRESS = "0x0000000000000000000000000000000000000000" +BALANCE = 0 + + +class TempENS(): + def __init__(self, name_addr_pairs): + self.registry = dict(name_addr_pairs) + + def address(self, name, guess_tld=True): + # no automated web3 usages should be guessing the TLD + assert not guess_tld + return self.registry.get(name, None) + + +@pytest.fixture +def w3(): + w3 = Web3(providers=[BaseProvider()], middlewares=[]) + w3.ens = TempENS({NAME: ADDRESS}) + w3.middleware_stack.add(name_to_address_middleware(w3)) + return w3 + + +def test_pass_name_resolver(w3): + return_chain_on_mainnet = construct_fixture_middleware({ + 'net_version': '1', + }) + return_balance = construct_fixture_middleware({ + 'eth_getBalance': BALANCE + }) + w3.middleware_stack.inject(return_chain_on_mainnet, layer=0) + w3.middleware_stack.inject(return_balance, layer=0) + assert w3.eth.getBalance(NAME) == BALANCE + + +def test_fail_name_resolver(w3): + return_chain_on_mainnet = construct_fixture_middleware({ + 'net_version': '2', + }) + w3.middleware_stack.inject(return_chain_on_mainnet, layer=0) + with pytest.raises(InvalidAddress, match='.*ethereum\.eth.*'): + w3.eth.getBalance("ethereum.eth") diff --git a/web3/utils/normalizers.py b/web3/utils/normalizers.py index e80a0deaba..3e7dedbd5c 100644 --- a/web3/utils/normalizers.py +++ b/web3/utils/normalizers.py @@ -31,6 +31,7 @@ to_text, ) from web3.utils.ens import ( + StaticENS, is_ens_name, validate_name_has_address, ) @@ -134,9 +135,20 @@ def abi_address_to_hex(abi_type, data): def abi_ens_resolver(w3, abi_type, val): if abi_type == 'address' and is_ens_name(val): if w3 is None: - raise InvalidAddress("Could not look up name, because no web3 connection available") + raise InvalidAddress( + "Could not look up name %r because no web3" + " connection available" % (val) + ) elif w3.ens is None: - raise InvalidAddress("Could not look up name, because ENS is set to None") + raise InvalidAddress( + "Could not look up name %r because ENS is" + " set to None" % (val) + ) + elif int(w3.net.version) is not 1 and not isinstance(w3.ens, StaticENS): + raise InvalidAddress( + "Could not look up name %r because web3 is" + " not connected to mainnet" % (val) + ) else: return (abi_type, validate_name_has_address(w3.ens, val)) else: