@@ -5,6 +5,7 @@ import "../wrapper/INameWrapper.sol";
5
5
import "@openzeppelin/contracts/utils/Address.sol " ;
6
6
import {IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
7
7
import {ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol " ;
8
+ import "hardhat/console.sol " ;
8
9
9
10
error Unavailable ();
10
11
error Unauthorised (bytes32 node );
@@ -13,6 +14,10 @@ error NameNotRegistered();
13
14
error InvalidTokenAddress (address );
14
15
error NameNotSetup (bytes32 node );
15
16
error DataMissing ();
17
+ error ParentExpired (bytes32 node );
18
+ error ParentNotWrapped (bytes32 node );
19
+ error ParentWillHaveExpired (bytes32 node );
20
+ error DurationTooLong (bytes32 node );
16
21
17
22
struct Name {
18
23
uint256 registrationFee; // per second
@@ -41,6 +46,11 @@ contract SubdomainRegistrar is ERC1155Holder {
41
46
_;
42
47
}
43
48
49
+ modifier canBeRegistered (bytes32 parentNode , uint64 duration ) {
50
+ _checkParent (parentNode, duration);
51
+ _;
52
+ }
53
+
44
54
function setupDomain (
45
55
bytes32 node ,
46
56
address token ,
@@ -71,6 +81,8 @@ contract SubdomainRegistrar is ERC1155Holder {
71
81
) public payable {
72
82
uint256 fee = duration * names[parentNode].registrationFee;
73
83
84
+ _checkParent (parentNode, duration);
85
+
74
86
if (fee > 0 ) {
75
87
if (IERC20 (names[parentNode].token).balanceOf (msg .sender ) < fee) {
76
88
revert InsufficientFunds ();
@@ -99,11 +111,7 @@ contract SubdomainRegistrar is ERC1155Holder {
99
111
bytes32 labelhash ,
100
112
uint64 duration
101
113
) external payable returns (uint64 newExpiry ) {
102
- bytes32 node = _makeNode (parentNode, labelhash);
103
- (, uint64 expiry ) = wrapper.getFuses (node);
104
- if (expiry < block .timestamp ) {
105
- revert NameNotRegistered ();
106
- }
114
+ _checkParent (parentNode, duration);
107
115
108
116
uint256 fee = duration * names[parentNode].registrationFee;
109
117
@@ -115,11 +123,7 @@ contract SubdomainRegistrar is ERC1155Holder {
115
123
);
116
124
}
117
125
118
- newExpiry = expiry += duration;
119
-
120
- wrapper.setChildFuses (parentNode, labelhash, 0 , newExpiry);
121
-
122
- emit NameRenewed (node, newExpiry);
126
+ _renew (parentNode, labelhash, duration);
123
127
}
124
128
125
129
function batchRegister (
@@ -137,6 +141,8 @@ contract SubdomainRegistrar is ERC1155Holder {
137
141
revert DataMissing ();
138
142
}
139
143
144
+ _checkParent (parentNode, duration);
145
+
140
146
uint256 fee = duration *
141
147
names[parentNode].registrationFee *
142
148
labels.length ;
@@ -166,8 +172,54 @@ contract SubdomainRegistrar is ERC1155Holder {
166
172
}
167
173
}
168
174
175
+ function batchRenew (
176
+ bytes32 parentNode ,
177
+ bytes32 [] calldata labelhashes ,
178
+ uint64 duration
179
+ ) external payable {
180
+ if (labelhashes.length == 0 ) {
181
+ revert DataMissing ();
182
+ }
183
+
184
+ _checkParent (parentNode, duration);
185
+
186
+ uint256 fee = duration *
187
+ names[parentNode].registrationFee *
188
+ labelhashes.length ;
189
+
190
+ if (fee > 0 ) {
191
+ if (IERC20 (names[parentNode].token).balanceOf (msg .sender ) < fee) {
192
+ revert InsufficientFunds ();
193
+ }
194
+
195
+ IERC20 (names[parentNode].token).transferFrom (
196
+ msg .sender ,
197
+ address (names[parentNode].beneficiary),
198
+ fee
199
+ );
200
+ }
201
+
202
+ for (uint256 i = 0 ; i < labelhashes.length ; i++ ) {
203
+ _renew (parentNode, labelhashes[i], duration);
204
+ }
205
+ }
206
+
169
207
/* Internal Functions */
170
208
209
+ function _checkParent (bytes32 node , uint256 duration ) internal {
210
+ try wrapper.getFuses (node) returns (uint32 , uint64 expiry ) {
211
+ if (expiry < block .timestamp ) {
212
+ revert ParentExpired (node);
213
+ }
214
+
215
+ if (duration + block .timestamp > expiry) {
216
+ revert ParentWillHaveExpired (node);
217
+ }
218
+ } catch {
219
+ revert ParentNotWrapped (node);
220
+ }
221
+ }
222
+
171
223
function _register (
172
224
bytes32 parentNode ,
173
225
string calldata label ,
@@ -209,6 +261,24 @@ contract SubdomainRegistrar is ERC1155Holder {
209
261
emit NameRegistered (node, uint64 (block .timestamp + duration));
210
262
}
211
263
264
+ function _renew (
265
+ bytes32 parentNode ,
266
+ bytes32 labelhash ,
267
+ uint64 duration
268
+ ) internal {
269
+ bytes32 node = _makeNode (parentNode, labelhash);
270
+ (, uint64 expiry ) = wrapper.getFuses (node);
271
+ if (expiry < block .timestamp ) {
272
+ revert NameNotRegistered ();
273
+ }
274
+
275
+ uint64 newExpiry = expiry += duration;
276
+
277
+ wrapper.setChildFuses (parentNode, labelhash, 0 , newExpiry);
278
+
279
+ emit NameRenewed (node, newExpiry);
280
+ }
281
+
212
282
function _setRecords (
213
283
bytes32 node ,
214
284
address resolver ,
0 commit comments