-
Notifications
You must be signed in to change notification settings - Fork 406
/
ReverseRegistrar.sol
190 lines (169 loc) · 6.35 KB
/
ReverseRegistrar.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
pragma solidity >=0.8.4;
import "../registry/ENS.sol";
import "./IReverseRegistrar.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../root/Controllable.sol";
abstract contract NameResolver {
function setName(bytes32 node, string memory name) public virtual;
}
bytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000;
bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;
// namehash('addr.reverse')
contract ReverseRegistrar is Ownable, Controllable, IReverseRegistrar {
ENS public immutable ens;
NameResolver public defaultResolver;
event ReverseClaimed(address indexed addr, bytes32 indexed node);
event DefaultResolverChanged(NameResolver indexed resolver);
/**
* @dev Constructor
* @param ensAddr The address of the ENS registry.
*/
constructor(ENS ensAddr) {
ens = ensAddr;
// Assign ownership of the reverse record to our deployer
ReverseRegistrar oldRegistrar = ReverseRegistrar(
ensAddr.owner(ADDR_REVERSE_NODE)
);
if (address(oldRegistrar) != address(0x0)) {
oldRegistrar.claim(msg.sender);
}
}
modifier authorised(address addr) {
require(
addr == msg.sender ||
controllers[msg.sender] ||
ens.isApprovedForAll(addr, msg.sender) ||
ownsContract(addr),
"ReverseRegistrar: Caller is not a controller or authorised by address or the address itself"
);
_;
}
function setDefaultResolver(address resolver) public override onlyOwner {
require(
address(resolver) != address(0),
"ReverseRegistrar: Resolver address must not be 0"
);
defaultResolver = NameResolver(resolver);
emit DefaultResolverChanged(NameResolver(resolver));
}
/**
* @dev Transfers ownership of the reverse ENS record associated with the
* calling account.
* @param owner The address to set as the owner of the reverse record in ENS.
* @return The ENS node hash of the reverse record.
*/
function claim(address owner) public override returns (bytes32) {
return claimForAddr(msg.sender, owner, address(defaultResolver));
}
/**
* @dev Transfers ownership of the reverse ENS record associated with the
* calling account.
* @param addr The reverse record to set
* @param owner The address to set as the owner of the reverse record in ENS.
* @param resolver The resolver of the reverse node
* @return The ENS node hash of the reverse record.
*/
function claimForAddr(
address addr,
address owner,
address resolver
) public override authorised(addr) returns (bytes32) {
bytes32 labelHash = sha3HexAddress(addr);
bytes32 reverseNode = keccak256(
abi.encodePacked(ADDR_REVERSE_NODE, labelHash)
);
emit ReverseClaimed(addr, reverseNode);
ens.setSubnodeRecord(ADDR_REVERSE_NODE, labelHash, owner, resolver, 0);
return reverseNode;
}
/**
* @dev Transfers ownership of the reverse ENS record associated with the
* calling account.
* @param owner The address to set as the owner of the reverse record in ENS.
* @param resolver The address of the resolver to set; 0 to leave unchanged.
* @return The ENS node hash of the reverse record.
*/
function claimWithResolver(
address owner,
address resolver
) public override returns (bytes32) {
return claimForAddr(msg.sender, owner, resolver);
}
/**
* @dev Sets the `name()` record for the reverse ENS record associated with
* the calling account. First updates the resolver to the default reverse
* resolver if necessary.
* @param name The name to set for this address.
* @return The ENS node hash of the reverse record.
*/
function setName(string memory name) public override returns (bytes32) {
return
setNameForAddr(
msg.sender,
msg.sender,
address(defaultResolver),
name
);
}
/**
* @dev Sets the `name()` record for the reverse ENS record associated with
* the account provided. Updates the resolver to a designated resolver
* Only callable by controllers and authorised users
* @param addr The reverse record to set
* @param owner The owner of the reverse node
* @param resolver The resolver of the reverse node
* @param name The name to set for this address.
* @return The ENS node hash of the reverse record.
*/
function setNameForAddr(
address addr,
address owner,
address resolver,
string memory name
) public override returns (bytes32) {
bytes32 node = claimForAddr(addr, owner, resolver);
NameResolver(resolver).setName(node, name);
return node;
}
/**
* @dev Returns the node hash for a given account's reverse records.
* @param addr The address to hash
* @return The ENS node hash.
*/
function node(address addr) public pure override returns (bytes32) {
return
keccak256(
abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr))
);
}
/**
* @dev An optimised function to compute the sha3 of the lower-case
* hexadecimal representation of an Ethereum address.
* @param addr The address to hash
* @return ret The SHA3 hash of the lower-case hexadecimal encoding of the
* input address.
*/
function sha3HexAddress(address addr) private pure returns (bytes32 ret) {
assembly {
for {
let i := 40
} gt(i, 0) {
} {
i := sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr := div(addr, 0x10)
i := sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr := div(addr, 0x10)
}
ret := keccak256(0, 40)
}
}
function ownsContract(address addr) internal view returns (bool) {
try Ownable(addr).owner() returns (address owner) {
return owner == msg.sender;
} catch {
return false;
}
}
}