--- eip: 2304 title: Multichain address resolution for ENS author: Nick Johnson type: Standards Track category: ERC status: Draft created: 2019-09-09 discussions-to: https://discuss.ens.domains/t/new-standard-proposal-ens-multicoin-support/1148 requires: 137 --- ## Abstract This EIP introduces the `address` field for ENS resolvers, which permits resolution of addresses for other blockchains via ENS. ## Motivation With the increasing uptake of ENS by multi-coin wallets, wallet authors have requested the ability to resolve addresses for non-Ethereum chains inside ENS. This specification standardises a way to enter and retrieve these addresses in a cross-client fashion. ## Specification A new accessor function for resolvers is specified: ``` function addr(bytes32 node, uint coinType) external view returns(bytes memory); ``` The EIP165 interface ID for this function is 0xf1cb7e06. When called on a resolver, this function must return the cryptocurrency address for the specified namehash and coin type. A zero-length string must be returned if the specified coin ID does not exist on the specified node. `coinType` is the cryptocurrency coin type index from [SLIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md). The return value is the cryptocurency address in binary format. For example, the Bitcoin address `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` is base58check-decoded and stored as the 21 bytes `0x0062e907b15cbf27d5425399ebf6f0fb50ebb88f18`, while the Ethereum address `0x314159265dd8dbb310642f98f50c066173c1259b` is hex-decoded and stored as the 20 bytes `0x314159265dd8dbb310642f98f50c066173c1259b`. In general, the native binary representation of the address should be used, without any checksum commonly used in the text representation. A new event for resolvers is defined: ``` event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress); ``` Resolvers MUST emit this event on each change to the address for a name and coin type. ### Recommended accessor functions The following function provides the recommended interface for changing the addresses stored for a node. Resolvers SHOULD implement this interface for setting addresses unless their needs dictate a different interface. ``` function setAddr(bytes32 node, uint coinType, bytes calldata addr); ``` `setAddr` adds or replaces the address for the given node and coin type. The parameters for this function are as per those described in `addr()` above. This function emits an `AddressChanged` event with the new address; see also the backwards compatibility section below for resolvers that also support `addr(bytes32)`. ### Example An example implementation of a resolver that supports this EIP is provided here: ``` pragma solidity ^0.5.8; contract AddrResolver is ResolverBase { bytes4 constant private ADDR_INTERFACE_ID = 0x3b3b57de; bytes4 constant private ADDRESS_INTERFACE_ID = 0xf1cb7e06; uint constant private COIN_TYPE_ETH = 60; event AddrChanged(bytes32 indexed node, address a); event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress); mapping(bytes32=>mapping(uint=>bytes)) _addresses; /** * Sets the address associated with an ENS node. * May only be called by the owner of that node in the ENS registry. * @param node The node to update. * @param a The address to set. */ function setAddr(bytes32 node, address a) external authorised(node) { setAddr(node, COIN_TYPE_ETH, addressToBytes(a)); } /** * Returns the address associated with an ENS node. * @param node The ENS node to query. * @return The associated address. */ function addr(bytes32 node) public view returns (address) { bytes memory a = addr(node, COIN_TYPE_ETH); if(a.length == 0) { return address(0); } return bytesToAddress(a); } function setAddr(bytes32 node, uint coinType, bytes memory a) public authorised(node) { emit AddressChanged(node, coinType, a); if(coinType == COIN_TYPE_ETH) { emit AddrChanged(node, bytesToAddress(a)); } _addresses[node][coinType] = a; } function addr(bytes32 node, uint coinType) public view returns(bytes memory) { return _addresses[node][coinType]; } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == ADDR_INTERFACE_ID || interfaceID == ADDRESS_INTERFACE_ID || super.supportsInterface(interfaceID); } } ``` ### Implementation An implementation of this interface is provided in the [ensdomains/resolvers](https://github.com/ensdomains/resolvers/) repository. ## Backwards Compatibility If the resolver supports the `addr(bytes32)` interface defined in EIP137, the resolver MUST treat this as a special case of this new specification in the following ways: 1. The value returned by `addr(node)` from EIP137 should always match the value returned by `addr(node, 60)` (60 is the coin type ID for Ethereum). 2. Anything that causes the `AddrChanged` event from EIP137 to be emitted must also emit an `AddressChanged` event from this EIP, with the `coinType` specified as 60, and vice-versa. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).