@@ -24,12 +24,21 @@ abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase
24
24
// keccak256(abi.encode(uint256(keccak256("addr.resolver.storage")) - 1)) & ~bytes32(uint256(0xff));
25
25
bytes32 constant ADDR_RESOLVER_STORAGE = 0x1871a91a9a944f867849820431bb11c2d1625edae573523bceb5b38b8b8a7500 ;
26
26
27
+ /// @notice Ethereum chain id.
28
+ uint32 constant CHAIN_ID_ETH = 1 ;
29
+
27
30
/// @notice Ethereum mainnet network-as-cointype.
28
31
uint256 private constant COIN_TYPE_ETH = 60 ;
29
32
33
+ /// @notice EVM default cointype per ENSIP-19.
34
+ uint256 constant COIN_TYPE_DEFAULT = 1 << 31 ; // 0x8000_0000
35
+
30
36
/// @notice Thrown when an invalid bytes length is detected.
31
37
error InvalidBytesLength ();
32
38
39
+ /// @notice Thrown when setting an invalid EVM address for a valid EVM cointype.
40
+ error InvalidEVMAddress (bytes a );
41
+
33
42
/// @notice Sets the address associated with an ENS node.
34
43
///
35
44
/// @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
46
55
/// @param coinType The coinType for this address.
47
56
/// @param a The network-agnostic bytes of the address.
48
57
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
+ }
49
61
emit AddressChanged (node, coinType, a);
50
62
if (coinType == COIN_TYPE_ETH) {
51
- emit AddrChanged (node, bytesToAddress (a ));
63
+ emit AddrChanged (node, address ( bytes20 (a) ));
52
64
}
53
65
_getAddrResolverStorage ().versionable_addresses[_getResolverBaseStorage ().recordVersions[node]][node][coinType]
54
66
= a;
@@ -71,14 +83,20 @@ abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase
71
83
72
84
/// @notice Returns the address of the `node` for a specified `coinType`.
73
85
///
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.
75
88
///
76
89
/// @param node The ENS node to update.
77
90
/// @param coinType The coinType to fetch.
78
91
///
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
+ }
82
100
}
83
101
84
102
/// @notice ERC-165 compliance.
@@ -103,6 +121,28 @@ abstract contract AddrResolver is IAddrResolver, IAddressResolver, ResolverBase
103
121
}
104
122
}
105
123
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
+
106
146
/// @notice EIP-7201 storage pointer fetch helper.
107
147
function _getAddrResolverStorage () internal pure returns (AddrResolverStorage storage $) {
108
148
assembly {
0 commit comments