Repository: ethereum/web3.py

Issue:
Support ENS multicoin EIP-2304
* Version: 5.11.1
* Python: 3.7
* OS: osx/linux/win

[ENS PublicResolver](https://docs.ens.domains/contract-api-reference/publicresolver)
[EIP-2304](https://eips.ethereum.org/EIPS/eip-2304)

`RESOLVER` would require something like this:
```python
  {
      "constant": True,
      "inputs": [
          {
              "name": "node",
              "type": "bytes32"
          },
          {
              "name": "coinType",
              "type": "uint256"
          },
      ],
      "name": "addr",
      "outputs": [
          {
              "name": "ret",
              "type": "bytes"
          }
      ],
      "payable": False,
      "type": "function"
  },
```

[bruno.eth](https://app.ens.domains/name/bruno.eth) is an ENS domain with multiple coins set up.

By calling `addr(bytes32, unit256)` on its public resolver with:
- bytes32: `0x9de0b76f3b87380f0bcb9e41b403c69b88b01fbeaf785e83f38a6879902af71b`
- uint256: `434`

You should expect:
- bytes: `0x0aff6865635ae11013a83835c019d44ec3f865145943f487ae82a8e7bed3a66b`

Thanks

Discussion:

Patch:
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 565efbe6..d9058ca6 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 6.6.0
+current_version = 6.6.1
 commit = True
 tag = True
 parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(-(?P<stage>[^.]*)\.(?P<devnum>\d+))?
diff --git a/MANIFEST.in b/MANIFEST.in
index 7375aea9..a5b084e7 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -6,6 +6,8 @@ include requirements.txt
 recursive-exclude * __pycache__
 recursive-exclude * *.py[co]
 
+recursive-include ens/specs *
+
 recursive-include ethpm/assets/ *
 recursive-include ethpm/ethpm-spec/examples *
 recursive-include ethpm/ethpm-spec/spec *
diff --git a/docs/ens_overview.rst b/docs/ens_overview.rst
index 97b41175..50995592 100644
--- a/docs/ens_overview.rst
+++ b/docs/ens_overview.rst
@@ -162,9 +162,26 @@ Get the Address for an ENS Name
     eth_address = ns.address('ens.eth')
     assert eth_address == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
 
-The ``ENS`` module has no opinion as to which TLD you can use,
+The ``ENS`` module has no opinion as to which **TLD (Top Level Domain)** you can use,
 but will not infer a TLD if it is not provided with the name.
 
+Multichain Address Resolution
++++++++++++++++++++++++++++++
+
+`ENSIP-9 <https://docs.ens.domains/ens-improvement-proposals/ensip-9-multichain-address-resolution>`_
+introduced multichain address resolution, allowing users to resolve addresses from
+different chains, specified by the coin type index from
+`SLIP44 <https://github.com/satoshilabs/slips/blob/master/slip-0044.md>`_. The
+``address()`` method on the ``ENS`` class supports multichain address resolution via
+the ``coin_type`` keyword argument.
+
+.. code-block:: python
+
+    from ens.auto import ns
+    eth_address = ns.address('ens.eth', coin_type=60)  # ETH is coin_type 60
+    assert eth_address == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
+
+
 Get the ENS Name for an Address
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -226,6 +243,22 @@ You can claim arbitrarily deep subdomains.
 
 .. warning:: Gas costs scale up with the number of subdomains!
 
+Multichain Address Support
+++++++++++++++++++++++++++
+
+`ENSIP-9 <https://docs.ens.domains/ens-improvement-proposals/ensip-9-multichain-address-resolution>`_
+introduced multichain address resolution, allowing users to resolve addresses from
+different chains, specified by the coin type index from
+`SLIP44 <https://github.com/satoshilabs/slips/blob/master/slip-0044.md>`_. The
+``setup_address()`` method on the ``ENS`` class supports multichain address setup
+via the ``coin_type`` keyword argument.
+
+.. code-block:: python
+
+    from ens.auto import ns
+    ns.setup_address('ens.eth', coin_type=60)  # ETH is coin_type 60
+    assert ns.address('ens.eth', coin_type=60) == '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7'
+
 Link an Address to a Name
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/docs/releases.rst b/docs/releases.rst
index 440933a4..e7d24432 100644
--- a/docs/releases.rst
+++ b/docs/releases.rst
@@ -4,11 +4,27 @@ Release Notes
 v6 Breaking Changes Summary
    See the :ref:`v6 Migration Guide<migrating_v5_to_v6>`
 
+.. note::
+   web3.py v5 support will end on August 31, 2023.
+   See issue `#3044 <https://github.com/ethereum/web3.py/issues/3044>`__
+
 .. towncrier release notes start
 
+web3.py v6.6.1 (2023-07-12)
+---------------------------
+
+Bugfixes
+~~~~~~~~
+
+- Add ``ens/specs`` to MANIFEST.in (`#3039 <https://github.com/ethereum/web3.py/issues/3039>`__)
+
+
 web3.py v6.6.0 (2023-07-12)
 ---------------------------
 
+**Note: This release was missing the required ``ens/specs`` directory, so it was yanked
+from Pypi in favor of v6.6.1**
+
 Breaking Changes
 ~~~~~~~~~~~~~~~~
 
@@ -18,7 +34,7 @@ Breaking Changes
 Bugfixes
 ~~~~~~~~
 
-- Handle `None` in the formatting middleware (`#2546 <https://github.com/ethereum/web3.py/issues/2546>`__)
+- Handle ``None`` in the formatting middleware (`#2546 <https://github.com/ethereum/web3.py/issues/2546>`__)
 - Fix for a possible bug in ``construct_sign_and_send_raw_middleware`` where the signed transaction was sent as bytes and expected to be converted to hex by formatting later on. It is now explicitly sent as the hex string hash within the middleware. (`#2936 <https://github.com/ethereum/web3.py/issues/2936>`__)
 - Fixes ``max_priority_fee_per_gas``. It wasn't falling back to ``eth_feeHistory`` since the ``MethodUnavailable`` error was introduced. (`#3002 <https://github.com/ethereum/web3.py/issues/3002>`__)
 - Properly initialize logger in ``AsyncHTTPProvider``. (`#3026 <https://github.com/ethereum/web3.py/issues/3026>`__)
@@ -41,7 +57,7 @@ Features
 
 - Update ENS Resolver ABI (`#1839 <https://github.com/ethereum/web3.py/issues/1839>`__)
 - ``async_http_retry_request_middleware``, an async http request retry middleware for ``AsyncHTTPProvider``. (`#3009 <https://github.com/ethereum/web3.py/issues/3009>`__)
-- Add `eth_getStorageAt()` support for ``EthereumTesterProvider``. (`#3011 <https://github.com/ethereum/web3.py/issues/3011>`__)
+- Add ``eth_getStorageAt()`` support for ``EthereumTesterProvider``. (`#3011 <https://github.com/ethereum/web3.py/issues/3011>`__)
 - Add async support for ENS name-to-address resolution via ``async_name_to_address_middleware``. (`#3012 <https://github.com/ethereum/web3.py/issues/3012>`__)
 - Add async support for the sign-and-send raw transaction middleware via ``construct_async_sign_and_send_raw_middleware()``. (`#3025 <https://github.com/ethereum/web3.py/issues/3025>`__)
 
diff --git a/ens/async_ens.py b/ens/async_ens.py
index f52883a2..48a2646a 100644
--- a/ens/async_ens.py
+++ b/ens/async_ens.py
@@ -3,6 +3,7 @@ from copy import (
 )
 from typing import (
     TYPE_CHECKING,
+    Any,
     Optional,
     Sequence,
     Tuple,
@@ -37,9 +38,10 @@ from ens.base_ens import (
 )
 from ens.constants import (
     EMPTY_ADDR_HEX,
+    ENS_EXTENDED_RESOLVER_INTERFACE_ID,
     ENS_MAINNET_ADDR,
-    EXTENDED_RESOLVER_INTERFACE_ID,
-    GET_TEXT_INTERFACE_ID,
+    ENS_MULTICHAIN_ADDRESS_INTERFACE_ID,
+    ENS_TEXT_INTERFACE_ID,
     REVERSE_REGISTRAR_DOMAIN,
 )
 from ens.exceptions import (
@@ -64,8 +66,9 @@ from ens.utils import (
 )
 
 if TYPE_CHECKING:
-    from web3.contract import (  # noqa: F401
+    from web3.contract.async_contract import (  # noqa: F401
         AsyncContract,
+        AsyncContractFunction,
     )
     from web3.main import AsyncWeb3  # noqa: F401
     from web3.providers import (  # noqa: F401
@@ -134,14 +137,32 @@ class AsyncENS(BaseENS):
 
         return ns
 
-    async def address(self, name: str) -> Optional[ChecksumAddress]:
+    async def address(
+        self,
+        name: str,
+        coin_type: Optional[int] = None,
+    ) -> Optional[ChecksumAddress]:
         """
         Look up the Ethereum address that `name` currently points to.
 
         :param str name: an ENS name to look up
+        :param int coin_type: if provided, look up the address for this coin type
         :raises InvalidName: if `name` has invalid syntax
         """
-        return cast(ChecksumAddress, await self._resolve(name, "addr"))
+        r = await self.resolver(name)
+        if coin_type is None:
+            # don't validate `addr(bytes32)` interface id since extended resolvers
+            # can implement a "resolve" function as of ENSIP-10
+            return cast(ChecksumAddress, await self._resolve(name, "addr"))
+        else:
+            await _async_validate_resolver_and_interface_id(
+                name, r, ENS_MULTICHAIN_ADDRESS_INTERFACE_ID, "addr(bytes32,uint256)"
+            )
+            node = raw_name_to_hash(name)
+            address_as_bytes = await r.caller.addr(node, coin_type)
+            if is_none_or_zero_address(address_as_bytes):
+                return None
+            return to_checksum_address(address_as_bytes)
 
     async def setup_address(
         self,
@@ -149,6 +170,7 @@ class AsyncENS(BaseENS):
         address: Union[Address, ChecksumAddress, HexAddress] = cast(
             ChecksumAddress, default
         ),
+        coin_type: Optional[int] = None,
         transact: Optional["TxParams"] = None,
     ) -> Optional[HexBytes]:
         """
@@ -164,6 +186,7 @@ class AsyncENS(BaseENS):
         :param str address: name will point to this address, in checksum format.
             If ``None``, erase the record. If not specified, name will point
             to the owner's address.
+        :param int coin_type: if provided, set up the address for this coin type
         :param dict transact: the transaction configuration, like in
             :meth:`~web3.eth.Eth.send_transaction`
         :raises InvalidName: if ``name`` has invalid syntax
@@ -189,9 +212,14 @@ class AsyncENS(BaseENS):
         transact["from"] = owner
 
         resolver: "AsyncContract" = await self._set_resolver(name, transact=transact)
-        return await resolver.functions.setAddr(
-            raw_name_to_hash(name), address
-        ).transact(transact)
+        node = raw_name_to_hash(name)
+
+        if coin_type is None:
+            return await resolver.functions.setAddr(node, address).transact(transact)
+        else:
+            return await resolver.functions.setAddr(node, coin_type, address).transact(
+                transact
+            )
 
     async def name(self, address: ChecksumAddress) -> Optional[str]:
         """
@@ -222,7 +250,7 @@ class AsyncENS(BaseENS):
         `name` when supplied with `address`.
 
         :param str name: ENS name that address will point to
-        :param str address: to set up, in checksum format
+        :param str address: address to set up, in checksum format
         :param dict transact: the transaction configuration, like in
             :meth:`~web3.eth.send_transaction`
         :raises AddressMismatch: if the name does not already point to the address
@@ -342,6 +370,8 @@ class AsyncENS(BaseENS):
         reversed_domain = address_to_reverse_domain(target_address)
         return await self.resolver(reversed_domain)
 
+    # -- text records -- #
+
     async def get_text(self, name: str, key: str) -> str:
         """
         Get the value of a text record by key from an ENS name.
@@ -357,18 +387,10 @@ class AsyncENS(BaseENS):
         node = raw_name_to_hash(name)
 
         r = await self.resolver(name)
-        if r:
-            if await _async_resolver_supports_interface(r, GET_TEXT_INTERFACE_ID):
-                return await r.caller.text(node, key)
-            else:
-                raise UnsupportedFunction(
-                    f"Resolver for name {name} does not support `text` function."
-                )
-        else:
-            raise ResolverNotFound(
-                f"No resolver found for name `{name}`. It is likely the name "
-                "contains an unsupported top level domain (tld)."
-            )
+        await _async_validate_resolver_and_interface_id(
+            name, r, ENS_TEXT_INTERFACE_ID, "text"
+        )
+        return await r.caller.text(node, key)
 
     async def set_text(
         self,
@@ -381,7 +403,7 @@ class AsyncENS(BaseENS):
         Set the value of a text record of an ENS name.
 
         :param str name: ENS name
-        :param str key: Name of the attribute to set
+        :param str key: The name of the attribute to set
         :param str value: Value to set the attribute to
         :param dict transact: The transaction configuration, like in
             :meth:`~web3.eth.Eth.send_transaction`
@@ -391,30 +413,17 @@ class AsyncENS(BaseENS):
             the "0x59d1d43c" interface id
         :raises ResolverNotFound: If no resolver is found for the provided name
         """
-        if not transact:
-            transact = {}
-
-        owner = await self.owner(name)
+        r = await self.resolver(name)
+        await _async_validate_resolver_and_interface_id(
+            name, r, ENS_TEXT_INTERFACE_ID, "setText"
+        )
         node = raw_name_to_hash(name)
-        normal_name = normalize_name(name)
 
-        transaction_dict = merge({"from": owner}, transact)
+        return await self._set_property(
+            name, r.functions.setText, (node, key, value), transact
+        )
 
-        r = await self.resolver(normal_name)
-        if r:
-            if await _async_resolver_supports_interface(r, GET_TEXT_INTERFACE_ID):
-                return await r.functions.setText(node, key, value).transact(
-                    transaction_dict
-                )
-            else:
-                raise UnsupportedFunction(
-                    f"Resolver for name `{name}` does not support `text` function"
-                )
-        else:
-            raise ResolverNotFound(
-                f"No resolver found for name `{name}`. It is likely the name contains "
-                "an unsupported top level domain (tld)."
-            )
+    # -- private methods -- #
 
     async def _get_resolver(
         self,
@@ -477,7 +486,7 @@ class AsyncENS(BaseENS):
 
         # handle extended resolver case
         if await _async_resolver_supports_interface(
-            resolver, EXTENDED_RESOLVER_INTERFACE_ID
+            resolver, ENS_EXTENDED_RESOLVER_INTERFACE_ID
         ):
             contract_func_with_args = (fn_name, [node])
 
@@ -568,11 +577,44 @@ class AsyncENS(BaseENS):
         )
         return self.w3.eth.contract(address=addr, abi=abis.REVERSE_REGISTRAR)
 
+    async def _set_property(
+        self,
+        name: str,
+        func: "AsyncContractFunction",
+        args: Sequence[Any],
+        transact: "TxParams" = None,
+    ) -> HexBytes:
+        if not transact:
+            transact = {}
+
+        owner = await self.owner(name)
+        transact_from_owner = merge({"from": owner}, transact)
+
+        return await func(*args).transact(transact_from_owner)
+
 
 async def _async_resolver_supports_interface(
     resolver: "AsyncContract",
     interface_id: HexStr,
 ) -> bool:
-    if not any("supportsInterface" in repr(func) for func in resolver.all_functions()):
-        return False
-    return await resolver.caller.supportsInterface(interface_id)
+    return any(
+        "supportsInterface" in repr(func) for func in resolver.all_functions()
+    ) and await resolver.caller.supportsInterface(interface_id)
+
+
+async def _async_validate_resolver_and_interface_id(
+    ens_name: str,
+    resolver: "AsyncContract",
+    ens_interface_id: HexStr,
+    interface_name: str,
+) -> None:
+    if not resolver:
+        raise ResolverNotFound(
+            f"No resolver found for name `{ens_name}`. It is likely the name "
+            "contains an unsupported top level domain (tld)."
+        )
+    elif not await _async_resolver_supports_interface(resolver, ens_interface_id):
+        raise UnsupportedFunction(
+            f"Resolver for name `{ens_name}` does not support the `{interface_name}` "
+            f"interface."
+        )
diff --git a/ens/constants.py b/ens/constants.py
index 50f812a3..c2415f36 100644
--- a/ens/constants.py
+++ b/ens/constants.py
@@ -24,5 +24,11 @@ ENS_MAINNET_ADDR = ChecksumAddress(
 
 # --- interface ids --- #
 
-GET_TEXT_INTERFACE_ID = HexStr("0x59d1d43c")
-EXTENDED_RESOLVER_INTERFACE_ID = HexStr("0x9061b923")  # ENSIP-10
+ENS_ADDR_INTERFACE_ID = HexStr("0x3b3b57de")
+ENS_NAME_INTERFACE_ID = HexStr("0x691f3431")
+ENS_ABI_INTERFACE_ID = HexStr("0x2203ab56")
+ENS_PUBLIC_KEY_INTERFACE_ID = HexStr("0xc8690233")
+ENS_TEXT_INTERFACE_ID = HexStr("0x59d1d43c")
+ENS_CONTENT_HASH_INTERFACE_ID = HexStr("0xbc1c58d1")
+ENS_MULTICHAIN_ADDRESS_INTERFACE_ID = HexStr("0xf1cb7e06")  # ENSIP-9
+ENS_EXTENDED_RESOLVER_INTERFACE_ID = HexStr("0x9061b923")  # ENSIP-10
diff --git a/ens/contract_data.py b/ens/contract_data.py
index a0a52556..051a17ca 100644
--- a/ens/contract_data.py
+++ b/ens/contract_data.py
@@ -1,6 +1,14 @@
 # flake8: noqa
 import json
 
+"""
+This contract data is taken from the actual ENS contracts deployed on mainnet.
+The information was taken from etherscan.io and may need to be updated as the ENS 
+contracts are updated. 
+
+https://etherscan.io/accounts/label/ens
+"""
+
 # ENS Default Registrar
 registrar_abi = json.loads(
     '[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"},{"internalType":"bytes32","name":"_baseNode","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"}],"name":"ControllerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"}],"name":"ControllerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expires","type":"uint256"}],"name":"NameRenewed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"GRACE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"addController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"available","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"baseNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"controllers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ens","outputs":[{"internalType":"contract ENS","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"nameExpires","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"reclaim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"register","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"registerOnly","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"removeController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"renew","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]'
@@ -27,25 +35,3 @@ reverse_resolver_abi = json.loads(
 )
 reverse_resolver_bytecode = "608060405234801561001057600080fd5b5060405160208061079f8339810180604052602081101561003057600080fd5b8101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be37f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e26001026040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082815260200191505060206040518083038186803b15801561013457600080fd5b505afa158015610148573d6000803e3d6000fd5b505050506040513d602081101561015e57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151561027f578073ffffffffffffffffffffffffffffffffffffffff16631e83409a336040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561024257600080fd5b505af1158015610256573d6000803e3d6000fd5b505050506040513d602081101561026c57600080fd5b8101908080519060200190929190505050505b505061050f806102906000396000f3fe608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633f15457f1461005c578063691f3431146100b35780637737221314610167575b600080fd5b34801561006857600080fd5b50610071610239565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100bf57600080fd5b506100ec600480360360208110156100d657600080fd5b810190808035906020019092919050505061025e565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561012c578082015181840152602081019050610111565b50505050905090810190601f1680156101595780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561017357600080fd5b506102376004803603604081101561018a57600080fd5b8101908080359060200190929190803590602001906401000000008111156101b157600080fd5b8201836020820111156101c357600080fd5b803590602001918460018302840111640100000000831117156101e557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061030e565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103065780601f106102db57610100808354040283529160200191610306565b820191906000526020600020905b8154815290600101906020018083116102e957829003601f168201915b505050505081565b816000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3826040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082815260200191505060206040518083038186803b15801561039d57600080fd5b505afa1580156103b1573d6000803e3d6000fd5b505050506040513d60208110156103c757600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561041157600080fd5b8160016000858152602001908152602001600020908051906020019061043892919061043e565b50505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061047f57805160ff19168380011785556104ad565b828001600101855582156104ad579182015b828111156104ac578251825591602001919060010190610491565b5b5090506104ba91906104be565b5090565b6104e091905b808211156104dc5760008160009055506001016104c4565b5090565b9056fea165627a7a72305820f326fd97e1fac0bcd89f007846301e41c2ad494c12d70b2b50dd61e62ffc906a0029"
 reverse_resolver_bytecode_runtime = "608060405234801561001057600080fd5b506004361061004c5760003560e01c806301ffc9a7146100515780633e9ce794146100815780639061b9231461009d578063f86bc879146100cd575b600080fd5b61006b6004803603810190610066919061051e565b6100fd565b6040516100789190610566565b60405180910390f35b61009b60048036038101906100969190610641565b61015e565b005b6100b760048036038101906100b291906106f9565b610245565b6040516100c49190610813565b60405180910390f35b6100e760048036038101906100e29190610835565b61042f565b6040516100f49190610566565b60405180910390f35b6000639061b92360e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061015757506101568261046b565b5b9050919050565b806001600085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fe1c5610a6e0cbe10764ecd182adcef1ec338dc4e199c99c32ce98f38e12791df8333848460405161023894939291906108a6565b60405180910390a1505050565b60606040518060400160405280601781526020017f11657874656e6465642d7265736f6c766572036574680000000000000000000081525080519060200120858560405161029492919061092a565b60405180910390201480156102ad575060248383905010155b15610328577ff0a378cc2afe91730d0105e67d6bb037cc5b8b6bfec5b5962d9b637ff6497e5560001b83836004906024926102ea9392919061094d565b906102f591906109a0565b146102ff57600080fd5b61beef60405160200161031291906109ff565b6040516020818303038152906040529050610427565b60008585600081811061033e5761033d610a1a565b5b9050013560f81c60f81b60f81c60ff1690506040518060400160405280601781526020017f11657874656e6465642d7265736f6c766572036574680000000000000000000081525080519060200120868683600161039c9190610a82565b9080926103ab9392919061094d565b6040516103b9929190610ad8565b604051809103902014610401576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f890610b28565b60405180910390fd5b61dead60405160200161041491906109ff565b6040516020818303038152906040529150505b949350505050565b6001602052826000526040600020602052816000526040600020602052806000526040600020600092509250509054906101000a900460ff1681565b60006301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6104fb816104c6565b811461050657600080fd5b50565b600081359050610518816104f2565b92915050565b600060208284031215610534576105336104bc565b5b600061054284828501610509565b91505092915050565b60008115159050919050565b6105608161054b565b82525050565b600060208201905061057b6000830184610557565b92915050565b6000819050919050565b61059481610581565b811461059f57600080fd5b50565b6000813590506105b18161058b565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006105e2826105b7565b9050919050565b6105f2816105d7565b81146105fd57600080fd5b50565b60008135905061060f816105e9565b92915050565b61061e8161054b565b811461062957600080fd5b50565b60008135905061063b81610615565b92915050565b60008060006060848603121561065a576106596104bc565b5b6000610668868287016105a2565b935050602061067986828701610600565b925050604061068a8682870161062c565b9150509250925092565b600080fd5b600080fd5b600080fd5b60008083601f8401126106b9576106b8610694565b5b8235905067ffffffffffffffff8111156106d6576106d5610699565b5b6020830191508360018202830111156106f2576106f161069e565b5b9250929050565b60008060008060408587031215610713576107126104bc565b5b600085013567ffffffffffffffff811115610731576107306104c1565b5b61073d878288016106a3565b9450945050602085013567ffffffffffffffff8111156107605761075f6104c1565b5b61076c878288016106a3565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60005b838110156107b4578082015181840152602081019050610799565b838111156107c3576000848401525b50505050565b6000601f19601f8301169050919050565b60006107e58261077a565b6107ef8185610785565b93506107ff818560208601610796565b610808816107c9565b840191505092915050565b6000602082019050818103600083015261082d81846107da565b905092915050565b60008060006060848603121561084e5761084d6104bc565b5b600061085c868287016105a2565b935050602061086d86828701610600565b925050604061087e86828701610600565b9150509250925092565b61089181610581565b82525050565b6108a0816105d7565b82525050565b60006080820190506108bb6000830187610888565b6108c86020830186610897565b6108d56040830185610897565b6108e26060830184610557565b95945050505050565b600081905092915050565b82818337600083830152505050565b600061091183856108eb565b935061091e8385846108f6565b82840190509392505050565b6000610937828486610905565b91508190509392505050565b600080fd5b600080fd5b6000808585111561096157610960610943565b5b8386111561097257610971610948565b5b6001850283019150848603905094509492505050565b600082905092915050565b600082821b905092915050565b60006109ac8383610988565b826109b78135610581565b925060208210156109f7576109f27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83602003600802610993565b831692505b505092915050565b6000602082019050610a146000830184610897565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610a8d82610a49565b9150610a9883610a49565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610acd57610acc610a53565b5b828201905092915050565b6000610ae5828486610905565b91508190509392505050565b600082825260208201905092915050565b50565b6000610b12600083610af1565b9150610b1d82610b02565b600082019050919050565b60006020820190508181036000830152610b4181610b05565b905091905056fea264697066735822122053f3072486d953b17f72555d93bae38d3607f573e572c03ca3b10c082471640064736f6c634300080d0033"
-
-# ENSIP-10 - Extended Resolver for Wildcard Resolution
-# compiled from `web3/_utils/contract_sources/ExtendedResolver.sol`
-extended_resolver_abi = '[{"inputs": [{"internalType": "contract ENS","name": "_ens","type": "address"}],"stateMutability": "nonpayable","type": "constructor"},{"anonymous": false,"inputs": [{"indexed": false,"internalType": "bytes32","name": "node","type": "bytes32"},{"indexed": false,"internalType": "address","name": "owner","type": "address"},{"indexed": false,"internalType": "address","name": "target","type": "address"},{"indexed": false,"internalType": "bool","name": "isAuthorised","type": "bool"}],"name": "AuthorisationChanged","type": "event"},{"inputs": [{"internalType": "bytes32", "name": "", "type": "bytes32"},{"internalType": "address", "name": "", "type": "address"},{"internalType": "address", "name": "", "type": "address"}],"name": "authorisations","outputs": [{"internalType": "bool", "name": "", "type": "bool"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes", "name": "dnsName", "type": "bytes"},{"internalType": "bytes", "name": "data", "type": "bytes"}],"name": "resolve","outputs": [{"internalType": "bytes", "name": "", "type": "bytes"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "bytes32", "name": "node", "type": "bytes32"},{"internalType": "address", "name": "target", "type": "address"},{"internalType": "bool", "name": "isAuthorised", "type": "bool"}],"name": "setAuthorisation","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [{"internalType": "bytes4","name": "interfaceID","type": "bytes4"}],"name": "supportsInterface","outputs": [{"internalType": "bool", "name": "", "type": "bool"}],"stateMutability": "pure","type": "function"}]'
-extended_resolver_bytecode = "608060405234801561001057600080fd5b50604051610dbb380380610dbb833981810160405281019061003291906100ed565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505061011a565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a88261007d565b9050919050565b60006100ba8261009d565b9050919050565b6100ca816100af565b81146100d557600080fd5b50565b6000815190506100e7816100c1565b92915050565b60006020828403121561010357610102610078565b5b6000610111848285016100d8565b91505092915050565b610c92806101296000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806301ffc9a7146100515780633e9ce794146100815780639061b9231461009d578063f86bc879146100cd575b600080fd5b61006b60048036038101906100669190610554565b6100fd565b604051610078919061059c565b60405180910390f35b61009b60048036038101906100969190610677565b61015e565b005b6100b760048036038101906100b2919061072f565b610245565b6040516100c49190610849565b60405180910390f35b6100e760048036038101906100e2919061086b565b610465565b6040516100f4919061059c565b60405180910390f35b6000639061b92360e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101575750610156826104a1565b5b9050919050565b806001600085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fe1c5610a6e0cbe10764ecd182adcef1ec338dc4e199c99c32ce98f38e12791df8333848460405161023894939291906108dc565b60405180910390a1505050565b60606040518060400160405280601781526020017f11657874656e6465642d7265736f6c7665720365746800000000000000000000815250805190602001208585604051610294929190610960565b60405180910390201480156102ad575060248383905010155b1561035e577ff0a378cc2afe91730d0105e67d6bb037cc5b8b6bfec5b5962d9b637ff6497e5560001b83836004906024926102ea93929190610983565b906102f591906109d6565b14610335576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032c90610ab8565b60405180910390fd5b61beef6040516020016103489190610ad8565b604051602081830303815290604052905061045d565b60008585600081811061037457610373610af3565b5b9050013560f81c60f81b60f81c60ff1690506040518060400160405280601781526020017f11657874656e6465642d7265736f6c76657203657468000000000000000000008152508051906020012086868360016103d29190610b5b565b9080926103e193929190610983565b6040516103ef929190610bb1565b604051809103902014610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90610c3c565b60405180910390fd5b61dead60405160200161044a9190610ad8565b6040516020818303038152906040529150505b949350505050565b6001602052826000526040600020602052816000526040600020602052806000526040600020600092509250509054906101000a900460ff1681565b60006301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610531816104fc565b811461053c57600080fd5b50565b60008135905061054e81610528565b92915050565b60006020828403121561056a576105696104f2565b5b60006105788482850161053f565b91505092915050565b60008115159050919050565b61059681610581565b82525050565b60006020820190506105b1600083018461058d565b92915050565b6000819050919050565b6105ca816105b7565b81146105d557600080fd5b50565b6000813590506105e7816105c1565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610618826105ed565b9050919050565b6106288161060d565b811461063357600080fd5b50565b6000813590506106458161061f565b92915050565b61065481610581565b811461065f57600080fd5b50565b6000813590506106718161064b565b92915050565b6000806000606084860312156106905761068f6104f2565b5b600061069e868287016105d8565b93505060206106af86828701610636565b92505060406106c086828701610662565b9150509250925092565b600080fd5b600080fd5b600080fd5b60008083601f8401126106ef576106ee6106ca565b5b8235905067ffffffffffffffff81111561070c5761070b6106cf565b5b602083019150836001820283011115610728576107276106d4565b5b9250929050565b60008060008060408587031215610749576107486104f2565b5b600085013567ffffffffffffffff811115610767576107666104f7565b5b610773878288016106d9565b9450945050602085013567ffffffffffffffff811115610796576107956104f7565b5b6107a2878288016106d9565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60005b838110156107ea5780820151818401526020810190506107cf565b838111156107f9576000848401525b50505050565b6000601f19601f8301169050919050565b600061081b826107b0565b61082581856107bb565b93506108358185602086016107cc565b61083e816107ff565b840191505092915050565b600060208201905081810360008301526108638184610810565b905092915050565b600080600060608486031215610884576108836104f2565b5b6000610892868287016105d8565b93505060206108a386828701610636565b92505060406108b486828701610636565b9150509250925092565b6108c7816105b7565b82525050565b6108d68161060d565b82525050565b60006080820190506108f160008301876108be565b6108fe60208301866108cd565b61090b60408301856108cd565b610918606083018461058d565b95945050505050565b600081905092915050565b82818337600083830152505050565b60006109478385610921565b935061095483858461092c565b82840190509392505050565b600061096d82848661093b565b91508190509392505050565b600080fd5b600080fd5b6000808585111561099757610996610979565b5b838611156109a8576109a761097e565b5b6001850283019150848603905094509492505050565b600082905092915050565b600082821b905092915050565b60006109e283836109be565b826109ed81356105b7565b92506020821015610a2d57610a287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008026109c9565b831692505b505092915050565b600082825260208201905092915050565b7f706172656e7420646f6d61696e206e6f742076616c696461746564206170707260008201527f6f7072696174656c790000000000000000000000000000000000000000000000602082015250565b6000610aa2602983610a35565b9150610aad82610a46565b604082019050919050565b60006020820190508181036000830152610ad181610a95565b9050919050565b6000602082019050610aed60008301846108cd565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610b6682610b22565b9150610b7183610b22565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ba657610ba5610b2c565b5b828201905092915050565b6000610bbe82848661093b565b91508190509392505050565b7f737562646f6d61696e206e6f742076616c69646174656420617070726f70726960008201527f6174656c79000000000000000000000000000000000000000000000000000000602082015250565b6000610c26602583610a35565b9150610c3182610bca565b604082019050919050565b60006020820190508181036000830152610c5581610c19565b905091905056fea26469706673582212209fff87be19ed85e754d5e2791de6ed052e7e653185e1d47fa94515f851becd2f64736f6c634300080d0033"
-extended_resolver_bytecode_runtime = "608060405234801561001057600080fd5b506004361061004c5760003560e01c806301ffc9a7146100515780633e9ce794146100815780639061b9231461009d578063f86bc879146100cd575b600080fd5b61006b60048036038101906100669190610554565b6100fd565b604051610078919061059c565b60405180910390f35b61009b60048036038101906100969190610677565b61015e565b005b6100b760048036038101906100b2919061072f565b610245565b6040516100c49190610849565b60405180910390f35b6100e760048036038101906100e2919061086b565b610465565b6040516100f4919061059c565b60405180910390f35b6000639061b92360e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101575750610156826104a1565b5b9050919050565b806001600085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fe1c5610a6e0cbe10764ecd182adcef1ec338dc4e199c99c32ce98f38e12791df8333848460405161023894939291906108dc565b60405180910390a1505050565b60606040518060400160405280601781526020017f11657874656e6465642d7265736f6c7665720365746800000000000000000000815250805190602001208585604051610294929190610960565b60405180910390201480156102ad575060248383905010155b1561035e577ff0a378cc2afe91730d0105e67d6bb037cc5b8b6bfec5b5962d9b637ff6497e5560001b83836004906024926102ea93929190610983565b906102f591906109d6565b14610335576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032c90610ab8565b60405180910390fd5b61beef6040516020016103489190610ad8565b604051602081830303815290604052905061045d565b60008585600081811061037457610373610af3565b5b9050013560f81c60f81b60f81c60ff1690506040518060400160405280601781526020017f11657874656e6465642d7265736f6c76657203657468000000000000000000008152508051906020012086868360016103d29190610b5b565b9080926103e193929190610983565b6040516103ef929190610bb1565b604051809103902014610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90610c3c565b60405180910390fd5b61dead60405160200161044a9190610ad8565b6040516020818303038152906040529150505b949350505050565b6001602052826000526040600020602052816000526040600020602052806000526040600020600092509250509054906101000a900460ff1681565b60006301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610531816104fc565b811461053c57600080fd5b50565b60008135905061054e81610528565b92915050565b60006020828403121561056a576105696104f2565b5b60006105788482850161053f565b91505092915050565b60008115159050919050565b61059681610581565b82525050565b60006020820190506105b1600083018461058d565b92915050565b6000819050919050565b6105ca816105b7565b81146105d557600080fd5b50565b6000813590506105e7816105c1565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610618826105ed565b9050919050565b6106288161060d565b811461063357600080fd5b50565b6000813590506106458161061f565b92915050565b61065481610581565b811461065f57600080fd5b50565b6000813590506106718161064b565b92915050565b6000806000606084860312156106905761068f6104f2565b5b600061069e868287016105d8565b93505060206106af86828701610636565b92505060406106c086828701610662565b9150509250925092565b600080fd5b600080fd5b600080fd5b60008083601f8401126106ef576106ee6106ca565b5b8235905067ffffffffffffffff81111561070c5761070b6106cf565b5b602083019150836001820283011115610728576107276106d4565b5b9250929050565b60008060008060408587031215610749576107486104f2565b5b600085013567ffffffffffffffff811115610767576107666104f7565b5b610773878288016106d9565b9450945050602085013567ffffffffffffffff811115610796576107956104f7565b5b6107a2878288016106d9565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60005b838110156107ea5780820151818401526020810190506107cf565b838111156107f9576000848401525b50505050565b6000601f19601f8301169050919050565b600061081b826107b0565b61082581856107bb565b93506108358185602086016107cc565b61083e816107ff565b840191505092915050565b600060208201905081810360008301526108638184610810565b905092915050565b600080600060608486031215610884576108836104f2565b5b6000610892868287016105d8565b93505060206108a386828701610636565b92505060406108b486828701610636565b9150509250925092565b6108c7816105b7565b82525050565b6108d68161060d565b82525050565b60006080820190506108f160008301876108be565b6108fe60208301866108cd565b61090b60408301856108cd565b610918606083018461058d565b95945050505050565b600081905092915050565b82818337600083830152505050565b60006109478385610921565b935061095483858461092c565b82840190509392505050565b600061096d82848661093b565b91508190509392505050565b600080fd5b600080fd5b6000808585111561099757610996610979565b5b838611156109a8576109a761097e565b5b6001850283019150848603905094509492505050565b600082905092915050565b600082821b905092915050565b60006109e283836109be565b826109ed81356105b7565b92506020821015610a2d57610a287fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff836020036008026109c9565b831692505b505092915050565b600082825260208201905092915050565b7f706172656e7420646f6d61696e206e6f742076616c696461746564206170707260008201527f6f7072696174656c790000000000000000000000000000000000000000000000602082015250565b6000610aa2602983610a35565b9150610aad82610a46565b604082019050919050565b60006020820190508181036000830152610ad181610a95565b9050919050565b6000602082019050610aed60008301846108cd565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610b6682610b22565b9150610b7183610b22565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610ba657610ba5610b2c565b5b828201905092915050565b6000610bbe82848661093b565b91508190509392505050565b7f737562646f6d61696e206e6f742076616c69646174656420617070726f70726960008201527f6174656c79000000000000000000000000000000000000000000000000000000602082015250565b6000610c26602583610a35565b9150610c3182610bca565b604082019050919050565b60006020820190508181036000830152610c5581610c19565b905091905056fea26469706673582212209fff87be19ed85e754d5e2791de6ed052e7e653185e1d47fa94515f851becd2f64736f6c634300080d0033"
-
-# Simple resolver with no support for interfaces like getText(), etc
-# compiled from `web3/_utils/contract_sources/SimpleResolver.sol`
-simple_resolver_abi = json.loads(
-    '[{"inputs":[{"internalType":"bytes32","name":"nodeID","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]'
-)
-simple_resolver_bytecode = "608060405234801561001057600080fd5b5061028c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806301ffc9a71461003b5780633b3b57de1461006b575b600080fd5b61005560048036038101906100509190610134565b61009b565b604051610062919061017c565b60405180910390f35b610085600480360381019061008091906101cd565b6100cd565b604051610092919061023b565b60405180910390f35b6000633b3b57de60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000309050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610111816100dc565b811461011c57600080fd5b50565b60008135905061012e81610108565b92915050565b60006020828403121561014a576101496100d7565b5b60006101588482850161011f565b91505092915050565b60008115159050919050565b61017681610161565b82525050565b6000602082019050610191600083018461016d565b92915050565b6000819050919050565b6101aa81610197565b81146101b557600080fd5b50565b6000813590506101c7816101a1565b92915050565b6000602082840312156101e3576101e26100d7565b5b60006101f1848285016101b8565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610225826101fa565b9050919050565b6102358161021a565b82525050565b6000602082019050610250600083018461022c565b9291505056fea2646970667358221220e9d34e70193fa6e99d9be00bd7b1e4b63dc6fd9c84934a35350d8b2c4215974964736f6c634300080d0033"
-simple_resolver_bytecode_runtime = "608060405234801561001057600080fd5b50600436106100365760003560e01c806301ffc9a71461003b5780633b3b57de1461006b575b600080fd5b61005560048036038101906100509190610134565b61009b565b604051610062919061017c565b60405180910390f35b610085600480360381019061008091906101cd565b6100cd565b604051610092919061023b565b60405180910390f35b6000633b3b57de60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6000309050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610111816100dc565b811461011c57600080fd5b50565b60008135905061012e81610108565b92915050565b60006020828403121561014a576101496100d7565b5b60006101588482850161011f565b91505092915050565b60008115159050919050565b61017681610161565b82525050565b6000602082019050610191600083018461016d565b92915050565b6000819050919050565b6101aa81610197565b81146101b557600080fd5b50565b6000813590506101c7816101a1565b92915050565b6000602082840312156101e3576101e26100d7565b5b60006101f1848285016101b8565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610225826101fa565b9050919050565b6102358161021a565b82525050565b6000602082019050610250600083018461022c565b9291505056fea2646970667358221220e9d34e70193fa6e99d9be00bd7b1e4b63dc6fd9c84934a35350d8b2c4215974964736f6c634300080d0033"
-
-# Offchain Resolver for offchain resolution w/ CCIP Read as described in EIP-3668
-# compiled from `web3/_utils/contract_sources/OffchainResolver.sol`
-offchain_resolver_abi = json.loads(
-    '[{"inputs":[{"internalType":"string[]","name":"_urls","type":"string[]"},{"internalType":"address[]","name":"_signers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string[]","name":"urls","type":"string[]"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes4","name":"callbackFunction","type":"bytes4"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"OffchainLookup","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"}],"name":"NewSigners","type":"event"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint64","name":"expires","type":"uint64"},{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes","name":"result","type":"bytes"}],"name":"makeSignatureHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"name","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"resolve","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"response","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"resolveWithProof","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"url","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]'
-)
-offchain_resolver_bytecode = "60806040523480156200001157600080fd5b506040516200219038038062002190833981810160405281019062000037919062000511565b81600090805190602001906200004f929190620001a4565b5060005b81518110156200010b5760018060008484815181106200009c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080620001029062000813565b91505062000053565b5060018060003073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fab0b9cc3a46b568cb08d985497cde8ab7e18892d01f58db7dc7f0d2af859b2d78160405162000194919062000619565b60405180910390a1505062000919565b828054828255906000526020600020908101928215620001f8579160200282015b82811115620001f7578251829080519060200190620001e69291906200020b565b5091602001919060010190620001c5565b5b5090506200020791906200029c565b5090565b8280546200021990620007a7565b90600052602060002090601f0160209004810192826200023d576000855562000289565b82601f106200025857805160ff191683800117855562000289565b8280016001018555821562000289579182015b82811115620002885782518255916020019190600101906200026b565b5b509050620002989190620002c4565b5090565b5b80821115620002c05760008181620002b69190620002e3565b506001016200029d565b5090565b5b80821115620002df576000816000905550600101620002c5565b5090565b508054620002f190620007a7565b6000825580601f1062000305575062000326565b601f016020900490600052602060002090810190620003259190620002c4565b5b50565b6000620003406200033a8462000666565b6200063d565b905080838252602082019050828560208602820111156200036057600080fd5b60005b8581101562000394578162000379888262000473565b84526020840193506020830192505060018101905062000363565b5050509392505050565b6000620003b5620003af8462000695565b6200063d565b90508083825260208201905082856020860282011115620003d557600080fd5b60005b858110156200042457815167ffffffffffffffff811115620003f957600080fd5b808601620004088982620004e4565b85526020850194506020840193505050600181019050620003d8565b5050509392505050565b6000620004456200043f84620006c4565b6200063d565b9050828152602081018484840111156200045e57600080fd5b6200046b84828562000771565b509392505050565b6000815190506200048481620008ff565b92915050565b600082601f8301126200049c57600080fd5b8151620004ae84826020860162000329565b91505092915050565b600082601f830112620004c957600080fd5b8151620004db8482602086016200039e565b91505092915050565b600082601f830112620004f657600080fd5b8151620005088482602086016200042e565b91505092915050565b600080604083850312156200052557600080fd5b600083015167ffffffffffffffff8111156200054057600080fd5b6200054e85828601620004b7565b925050602083015167ffffffffffffffff8111156200056c57600080fd5b6200057a858286016200048a565b9150509250929050565b60006200059283836200059e565b60208301905092915050565b620005a98162000733565b82525050565b6000620005bc826200070a565b620005c8818562000722565b9350620005d583620006fa565b8060005b838110156200060c578151620005f0888262000584565b9750620005fd8362000715565b925050600181019050620005d9565b5085935050505092915050565b60006020820190508181036000830152620006358184620005af565b905092915050565b6000620006496200065c565b9050620006578282620007dd565b919050565b6000604051905090565b600067ffffffffffffffff821115620006845762000683620008bf565b5b602082029050602081019050919050565b600067ffffffffffffffff821115620006b357620006b2620008bf565b5b602082029050602081019050919050565b600067ffffffffffffffff821115620006e257620006e1620008bf565b5b620006ed82620008ee565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b6000620007408262000747565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b838110156200079157808201518184015260208101905062000774565b83811115620007a1576000848401525b50505050565b60006002820490506001821680620007c057607f821691505b60208210811415620007d757620007d662000890565b5b50919050565b620007e882620008ee565b810181811067ffffffffffffffff821117156200080a5762000809620008bf565b5b80604052505050565b6000620008208262000767565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141562000856576200085562000861565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b6200090a8162000733565b81146200091657600080fd5b50565b61186780620009296000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780631dcfea0914610097578063736c0d5b146100c7578063796676be146100f75780639061b92314610127578063f4d4d2f814610157575b600080fd5b610081600480360381019061007c9190610cb9565b610187565b60405161008e91906111c9565b60405180910390f35b6100b160048036038101906100ac9190610c26565b610201565b6040516100be91906111e4565b60405180910390f35b6100e160048036038101906100dc9190610bfd565b610219565b6040516100ee91906111c9565b60405180910390f35b610111600480360381019061010c9190610dd6565b610239565b60405161011e91906112a1565b60405180910390f35b610141600480360381019061013c9190610ce2565b6102e5565b60405161014e919061127f565b60405180910390f35b610171600480360381019061016c9190610ce2565b6103b4565b60405161017e919061127f565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101fa57506101f982610462565b5b9050919050565b600061020f858585856104cc565b9050949350505050565b60016020528060005260406000206000915054906101000a900460ff1681565b6000818154811061024957600080fd5b90600052602060002001600091509050805461026490611541565b80601f016020809104026020016040519081016040528092919081815260200182805461029090611541565b80156102dd5780601f106102b2576101008083540402835291602001916102dd565b820191906000526020600020905b8154815290600101906020018083116102c057829003601f168201915b505050505081565b60606000639061b92360e01b868686866040516024016103089493929190611244565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090503060008263f4d4d2f860e01b846040517f556f18300000000000000000000000000000000000000000000000000000000081526004016103ab959493929190611161565b60405180910390fd5b60606000806103c585858989610513565b91509150600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044c90611323565b60405180910390fd5b8092505050949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008484848051906020012084805190602001206040516020016104f39493929190611108565b604051602081830303815290604052805190602001209050949350505050565b600060606000806000868681019061052b9190610d57565b925092509250600061058c61058630858d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050886104cc565b836105a1565b90508084955095505050505094509492505050565b60008060006105b085856105c8565b915091506105bd8161064b565b819250505092915050565b60008060418351141561060a5760008060006020860151925060408601519150606086015160001a90506105fe8782858561099c565b94509450505050610644565b60408351141561063b576000806020850151915060408501519050610630868383610aa9565b935093505050610644565b60006002915091505b9250929050565b60006004811115610685577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160048111156106be577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156106c957610999565b60016004811115610703577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81600481111561073c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b141561077d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610774906112c3565b60405180910390fd5b600260048111156107b7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160048111156107f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415610831576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610828906112e3565b60405180910390fd5b6003600481111561086b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160048111156108a4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156108e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108dc90611303565b60405180910390fd5b60048081111561091e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b816004811115610957577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415610998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098f90611343565b60405180910390fd5b5b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156109d7576000600391509150610aa0565b601b8560ff16141580156109ef5750601c8560ff1614155b15610a01576000600491509150610aa0565b600060018787878760405160008152602001604052604051610a2694939291906111ff565b6020604051602081039080840390855afa158015610a48573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a9757600060019250925050610aa0565b80600092509250505b94509492505050565b6000806000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85169150601b8560ff1c019050610ae98782888561099c565b935093505050935093915050565b6000610b0a610b0584611388565b611363565b905082815260208101848484011115610b2257600080fd5b610b2d8482856114ff565b509392505050565b600081359050610b44816117d5565b92915050565b600081359050610b59816117ec565b92915050565b60008083601f840112610b7157600080fd5b8235905067ffffffffffffffff811115610b8a57600080fd5b602083019150836001820283011115610ba257600080fd5b9250929050565b600082601f830112610bba57600080fd5b8135610bca848260208601610af7565b91505092915050565b600081359050610be281611803565b92915050565b600081359050610bf78161181a565b92915050565b600060208284031215610c0f57600080fd5b6000610c1d84828501610b35565b91505092915050565b60008060008060808587031215610c3c57600080fd5b6000610c4a87828801610b35565b9450506020610c5b87828801610be8565b935050604085013567ffffffffffffffff811115610c7857600080fd5b610c8487828801610ba9565b925050606085013567ffffffffffffffff811115610ca157600080fd5b610cad87828801610ba9565b91505092959194509250565b600060208284031215610ccb57600080fd5b6000610cd984828501610b4a565b91505092915050565b60008060008060408587031215610cf857600080fd5b600085013567ffffffffffffffff811115610d1257600080fd5b610d1e87828801610b5f565b9450945050602085013567ffffffffffffffff811115610d3d57600080fd5b610d4987828801610b5f565b925092505092959194509250565b600080600060608486031215610d6c57600080fd5b600084013567ffffffffffffffff811115610d8657600080fd5b610d9286828701610ba9565b9350506020610da386828701610be8565b925050604084013567ffffffffffffffff811115610dc057600080fd5b610dcc86828701610ba9565b9150509250925092565b600060208284031215610de857600080fd5b6000610df684828501610bd3565b91505092915050565b6000610e0b8383610f90565b905092915050565b610e1c81611460565b82525050565b610e33610e2e82611460565b6115a4565b82525050565b6000610e44826113e3565b610e4e8185611411565b935083602082028501610e60856113b9565b8060005b85811015610e9b57848403895281610e7c8582610dff565b9450610e8783611404565b925060208a01995050600181019050610e64565b50829750879550505050505092915050565b610eb681611472565b82525050565b610ec58161147e565b82525050565b610edc610ed78261147e565b6115b6565b82525050565b610eeb81611488565b82525050565b6000610efd8385611422565b9350610f0a8385846114ff565b610f1383611642565b840190509392505050565b6000610f29826113ee565b610f338185611422565b9350610f4381856020860161150e565b610f4c81611642565b840191505092915050565b6000610f62826113f9565b610f6c8185611444565b9350610f7c81856020860161150e565b610f8581611642565b840191505092915050565b60008154610f9d81611541565b610fa78186611433565b94506001821660008114610fc25760018114610fd457611007565b60ff1983168652602086019350611007565b610fdd856113ce565b60005b83811015610fff57815481890152600182019150602081019050610fe0565b808801955050505b50505092915050565b600061101d601883611444565b91506110288261166d565b602082019050919050565b6000611040601f83611444565b915061104b82611696565b602082019050919050565b6000611063602283611444565b915061106e826116bf565b604082019050919050565b6000611086602483611444565b91506110918261170e565b604082019050919050565b60006110a9600283611455565b91506110b48261175d565b600282019050919050565b60006110cc602283611444565b91506110d782611786565b604082019050919050565b6110f36110ee826114de565b6115d2565b82525050565b611102816114f2565b82525050565b60006111138261109c565b915061111f8287610e22565b60148201915061112f82866110e2565b60088201915061113f8285610ecb565b60208201915061114f8284610ecb565b60208201915081905095945050505050565b600060a0820190506111766000830188610e13565b81810360208301526111888187610e39565b9050818103604083015261119c8186610f1e565b90506111ab6060830185610ee2565b81810360808301526111bd8184610f1e565b90509695505050505050565b60006020820190506111de6000830184610ead565b92915050565b60006020820190506111f96000830184610ebc565b92915050565b60006080820190506112146000830187610ebc565b61122160208301866110f9565b61122e6040830185610ebc565b61123b6060830184610ebc565b95945050505050565b6000604082019050818103600083015261125f818688610ef1565b90508181036020830152611274818486610ef1565b905095945050505050565b600060208201905081810360008301526112998184610f1e565b905092915050565b600060208201905081810360008301526112bb8184610f57565b905092915050565b600060208201905081810360008301526112dc81611010565b9050919050565b600060208201905081810360008301526112fc81611033565b9050919050565b6000602082019050818103600083015261131c81611056565b9050919050565b6000602082019050818103600083015261133c81611079565b9050919050565b6000602082019050818103600083015261135c816110bf565b9050919050565b600061136d61137e565b90506113798282611573565b919050565b6000604051905090565b600067ffffffffffffffff8211156113a3576113a2611613565b5b6113ac82611642565b9050602081019050919050565b60008190508160005260206000209050919050565b60008190508160005260206000209050919050565b600081549050919050565b600081519050919050565b600081519050919050565b6000600182019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061146b826114b4565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600067ffffffffffffffff82169050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561152c578082015181840152602081019050611511565b8381111561153b576000848401525b50505050565b6000600282049050600182168061155957607f821691505b6020821081141561156d5761156c6115e4565b5b50919050565b61157c82611642565b810181811067ffffffffffffffff8211171561159b5761159a611613565b5b80604052505050565b60006115af826115c0565b9050919050565b6000819050919050565b60006115cb82611660565b9050919050565b60006115dd82611653565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160c01b9050919050565b60008160601b9050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f5369676e617475726556657269666965723a20496e76616c6964207369676e6160008201527f7475726500000000000000000000000000000000000000000000000000000000602082015250565b7f1900000000000000000000000000000000000000000000000000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6117de81611460565b81146117e957600080fd5b50565b6117f581611488565b811461180057600080fd5b50565b61180c816114d4565b811461181757600080fd5b50565b611823816114de565b811461182e57600080fd5b5056fea2646970667358221220e5f1e91619d2bc52c11e1bd99d0dabfdbeca91f7eac25e3122f6117fc623900b64736f6c63430008040033"
-offchain_resolver_bytecode_runtime = "608060405234801561001057600080fd5b50600436106100625760003560e01c806301ffc9a7146100675780631dcfea0914610097578063736c0d5b146100c7578063796676be146100f75780639061b92314610127578063f4d4d2f814610157575b600080fd5b610081600480360381019061007c9190610cb9565b610187565b60405161008e91906111c9565b60405180910390f35b6100b160048036038101906100ac9190610c26565b610201565b6040516100be91906111e4565b60405180910390f35b6100e160048036038101906100dc9190610bfd565b610219565b6040516100ee91906111c9565b60405180910390f35b610111600480360381019061010c9190610dd6565b610239565b60405161011e91906112a1565b60405180910390f35b610141600480360381019061013c9190610ce2565b6102e5565b60405161014e919061127f565b60405180910390f35b610171600480360381019061016c9190610ce2565b6103b4565b60405161017e919061127f565b60405180910390f35b60007f9061b923000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806101fa57506101f982610462565b5b9050919050565b600061020f858585856104cc565b9050949350505050565b60016020528060005260406000206000915054906101000a900460ff1681565b6000818154811061024957600080fd5b90600052602060002001600091509050805461026490611541565b80601f016020809104026020016040519081016040528092919081815260200182805461029090611541565b80156102dd5780601f106102b2576101008083540402835291602001916102dd565b820191906000526020600020905b8154815290600101906020018083116102c057829003601f168201915b505050505081565b60606000639061b92360e01b868686866040516024016103089493929190611244565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090503060008263f4d4d2f860e01b846040517f556f18300000000000000000000000000000000000000000000000000000000081526004016103ab959493929190611161565b60405180910390fd5b60606000806103c585858989610513565b91509150600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044c90611323565b60405180910390fd5b8092505050949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008484848051906020012084805190602001206040516020016104f39493929190611108565b604051602081830303815290604052805190602001209050949350505050565b600060606000806000868681019061052b9190610d57565b925092509250600061058c61058630858d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050886104cc565b836105a1565b90508084955095505050505094509492505050565b60008060006105b085856105c8565b915091506105bd8161064b565b819250505092915050565b60008060418351141561060a5760008060006020860151925060408601519150606086015160001a90506105fe8782858561099c565b94509450505050610644565b60408351141561063b576000806020850151915060408501519050610630868383610aa9565b935093505050610644565b60006002915091505b9250929050565b60006004811115610685577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160048111156106be577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156106c957610999565b60016004811115610703577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81600481111561073c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b141561077d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610774906112c3565b60405180910390fd5b600260048111156107b7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160048111156107f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415610831576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610828906112e3565b60405180910390fd5b6003600481111561086b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160048111156108a4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156108e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108dc90611303565b60405180910390fd5b60048081111561091e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b816004811115610957577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415610998576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098f90611343565b60405180910390fd5b5b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c11156109d7576000600391509150610aa0565b601b8560ff16141580156109ef5750601c8560ff1614155b15610a01576000600491509150610aa0565b600060018787878760405160008152602001604052604051610a2694939291906111ff565b6020604051602081039080840390855afa158015610a48573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a9757600060019250925050610aa0565b80600092509250505b94509492505050565b6000806000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85169150601b8560ff1c019050610ae98782888561099c565b935093505050935093915050565b6000610b0a610b0584611388565b611363565b905082815260208101848484011115610b2257600080fd5b610b2d8482856114ff565b509392505050565b600081359050610b44816117d5565b92915050565b600081359050610b59816117ec565b92915050565b60008083601f840112610b7157600080fd5b8235905067ffffffffffffffff811115610b8a57600080fd5b602083019150836001820283011115610ba257600080fd5b9250929050565b600082601f830112610bba57600080fd5b8135610bca848260208601610af7565b91505092915050565b600081359050610be281611803565b92915050565b600081359050610bf78161181a565b92915050565b600060208284031215610c0f57600080fd5b6000610c1d84828501610b35565b91505092915050565b60008060008060808587031215610c3c57600080fd5b6000610c4a87828801610b35565b9450506020610c5b87828801610be8565b935050604085013567ffffffffffffffff811115610c7857600080fd5b610c8487828801610ba9565b925050606085013567ffffffffffffffff811115610ca157600080fd5b610cad87828801610ba9565b91505092959194509250565b600060208284031215610ccb57600080fd5b6000610cd984828501610b4a565b91505092915050565b60008060008060408587031215610cf857600080fd5b600085013567ffffffffffffffff811115610d1257600080fd5b610d1e87828801610b5f565b9450945050602085013567ffffffffffffffff811115610d3d57600080fd5b610d4987828801610b5f565b925092505092959194509250565b600080600060608486031215610d6c57600080fd5b600084013567ffffffffffffffff811115610d8657600080fd5b610d9286828701610ba9565b9350506020610da386828701610be8565b925050604084013567ffffffffffffffff811115610dc057600080fd5b610dcc86828701610ba9565b9150509250925092565b600060208284031215610de857600080fd5b6000610df684828501610bd3565b91505092915050565b6000610e0b8383610f90565b905092915050565b610e1c81611460565b82525050565b610e33610e2e82611460565b6115a4565b82525050565b6000610e44826113e3565b610e4e8185611411565b935083602082028501610e60856113b9565b8060005b85811015610e9b57848403895281610e7c8582610dff565b9450610e8783611404565b925060208a01995050600181019050610e64565b50829750879550505050505092915050565b610eb681611472565b82525050565b610ec58161147e565b82525050565b610edc610ed78261147e565b6115b6565b82525050565b610eeb81611488565b82525050565b6000610efd8385611422565b9350610f0a8385846114ff565b610f1383611642565b840190509392505050565b6000610f29826113ee565b610f338185611422565b9350610f4381856020860161150e565b610f4c81611642565b840191505092915050565b6000610f62826113f9565b610f6c8185611444565b9350610f7c81856020860161150e565b610f8581611642565b840191505092915050565b60008154610f9d81611541565b610fa78186611433565b94506001821660008114610fc25760018114610fd457611007565b60ff1983168652602086019350611007565b610fdd856113ce565b60005b83811015610fff57815481890152600182019150602081019050610fe0565b808801955050505b50505092915050565b600061101d601883611444565b91506110288261166d565b602082019050919050565b6000611040601f83611444565b915061104b82611696565b602082019050919050565b6000611063602283611444565b915061106e826116bf565b604082019050919050565b6000611086602483611444565b91506110918261170e565b604082019050919050565b60006110a9600283611455565b91506110b48261175d565b600282019050919050565b60006110cc602283611444565b91506110d782611786565b604082019050919050565b6110f36110ee826114de565b6115d2565b82525050565b611102816114f2565b82525050565b60006111138261109c565b915061111f8287610e22565b60148201915061112f82866110e2565b60088201915061113f8285610ecb565b60208201915061114f8284610ecb565b60208201915081905095945050505050565b600060a0820190506111766000830188610e13565b81810360208301526111888187610e39565b9050818103604083015261119c8186610f1e565b90506111ab6060830185610ee2565b81810360808301526111bd8184610f1e565b90509695505050505050565b60006020820190506111de6000830184610ead565b92915050565b60006020820190506111f96000830184610ebc565b92915050565b60006080820190506112146000830187610ebc565b61122160208301866110f9565b61122e6040830185610ebc565b61123b6060830184610ebc565b95945050505050565b6000604082019050818103600083015261125f818688610ef1565b90508181036020830152611274818486610ef1565b905095945050505050565b600060208201905081810360008301526112998184610f1e565b905092915050565b600060208201905081810360008301526112bb8184610f57565b905092915050565b600060208201905081810360008301526112dc81611010565b9050919050565b600060208201905081810360008301526112fc81611033565b9050919050565b6000602082019050818103600083015261131c81611056565b9050919050565b6000602082019050818103600083015261133c81611079565b9050919050565b6000602082019050818103600083015261135c816110bf565b9050919050565b600061136d61137e565b90506113798282611573565b919050565b6000604051905090565b600067ffffffffffffffff8211156113a3576113a2611613565b5b6113ac82611642565b9050602081019050919050565b60008190508160005260206000209050919050565b60008190508160005260206000209050919050565b600081549050919050565b600081519050919050565b600081519050919050565b6000600182019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061146b826114b4565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600067ffffffffffffffff82169050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b8381101561152c578082015181840152602081019050611511565b8381111561153b576000848401525b50505050565b6000600282049050600182168061155957607f821691505b6020821081141561156d5761156c6115e4565b5b50919050565b61157c82611642565b810181811067ffffffffffffffff8211171561159b5761159a611613565b5b80604052505050565b60006115af826115c0565b9050919050565b6000819050919050565b60006115cb82611660565b9050919050565b60006115dd82611653565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160c01b9050919050565b60008160601b9050919050565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b7f5369676e617475726556657269666965723a20496e76616c6964207369676e6160008201527f7475726500000000000000000000000000000000000000000000000000000000602082015250565b7f1900000000000000000000000000000000000000000000000000000000000000600082015250565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6117de81611460565b81146117e957600080fd5b50565b6117f581611488565b811461180057600080fd5b50565b61180c816114d4565b811461181757600080fd5b50565b611823816114de565b811461182e57600080fd5b5056fea2646970667358221220e5f1e91619d2bc52c11e1bd99d0dabfdbeca91f7eac25e3122f6117fc623900b64736f6c63430008040033"
diff --git a/ens/ens.py b/ens/ens.py
index d427eb8d..97b24a28 100644
--- a/ens/ens.py
+++ b/ens/ens.py
@@ -3,6 +3,7 @@ from copy import (
 )
 from typing import (
     TYPE_CHECKING,
+    Any,
     Optional,
     Sequence,
     Tuple,
@@ -37,9 +38,10 @@ from .base_ens import (
 )
 from .constants import (
     EMPTY_ADDR_HEX,
+    ENS_EXTENDED_RESOLVER_INTERFACE_ID,
     ENS_MAINNET_ADDR,
-    EXTENDED_RESOLVER_INTERFACE_ID,
-    GET_TEXT_INTERFACE_ID,
+    ENS_MULTICHAIN_ADDRESS_INTERFACE_ID,
+    ENS_TEXT_INTERFACE_ID,
     REVERSE_REGISTRAR_DOMAIN,
 )
 from .exceptions import (
@@ -65,8 +67,9 @@ from .utils import (
 
 if TYPE_CHECKING:
     from web3 import Web3  # noqa: F401
-    from web3.contract import (  # noqa: F401
+    from web3.contract.contract import (  # noqa: F401
         Contract,
+        ContractFunction,
     )
     from web3.providers import (  # noqa: F401
         BaseProvider,
@@ -132,14 +135,35 @@ class ENS(BaseENS):
 
         return ns
 
-    def address(self, name: str) -> Optional[ChecksumAddress]:
+    def address(
+        self,
+        name: str,
+        coin_type: Optional[int] = None,
+    ) -> Optional[ChecksumAddress]:
         """
         Look up the Ethereum address that `name` currently points to.
 
         :param str name: an ENS name to look up
+        :param int coin_type: if provided, look up the address for this coin type
         :raises InvalidName: if `name` has invalid syntax
+        :raises ResolverNotFound: if no resolver found for `name`
+        :raises UnsupportedFunction: if the resolver does not support the ``addr()``
+                function
         """
-        return cast(ChecksumAddress, self._resolve(name, "addr"))
+        r = self.resolver(name)
+        if coin_type is None:
+            # don't validate `addr(bytes32)` interface id since extended resolvers
+            # can implement a "resolve" function as of ENSIP-10
+            return cast(ChecksumAddress, self._resolve(name, "addr"))
+        else:
+            _validate_resolver_and_interface_id(
+                name, r, ENS_MULTICHAIN_ADDRESS_INTERFACE_ID, "addr(bytes32,uint256)"
+            )
+            node = raw_name_to_hash(name)
+            address_as_bytes = r.caller.addr(node, coin_type)
+            if is_none_or_zero_address(address_as_bytes):
+                return None
+            return to_checksum_address(address_as_bytes)
 
     def setup_address(
         self,
@@ -147,6 +171,7 @@ class ENS(BaseENS):
         address: Union[Address, ChecksumAddress, HexAddress] = cast(
             ChecksumAddress, default
         ),
+        coin_type: Optional[int] = None,
         transact: Optional["TxParams"] = None,
     ) -> Optional[HexBytes]:
         """
@@ -162,6 +187,7 @@ class ENS(BaseENS):
         :param str address: name will point to this address, in checksum format.
             If ``None``, erase the record. If not specified, name will point
             to the owner's address.
+        :param int coin_type: if provided, set up the address for this coin type
         :param dict transact: the transaction configuration, like in
             :meth:`~web3.eth.Eth.send_transaction`
         :raises InvalidName: if ``name`` has invalid syntax
@@ -169,6 +195,7 @@ class ENS(BaseENS):
         """
         if not transact:
             transact = {}
+
         transact = deepcopy(transact)
         owner = self.setup_owner(name, transact=transact)
         self._assert_control(owner, name)
@@ -187,9 +214,14 @@ class ENS(BaseENS):
         transact["from"] = owner
 
         resolver: "Contract" = self._set_resolver(name, transact=transact)
-        return resolver.functions.setAddr(raw_name_to_hash(name), address).transact(
-            transact
-        )
+        node = raw_name_to_hash(name)
+
+        if coin_type is None:
+            return resolver.functions.setAddr(node, address).transact(transact)
+        else:
+            return resolver.functions.setAddr(node, coin_type, address).transact(
+                transact
+            )
 
     def name(self, address: ChecksumAddress) -> Optional[str]:
         """
@@ -218,7 +250,7 @@ class ENS(BaseENS):
         `name` when supplied with `address`.
 
         :param str name: ENS name that address will point to
-        :param str address: to set up, in checksum format
+        :param str address: address to set up, in checksum format
         :param dict transact: the transaction configuration, like in
             :meth:`~web3.eth.send_transaction`
         :raises AddressMismatch: if the name does not already point to the address
@@ -302,6 +334,7 @@ class ENS(BaseENS):
         """
         if not transact:
             transact = {}
+
         transact = deepcopy(transact)
         (super_owner, unowned, owned) = self._first_owner(name)
         if new_owner is default:
@@ -335,6 +368,8 @@ class ENS(BaseENS):
         reversed_domain = address_to_reverse_domain(target_address)
         return self.resolver(reversed_domain)
 
+    # -- text records -- #
+
     def get_text(self, name: str, key: str) -> str:
         """
         Get the value of a text record by key from an ENS name.
@@ -350,18 +385,8 @@ class ENS(BaseENS):
         node = raw_name_to_hash(name)
 
         r = self.resolver(name)
-        if r:
-            if _resolver_supports_interface(r, GET_TEXT_INTERFACE_ID):
-                return r.caller.text(node, key)
-            else:
-                raise UnsupportedFunction(
-                    f"Resolver for name {name} does not support `text` function."
-                )
-        else:
-            raise ResolverNotFound(
-                f"No resolver found for name `{name}`. It is likely the name "
-                "contains an unsupported top level domain (tld)."
-            )
+        _validate_resolver_and_interface_id(name, r, ENS_TEXT_INTERFACE_ID, "text")
+        return r.caller.text(node, key)
 
     def set_text(
         self,
@@ -384,27 +409,15 @@ class ENS(BaseENS):
             the "0x59d1d43c" interface id
         :raises ResolverNotFound: If no resolver is found for the provided name
         """
-        if not transact:
-            transact = {}
-
-        owner = self.owner(name)
+        r = self.resolver(name)
+        _validate_resolver_and_interface_id(name, r, ENS_TEXT_INTERFACE_ID, "text")
         node = raw_name_to_hash(name)
 
-        transaction_dict = merge({"from": owner}, transact)
+        return self._set_property(
+            name, r.functions.setText, (node, key, value), transact
+        )
 
-        r = self.resolver(name)
-        if r:
-            if _resolver_supports_interface(r, GET_TEXT_INTERFACE_ID):
-                return r.functions.setText(node, key, value).transact(transaction_dict)
-            else:
-                raise UnsupportedFunction(
-                    f"Resolver for name `{name}` does not support `text` function"
-                )
-        else:
-            raise ResolverNotFound(
-                f"No resolver found for name `{name}`. It is likely the name contains "
-                "an unsupported top level domain (tld)."
-            )
+    # -- private methods -- #
 
     def _get_resolver(
         self,
@@ -452,7 +465,6 @@ class ENS(BaseENS):
         self, name: str, fn_name: str = "addr"
     ) -> Optional[Union[ChecksumAddress, str]]:
         normal_name = normalize_name(name)
-
         resolver, current_name = self._get_resolver(normal_name, fn_name)
         if not resolver:
             return None
@@ -460,7 +472,7 @@ class ENS(BaseENS):
         node = self.namehash(normal_name)
 
         # handle extended resolver case
-        if _resolver_supports_interface(resolver, EXTENDED_RESOLVER_INTERFACE_ID):
+        if _resolver_supports_interface(resolver, ENS_EXTENDED_RESOLVER_INTERFACE_ID):
             contract_func_with_args = (fn_name, [node])
 
             calldata = resolver.encodeABI(*contract_func_with_args)
@@ -547,8 +559,44 @@ class ENS(BaseENS):
         addr = self.ens.caller.owner(normal_name_to_hash(REVERSE_REGISTRAR_DOMAIN))
         return self.w3.eth.contract(address=addr, abi=abis.REVERSE_REGISTRAR)
 
+    def _set_property(
+        self,
+        name: str,
+        func: "ContractFunction",
+        args: Sequence[Any],
+        transact: "TxParams" = None,
+    ) -> HexBytes:
+        if not transact:
+            transact = {}
+
+        owner = self.owner(name)
+        transact_from_owner = merge({"from": owner}, transact)
+
+        return func(*args).transact(transact_from_owner)
+
+
+def _validate_resolver_and_interface_id(
+    ens_name: str,
+    resolver: "Contract",
+    ens_interface_id: HexStr,
+    interface_name: str,
+) -> None:
+    if not resolver:
+        raise ResolverNotFound(
+            f"No resolver found for name `{ens_name}`. It is likely the name "
+            "contains an unsupported top level domain (tld)."
+        )
+    elif not _resolver_supports_interface(resolver, ens_interface_id):
+        raise UnsupportedFunction(
+            f"Resolver for name `{ens_name}` does not support the `{interface_name}` "
+            f"interface."
+        )
+
 
-def _resolver_supports_interface(resolver: "Contract", interface_id: HexStr) -> bool:
-    if not any("supportsInterface" in repr(func) for func in resolver.all_functions()):
-        return False
-    return resolver.caller.supportsInterface(interface_id)
+def _resolver_supports_interface(
+    resolver: "Contract",
+    ens_interface_id: HexStr,
+) -> bool:
+    return any(
+        "supportsInterface" in repr(func) for func in resolver.all_functions()
+    ) and resolver.caller.supportsInterface(ens_interface_id)
diff --git a/newsfragments/3030.feature.rst b/newsfragments/3030.feature.rst
new file mode 100644
index 00000000..c155f89d
--- /dev/null
+++ b/newsfragments/3030.feature.rst
@@ -0,0 +1,1 @@
+Add ENSIP-9 (Multichain Address Resolution) support for ``address()`` and ``setup_address()`` for ``ENS`` and ``AsyncENS`` classes.
diff --git a/newsfragments/3045.docs.rst b/newsfragments/3045.docs.rst
new file mode 100644
index 00000000..4148f1f1
--- /dev/null
+++ b/newsfragments/3045.docs.rst
@@ -0,0 +1,1 @@
+Add note to Release Notes about v5 end-of-life and v6.6.0 yank
diff --git a/setup.py b/setup.py
index 4bbf8b50..c06e9955 100644
--- a/setup.py
+++ b/setup.py
@@ -59,7 +59,7 @@ with open("./README.md") as readme:
 setup(
     name="web3",
     # *IMPORTANT*: Don't manually change the version here. Use the 'bumpversion' utility.
-    version="6.6.0",
+    version="6.6.1",
     description="""web3.py""",
     long_description_content_type="text/markdown",
     long_description=long_description,


Test patch:
diff --git a/tests/ens/conftest.py b/tests/ens/conftest.py
index a1e51ea8..919eb463 100644
--- a/tests/ens/conftest.py
+++ b/tests/ens/conftest.py
@@ -15,12 +15,6 @@ from ens import (
     AsyncENS,
 )
 from ens.contract_data import (
-    extended_resolver_abi,
-    extended_resolver_bytecode,
-    extended_resolver_bytecode_runtime,
-    offchain_resolver_abi,
-    offchain_resolver_bytecode,
-    offchain_resolver_bytecode_runtime,
     registrar_abi,
     registrar_bytecode,
     registrar_bytecode_runtime,
@@ -33,14 +27,26 @@ from ens.contract_data import (
     reverse_resolver_abi,
     reverse_resolver_bytecode,
     reverse_resolver_bytecode_runtime,
-    simple_resolver_abi,
-    simple_resolver_bytecode,
-    simple_resolver_bytecode_runtime,
 )
 from web3 import (
     AsyncWeb3,
     Web3,
 )
+from web3._utils.contract_sources.contract_data.extended_resolver import (
+    EXTENDED_RESOLVER_ABI,
+    EXTENDED_RESOLVER_BYTECODE,
+    EXTENDED_RESOLVER_RUNTIME,
+)
+from web3._utils.contract_sources.contract_data.offchain_resolver import (
+    OFFCHAIN_RESOLVER_ABI,
+    OFFCHAIN_RESOLVER_BYTECODE,
+    OFFCHAIN_RESOLVER_RUNTIME,
+)
+from web3._utils.contract_sources.contract_data.simple_resolver import (
+    SIMPLE_RESOLVER_ABI,
+    SIMPLE_RESOLVER_BYTECODE,
+    SIMPLE_RESOLVER_RUNTIME,
+)
 from web3.contract import (
     AsyncContract,
     Contract,
@@ -100,27 +106,27 @@ def PublicResolverFactory(w3):
 
 def SimpleResolver(w3):
     return w3.eth.contract(
-        bytecode=simple_resolver_bytecode,
-        bytecode_runtime=simple_resolver_bytecode_runtime,
-        abi=simple_resolver_abi,
+        abi=SIMPLE_RESOLVER_ABI,
+        bytecode=SIMPLE_RESOLVER_BYTECODE,
+        bytecode_runtime=SIMPLE_RESOLVER_RUNTIME,
         ContractFactoryClass=Contract,
     )
 
 
 def ExtendedResolver(w3):
     return w3.eth.contract(
-        bytecode=extended_resolver_bytecode,
-        bytecode_runtime=extended_resolver_bytecode_runtime,
-        abi=extended_resolver_abi,
+        abi=EXTENDED_RESOLVER_ABI,
+        bytecode=EXTENDED_RESOLVER_BYTECODE,
+        bytecode_runtime=EXTENDED_RESOLVER_RUNTIME,
         ContractFactoryClass=Contract,
     )
 
 
 def OffchainResolver(w3):
     return w3.eth.contract(
-        bytecode=offchain_resolver_bytecode,
-        bytecode_runtime=offchain_resolver_bytecode_runtime,
-        abi=offchain_resolver_abi,
+        abi=OFFCHAIN_RESOLVER_ABI,
+        bytecode=OFFCHAIN_RESOLVER_BYTECODE,
+        bytecode_runtime=OFFCHAIN_RESOLVER_RUNTIME,
         ContractFactoryClass=Contract,
     )
 
@@ -399,27 +405,27 @@ def async_public_resolver_factory(async_w3):
 
 def async_simple_resolver(async_w3):
     return async_w3.eth.contract(
-        bytecode=simple_resolver_bytecode,
-        bytecode_runtime=simple_resolver_bytecode_runtime,
-        abi=simple_resolver_abi,
+        abi=SIMPLE_RESOLVER_ABI,
+        bytecode=SIMPLE_RESOLVER_BYTECODE,
+        bytecode_runtime=SIMPLE_RESOLVER_RUNTIME,
         ContractFactoryClass=AsyncContract,
     )
 
 
 def async_extended_resolver(async_w3):
     return async_w3.eth.contract(
-        bytecode=extended_resolver_bytecode,
-        bytecode_runtime=extended_resolver_bytecode_runtime,
-        abi=extended_resolver_abi,
+        abi=EXTENDED_RESOLVER_ABI,
+        bytecode=EXTENDED_RESOLVER_BYTECODE,
+        bytecode_runtime=EXTENDED_RESOLVER_RUNTIME,
         ContractFactoryClass=AsyncContract,
     )
 
 
 def async_offchain_resolver(async_w3):
     return async_w3.eth.contract(
-        bytecode=offchain_resolver_bytecode,
-        bytecode_runtime=offchain_resolver_bytecode_runtime,
-        abi=offchain_resolver_abi,
+        abi=OFFCHAIN_RESOLVER_ABI,
+        bytecode=OFFCHAIN_RESOLVER_BYTECODE,
+        bytecode_runtime=OFFCHAIN_RESOLVER_RUNTIME,
         ContractFactoryClass=AsyncContract,
     )
 
diff --git a/tests/ens/test_get_text.py b/tests/ens/test_get_text.py
index 4676426d..6befbc36 100644
--- a/tests/ens/test_get_text.py
+++ b/tests/ens/test_get_text.py
@@ -79,7 +79,10 @@ def test_get_text_resolver_not_found(ens):
 
 
 def test_get_text_for_resolver_with_unsupported_function(ens):
-    with pytest.raises(UnsupportedFunction, match="does not support `text` function"):
+    with pytest.raises(
+        UnsupportedFunction,
+        match="does not support the `text` interface",
+    ):
         ens.get_text("simple-resolver.eth", "any_key")
 
 
@@ -156,5 +159,8 @@ async def test_async_get_text_resolver_not_found(async_ens):
 
 @pytest.mark.asyncio
 async def test_async_get_text_for_resolver_with_unsupported_function(async_ens):
-    with pytest.raises(UnsupportedFunction, match="does not support `text` function"):
+    with pytest.raises(
+        UnsupportedFunction,
+        match="does not support the `text` interface",
+    ):
         await async_ens.get_text("simple-resolver.eth", "any_key")
diff --git a/tests/ens/test_setup_address.py b/tests/ens/test_setup_address.py
index 8b0af291..d7df62b5 100644
--- a/tests/ens/test_setup_address.py
+++ b/tests/ens/test_setup_address.py
@@ -121,6 +121,17 @@ def test_setup_address_default_address_to_owner(ens):
     assert ens.address("default.tester.eth") == owner
 
 
+def test_setup_address_default_to_owner_for_multichain_address_resolution(ens):
+    ens.setup_address("leet.tester.eth", coin_type=1337)
+
+    # was never set up for ETH, so no address resolution expected
+    assert ens.address("leet.tester.eth") is None
+
+    # assert resolves for ``coin_type == 1337``
+    owner = ens.owner("tester.eth")
+    assert ens.address("leet.tester.eth", coin_type=1337) == owner
+
+
 def test_first_owner_upchain_identify(ens):
     # _first_owner should auto-select the name owner to send the transaction from
     addr = "0x5B2063246F2191f18F2675ceDB8b28102e957458"
@@ -229,6 +240,20 @@ async def test_async_setup_address_default_address_to_owner(async_ens):
     assert await async_ens.address("default.tester.eth") == owner
 
 
+@pytest.mark.asyncio
+async def test_async_setup_address_default_to_owner_for_multichain_address_resolution(
+    async_ens,
+):
+    await async_ens.setup_address("leet.tester.eth", coin_type=1337)
+
+    # was never set up for ETH, so no address resolution expected
+    assert await async_ens.address("leet.tester.eth") is None
+
+    # assert resolves for ``coin_type == 1337``
+    owner = await async_ens.owner("tester.eth")
+    assert await async_ens.address("leet.tester.eth", coin_type=1337) == owner
+
+
 @pytest.mark.asyncio
 async def test_async_first_owner_upchain_identify(async_ens):
     # _first_owner should auto-select the name owner to send the transaction