EIP 2304: Multichain address resolution for ENS Source

AuthorNick Johnson
Discussions-Tohttps://discuss.ens.domains/t/new-standard-proposal-ens-multicoin-support/1148
StatusDraft
TypeStandards Track
CategoryERC
Created2019-09-09
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.

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.

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 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 and related rights waived via CC0.