This repository has been archived by the owner on May 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathResolver.sol
278 lines (245 loc) · 9.96 KB
/
Resolver.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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
pragma solidity 0.5.12;
pragma experimental ABIEncoderV2;
import './CNSRegistry.sol';
import './util/SignatureUtil.sol';
import './controllers/MintingController.sol';
import './IResolver.sol';
import './IResolverReader.sol';
// solium-disable error-reason
contract Resolver is IResolverReader, SignatureUtil, IResolver {
event Set(uint256 indexed tokenId, string indexed keyIndex, string indexed valueIndex, string key, string value);
event NewKey(uint256 indexed tokenId, string indexed keyIndex, string key);
event ResetRecords(uint256 indexed tokenId);
// Mapping from token ID to preset id to key to value
mapping (uint256 => mapping (uint256 => mapping (string => string))) internal _records;
// Mapping from token ID to current preset id
mapping (uint256 => uint256) _tokenPresets;
// All keys that were set
mapping (uint256 => string) _hashedKeys;
MintingController internal _mintingController;
constructor(CNSRegistry registry, MintingController mintingController) public SignatureUtil(registry) {
require(address(registry) == mintingController.registry());
_mintingController = mintingController;
}
/**
* @dev Throws if called when not the resolver.
*/
modifier whenResolver(uint256 tokenId) {
require(address(this) == _registry.resolverOf(tokenId), "RESOLVER_DETACHED_FROM_DOMAIN");
_;
}
modifier whenApprovedOrOwner(uint256 tokenId) {
require(_registry.isApprovedOrOwner(msg.sender, tokenId), "SENDER_IS_NOT_APPROVED_OR_OWNER");
_;
}
function reset(uint256 tokenId) external whenApprovedOrOwner(tokenId) {
_setPreset(now, tokenId);
}
function resetFor(uint256 tokenId, bytes calldata signature) external {
_validate(keccak256(abi.encodeWithSelector(this.reset.selector, tokenId)), tokenId, signature);
_setPreset(now, tokenId);
}
/**
* @dev Function to get record.
* @param key The key to query the value of.
* @param tokenId The token id to fetch.
* @return The value string.
*/
function get(string memory key, uint256 tokenId) public view whenResolver(tokenId) returns (string memory) {
return _records[tokenId][_tokenPresets[tokenId]][key];
}
/**
* @dev Function to get key by provided hash. Keys hashes can be found in Sync event emitted by CNSRegistry.sol contract.
* @param keyHash The key to query the value of.
* @return The key string.
*/
function hashToKey(uint256 keyHash) public view returns (string memory) {
return _hashedKeys[keyHash];
}
/**
* @dev Function to get keys by provided key hashes. Keys hashes can be found in Sync event emitted by CNSRegistry.sol contract.
* @param hashes The key to query the value of.
* @return Keys
*/
function hashesToKeys(uint256[] memory hashes) public view returns (string[] memory) {
uint256 keyCount = hashes.length;
string[] memory values = new string[](keyCount);
for (uint256 i = 0; i < keyCount; i++) {
values[i] = hashToKey(hashes[i]);
}
return values;
}
/**
* @dev Function get value by provied key hash. Keys hashes can be found in Sync event emitted by CNSRegistry.sol contract.
* @param keyHash The key to query the value of.
* @param tokenId The token id to set.
* @return Key and value.
*/
function getByHash(uint256 keyHash, uint256 tokenId) public view whenResolver(tokenId) returns (string memory key, string memory value) {
key = hashToKey(keyHash);
value = get(key, tokenId);
}
/**
* @dev Function get values by provied key hashes. Keys hashes can be found in Sync event emitted by CNSRegistry.sol contract.
* @param keyHashes The key to query the value of.
* @param tokenId The token id to set.
* @return Keys and values.
*/
function getManyByHash(
uint256[] memory keyHashes,
uint256 tokenId
) public view whenResolver(tokenId) returns (string[] memory keys, string[] memory values) {
uint256 keyCount = keyHashes.length;
keys = new string[](keyCount);
values = new string[](keyCount);
for (uint256 i = 0; i < keyCount; i++) {
(keys[i], values[i]) = getByHash(keyHashes[i], tokenId);
}
}
function preconfigure(
string[] memory keys,
string[] memory values,
uint256 tokenId
) public {
require(_mintingController.isMinter(msg.sender), "SENDER_IS_NOT_MINTER");
_setMany(_tokenPresets[tokenId], keys, values, tokenId);
}
/**
* @dev Function to set record.
* @param key The key set the value of.
* @param value The value to set key to.
* @param tokenId The token id to set.
*/
function set(string calldata key, string calldata value, uint256 tokenId) external whenApprovedOrOwner(tokenId) {
_set(_tokenPresets[tokenId], key, value, tokenId);
}
/**
* @dev Function to set record on behalf of an address.
* @param key The key set the value of.
* @param value The value to set key to.
* @param tokenId The token id to set.
* @param signature The signature to verify the transaction with.
*/
function setFor(
string calldata key,
string calldata value,
uint256 tokenId,
bytes calldata signature
) external {
_validate(keccak256(abi.encodeWithSelector(this.set.selector, key, value, tokenId)), tokenId, signature);
_set(_tokenPresets[tokenId], key, value, tokenId);
}
/**
* @dev Function to get multiple record.
* @param keys The keys to query the value of.
* @param tokenId The token id to fetch.
* @return The values.
*/
function getMany(string[] calldata keys, uint256 tokenId) external view whenResolver(tokenId) returns (string[] memory) {
uint256 keyCount = keys.length;
string[] memory values = new string[](keyCount);
uint256 preset = _tokenPresets[tokenId];
for (uint256 i = 0; i < keyCount; i++) {
values[i] = _records[tokenId][preset][keys[i]];
}
return values;
}
function setMany(
string[] memory keys,
string[] memory values,
uint256 tokenId
) public whenApprovedOrOwner(tokenId) {
_setMany(_tokenPresets[tokenId], keys, values, tokenId);
}
/**
* @dev Function to set record on behalf of an address.
* @param keys The keys set the values of.
* @param values The values to set keys to.
* @param tokenId The token id to set.
* @param signature The signature to verify the transaction with.
*/
function setManyFor(
string[] memory keys,
string[] memory values,
uint256 tokenId,
bytes memory signature
) public {
_validate(keccak256(abi.encodeWithSelector(this.setMany.selector, keys, values, tokenId)), tokenId, signature);
_setMany(_tokenPresets[tokenId], keys, values, tokenId);
}
/**
* @dev Function to reset all domain records and set new ones.
* @param keys records keys.
* @param values records values.
* @param tokenId domain token id.
*/
function reconfigure(string[] memory keys, string[] memory values, uint256 tokenId) public whenApprovedOrOwner(tokenId) {
_reconfigure(keys, values, tokenId);
}
/**
* @dev Delegated version of reconfigure() function.
* @param keys records keys.
* @param values records values.
* @param tokenId domain token id.
* @param signature user signature.
*/
function reconfigureFor(
string[] memory keys,
string[] memory values,
uint256 tokenId,
bytes memory signature
) public {
_validate(keccak256(abi.encodeWithSelector(this.reconfigure.selector, keys, values, tokenId)), tokenId, signature);
_reconfigure(keys, values, tokenId);
}
// reset records
function _setPreset(uint256 presetId, uint256 tokenId) internal {
_tokenPresets[tokenId] = presetId;
_registry.sync(tokenId, 0); // notify registry that domain records were reset
emit ResetRecords(tokenId);
}
/**
* @dev Internal function to to set record. As opposed to set, this imposes no restrictions on msg.sender.
* @param preset preset to set key/values on
* @param key key of record to be set
* @param value value of record to be set
* @param tokenId uint256 ID of the token
*/
function _set(uint256 preset, string memory key, string memory value, uint256 tokenId) internal {
uint256 keyHash = uint256(keccak256(bytes(key)));
bool isNewKey = bytes(_records[tokenId][preset][key]).length == 0;
_registry.sync(tokenId, keyHash);
_records[tokenId][preset][key] = value;
if (bytes(_hashedKeys[keyHash]).length == 0) {
_hashedKeys[keyHash] = key;
}
if (isNewKey) {
emit NewKey(tokenId, key, key);
}
emit Set(tokenId, key, value, key, value);
}
/**
* @dev Internal function to to set multiple records. As opposed to setMany, this imposes
* no restrictions on msg.sender.
* @param preset preset to set key/values on
* @param keys keys of record to be set
* @param values values of record to be set
* @param tokenId uint256 ID of the token
*/
function _setMany(uint256 preset, string[] memory keys, string[] memory values, uint256 tokenId) internal {
uint256 keyCount = keys.length;
for (uint256 i = 0; i < keyCount; i++) {
_set(preset, keys[i], values[i], tokenId);
}
}
/**
* @dev Internal function to reset all domain records and set new ones.
* @param keys records keys.
* @param values records values.
* @param tokenId domain token id.
*/
function _reconfigure(string[] memory keys, string[] memory values, uint256 tokenId) internal {
_setPreset(now, tokenId);
_setMany(_tokenPresets[tokenId], keys, values, tokenId);
}
}