abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase {
  uint constant private COIN_TYPE_ETH = 60;

  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) virtual 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) virtual override public view returns (address payable) {
    bytes memory a = addr(node, COIN_TYPE_ETH);
    if(a.length == 0) {
      return payable(0);
    }
    return bytesToAddress(a);
  }

  function setAddr(bytes32 node, uint coinType, bytes memory a) virtual 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) virtual override public view returns(bytes memory) {
    return _addresses[node][coinType];
  }

  function bytesToAddress(bytes memory b) internal pure returns(address payable a) {
    require(b.length == 20);
    assembly {
      a := div(mload(add(b, 32)), exp(256, 12))
    }
  }

  function addressToBytes(address a) internal pure returns(bytes memory b) {
    b = new bytes(20);
    assembly {
      mstore(add(b, 32), mul(a, exp(256, 12)))
    }
  }
}
function setAddr(bytes32 node, address a) virtual external authorised(node) {
  setAddr(node, COIN_TYPE_ETH, addressToBytes(a));
}

/**
 * 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.
 */