@@ -24,12 +24,21 @@ abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase
2424 // keccak256(abi.encode(uint256(keccak256("addr.resolver.storage")) - 1)) & ~bytes32(uint256(0xff));
2525 bytes32 constant ADDR_RESOLVER_STORAGE = 0x1871a91a9a944f867849820431bb11c2d1625edae573523bceb5b38b8b8a7500 ;
2626
27+ /// @notice Ethereum chain id.
28+ uint32 constant CHAIN_ID_ETH = 1 ;
29+
2730 /// @notice Ethereum mainnet network-as-cointype.
2831 uint256 private constant COIN_TYPE_ETH = 60 ;
2932
33+ /// @notice EVM default cointype per ENSIP-19.
34+ uint256 constant COIN_TYPE_DEFAULT = 1 << 31 ; // 0x8000_0000
35+
3036 /// @notice Thrown when an invalid bytes length is detected.
3137 error InvalidBytesLength ();
3238
39+ /// @notice Thrown when setting an invalid EVM address for a valid EVM cointype.
40+ error InvalidEVMAddress (bytes a );
41+
3342 /// @notice Sets the address associated with an ENS node.
3443 ///
3544 /// @dev May only be called by the owner of that node in the ENS registry.
@@ -46,9 +55,12 @@ abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase
4655 /// @param coinType The coinType for this address.
4756 /// @param a The network-agnostic bytes of the address.
4857 function setAddr (bytes32 node , uint256 coinType , bytes memory a ) public virtual authorized (node) {
58+ if (a.length != 0 && a.length != 20 && isEVMCoinType (coinType)) {
59+ revert InvalidEVMAddress (a);
60+ }
4961 emit AddressChanged (node, coinType, a);
5062 if (coinType == COIN_TYPE_ETH) {
51- emit AddrChanged (node, bytesToAddress (a ));
63+ emit AddrChanged (node, address ( bytes20 (a) ));
5264 }
5365 _getAddrResolverStorage ().versionable_addresses[_getResolverBaseStorage ().recordVersions[node]][node][coinType]
5466 = a;
@@ -71,14 +83,20 @@ abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase
7183
7284 /// @notice Returns the address of the `node` for a specified `coinType`.
7385 ///
74- /// @dev Complies with ENSIP-9 and ENSIP-11.
86+ /// @dev Complies with ENSIP-9, ENSIP-11 and ENSIP-19.
87+ /// Will return `default` address if there is no address set for a specific EVM cointype.
7588 ///
7689 /// @param node The ENS node to update.
7790 /// @param coinType The coinType to fetch.
7891 ///
79- /// @return The address of the specified `node` for the specified `coinType`.
80- function addr (bytes32 node , uint256 coinType ) public view virtual override returns (bytes memory ) {
81- return _getAddrResolverStorage ().versionable_addresses[_getResolverBaseStorage ().recordVersions[node]][node][coinType];
92+ /// @return addressBytes The address of the specified `node` for the specified `coinType`.
93+ function addr (bytes32 node , uint256 coinType ) public view virtual override returns (bytes memory addressBytes ) {
94+ mapping (uint256 coinType = > bytes addr ) storage addrs =
95+ _getAddrResolverStorage ().versionable_addresses[_getResolverBaseStorage ().recordVersions[node]][node];
96+ addressBytes = addrs[coinType];
97+ if (addressBytes.length == 0 && chainFromCoinType (coinType) > 0 ) {
98+ addressBytes = addrs[COIN_TYPE_DEFAULT];
99+ }
82100 }
83101
84102 /// @notice ERC-165 compliance.
@@ -103,6 +121,28 @@ abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase
103121 }
104122 }
105123
124+ /// @notice Fetch the uint32 coinType from an EVM coinType.
125+ ///
126+ /// @dev Extract Chain ID from `coinType`.
127+ ///
128+ /// @param coinType The coin type.
129+ ///
130+ /// @return The Chain ID or 0 if non-EVM Chain.
131+ function chainFromCoinType (uint256 coinType ) internal pure returns (uint32 ) {
132+ if (coinType == COIN_TYPE_ETH) return CHAIN_ID_ETH;
133+ coinType ^= COIN_TYPE_DEFAULT;
134+ return uint32 (coinType < COIN_TYPE_DEFAULT ? coinType : 0 );
135+ }
136+
137+ /// @notice Determine if `coinType` is for an EVM address.
138+ ///
139+ /// @param coinType The network as a coinType.
140+ ///
141+ /// @return `true` if coinType represents an EVM address, else `false`.
142+ function isEVMCoinType (uint256 coinType ) internal pure returns (bool ) {
143+ return coinType == COIN_TYPE_DEFAULT || chainFromCoinType (coinType) > 0 ;
144+ }
145+
106146 /// @notice EIP-7201 storage pointer fetch helper.
107147 function _getAddrResolverStorage () internal pure returns (AddrResolverStorage storage $) {
108148 assembly {
0 commit comments