@evvm/testnet-contracts 2.1.3 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +355 -55
  3. package/contracts/evvm/Evvm.sol +39 -38
  4. package/contracts/evvm/lib/ErrorsLib.sol +2 -1
  5. package/contracts/evvm/lib/EvvmStorage.sol +2 -0
  6. package/contracts/evvm/lib/EvvmStructs.sol +27 -1
  7. package/contracts/evvm/lib/SignatureUtils.sol +14 -17
  8. package/contracts/nameService/NameService.sol +124 -366
  9. package/contracts/nameService/lib/ErrorsLib.sol +2 -8
  10. package/contracts/nameService/lib/IdentityValidation.sol +182 -0
  11. package/contracts/nameService/lib/NameServiceStructs.sol +69 -0
  12. package/contracts/nameService/lib/SignatureUtils.sol +47 -41
  13. package/contracts/p2pSwap/P2PSwap.sol +54 -535
  14. package/contracts/p2pSwap/lib/P2PSwapStructs.sol +59 -0
  15. package/contracts/p2pSwap/lib/SignatureUtils.sol +16 -18
  16. package/contracts/staking/Estimator.sol +7 -6
  17. package/contracts/staking/Staking.sol +70 -159
  18. package/contracts/staking/lib/ErrorsLib.sol +0 -1
  19. package/contracts/staking/lib/SignatureUtils.sol +7 -36
  20. package/contracts/staking/lib/StakingStructs.sol +94 -0
  21. package/contracts/treasury/Treasury.sol +18 -20
  22. package/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +88 -35
  23. package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +81 -47
  24. package/contracts/treasuryTwoChains/lib/ErrorsLib.sol +2 -0
  25. package/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +3 -14
  26. package/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +3 -7
  27. package/contracts/treasuryTwoChains/lib/SignatureUtils.sol +12 -14
  28. package/interfaces/IEstimator.sol +7 -50
  29. package/interfaces/IEvvm.sol +17 -91
  30. package/interfaces/INameService.sol +37 -88
  31. package/interfaces/IP2PSwap.sol +19 -15
  32. package/interfaces/IStaking.sol +20 -50
  33. package/interfaces/ITreasury.sol +1 -4
  34. package/interfaces/ITreasuryExternalChainStation.sol +11 -15
  35. package/interfaces/ITreasuryHostChainStation.sol +7 -10
  36. package/library/Erc191TestBuilder.sol +56 -57
  37. package/library/EvvmService.sol +40 -0
  38. package/library/primitives/IERC20.sol +79 -0
  39. package/library/primitives/Math.sol +415 -0
  40. package/library/primitives/SignatureRecover.sol +42 -0
  41. package/library/utils/AdvancedStrings.sol +89 -0
  42. package/library/utils/GovernanceUtils.sol +81 -0
  43. package/library/utils/SignatureUtil.sol +29 -0
  44. package/library/utils/nonces/AsyncNonce.sol +32 -0
  45. package/library/utils/nonces/SyncNonce.sol +27 -0
  46. package/library/utils/service/EvvmPayments.sol +77 -0
  47. package/library/utils/service/StakingServiceUtils.sol +32 -0
  48. package/package.json +11 -13
  49. package/contracts/evvm/EvvmLegacy.sol +0 -1553
  50. package/library/AdvancedStrings.sol +0 -77
  51. package/library/SignatureRecover.sol +0 -140
  52. package/library/StakingServiceHooks.sol +0 -116
@@ -56,78 +56,36 @@ pragma solidity ^0.8.0;
56
56
  * - Marketplace takes 0.5% fee on username sales
57
57
  */
58
58
 
59
- import {Evvm} from "@evvm/testnet-contracts/contracts/evvm/Evvm.sol";
60
- import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
61
- import {AdvancedStrings} from "@evvm/testnet-contracts/library/AdvancedStrings.sol";
62
- import {ErrorsLib} from "@evvm/testnet-contracts/contracts/nameService/lib/ErrorsLib.sol";
63
- import {SignatureUtils} from "@evvm/testnet-contracts/contracts/nameService/lib/SignatureUtils.sol";
59
+ import {IEvvm} from "@evvm/testnet-contracts/interfaces/IEvvm.sol";
60
+ import {
61
+ AsyncNonce
62
+ } from "@evvm/testnet-contracts/library/utils/nonces/AsyncNonce.sol";
63
+ import {
64
+ NameServiceStructs
65
+ } from "@evvm/testnet-contracts/contracts/nameService/lib/NameServiceStructs.sol";
66
+ import {
67
+ AdvancedStrings
68
+ } from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
69
+ import {
70
+ ErrorsLib
71
+ } from "@evvm/testnet-contracts/contracts/nameService/lib/ErrorsLib.sol";
72
+ import {
73
+ SignatureUtils
74
+ } from "@evvm/testnet-contracts/contracts/nameService/lib/SignatureUtils.sol";
75
+ import {
76
+ IdentityValidation
77
+ } from "@evvm/testnet-contracts/contracts/nameService/lib/IdentityValidation.sol";
78
+
79
+ contract NameService is AsyncNonce, NameServiceStructs {
80
+ /// @dev Time delay constant for accepting proposals
81
+ uint256 constant TIME_TO_ACCEPT_PROPOSAL = 1 days;
64
82
 
65
- contract NameService {
66
- /**
67
- * @dev Struct for managing address change proposals with time delay
68
- * @param current Currently active address
69
- * @param proposal Proposed new address waiting for approval
70
- * @param timeToAccept Timestamp when the proposal can be accepted
71
- */
72
- struct AddressTypeProposal {
73
- address current;
74
- address proposal;
75
- uint256 timeToAccept;
76
- }
77
-
78
- /**
79
- * @dev Struct for managing uint256 value proposals with time delay
80
- * @param current Currently active value
81
- * @param proposal Proposed new value waiting for approval
82
- * @param timeToAccept Timestamp when the proposal can be accepted
83
- */
84
- struct UintTypeProposal {
85
- uint256 current;
86
- uint256 proposal;
87
- uint256 timeToAccept;
88
- }
89
-
90
- /**
91
- * @dev Struct for managing boolean flag changes with time delay
92
- * @param flag Current boolean state
93
- * @param timeToAcceptChange Timestamp when the flag change can be executed
94
- */
95
- struct BoolTypeProposal {
96
- bool flag;
97
- uint256 timeToAcceptChange;
98
- }
99
-
100
- /**
101
- * @dev Core metadata for each registered identity/username
102
- * @param owner Address that owns this identity
103
- * @param expireDate Timestamp when the registration expires
104
- * @param customMetadataMaxSlots Number of custom metadata entries stored
105
- * @param offerMaxSlots Maximum number of offers that have been made
106
- * @param flagNotAUsername Flag indicating if this is a pre-registration (0x01) or actual username (0x00)
107
- */
108
- struct IdentityBaseMetadata {
109
- address owner;
110
- uint256 expireDate;
111
- uint256 customMetadataMaxSlots;
112
- uint256 offerMaxSlots;
113
- bytes1 flagNotAUsername;
114
- }
115
-
116
- /// @dev Mapping from username to its core metadata and registration details
117
- mapping(string username => IdentityBaseMetadata basicMetadata)
118
- private identityDetails;
83
+ /// @dev Constant address representing the Principal Token in the EVVM ecosystem
84
+ address private constant PRINCIPAL_TOKEN_ADDRESS =
85
+ 0x0000000000000000000000000000000000000001;
119
86
 
120
- /**
121
- * @dev Metadata for marketplace offers on usernames
122
- * @param offerer Address making the offer
123
- * @param expireDate Timestamp when the offer expires
124
- * @param amount Amount offered in Principal Tokens (after 0.5% marketplace fee deduction)
125
- */
126
- struct OfferMetadata {
127
- address offerer;
128
- uint256 expireDate;
129
- uint256 amount;
130
- }
87
+ /// @dev Amount of Principal Tokens locked in pending marketplace offers
88
+ uint256 private principalTokenTokenLockedForWithdrawOffers;
131
89
 
132
90
  /// @dev Nested mapping: username => offer ID => offer details
133
91
  mapping(string username => mapping(uint256 id => OfferMetadata))
@@ -137,9 +95,6 @@ contract NameService {
137
95
  mapping(string username => mapping(uint256 numberKey => string customValue))
138
96
  private identityCustomMetadata;
139
97
 
140
- /// @dev Mapping to track used nonces per address to prevent replay attacks
141
- mapping(address => mapping(uint256 => bool)) private nameServiceNonce;
142
-
143
98
  /// @dev Proposal system for token withdrawal amounts with time delay
144
99
  UintTypeProposal amountToWithdrawTokens;
145
100
 
@@ -149,12 +104,11 @@ contract NameService {
149
104
  /// @dev Proposal system for admin address changes with time delay
150
105
  AddressTypeProposal admin;
151
106
 
152
- /// @dev Constant address representing the Principal Token in the EVVM ecosystem
153
- address private constant PRINCIPAL_TOKEN_ADDRESS =
154
- 0x0000000000000000000000000000000000000001;
107
+ /// @dev Mapping from username to its core metadata and registration details
108
+ mapping(string username => IdentityBaseMetadata basicMetadata)
109
+ private identityDetails;
155
110
 
156
- /// @dev Amount of Principal Tokens locked in pending marketplace offers
157
- uint256 private principalTokenTokenLockedForWithdrawOffers;
111
+ IEvvm private evvm;
158
112
 
159
113
  /// @dev Restricts function access to the current admin address only
160
114
  modifier onlyAdmin() {
@@ -171,14 +125,6 @@ contract NameService {
171
125
  _;
172
126
  }
173
127
 
174
- /// @dev Ensures the nonce hasn't been used before to prevent replay attacks
175
- modifier verifyIfNonceIsAvailable(address _user, uint256 _nonce) {
176
- if (nameServiceNonce[_user][_nonce])
177
- revert ErrorsLib.NonceAlreadyUsed();
178
-
179
- _;
180
- }
181
-
182
128
  /**
183
129
  * @notice Initializes the NameService contract
184
130
  * @dev Sets up the EVVM integration and initial admin
@@ -188,6 +134,7 @@ contract NameService {
188
134
  constructor(address _evvmAddress, address _initialOwner) {
189
135
  evvmAddress.current = _evvmAddress;
190
136
  admin.current = _initialOwner;
137
+ evvm = IEvvm(_evvmAddress);
191
138
  }
192
139
 
193
140
  /**
@@ -211,10 +158,10 @@ contract NameService {
211
158
  uint256 nonce_EVVM,
212
159
  bool priorityFlag_EVVM,
213
160
  bytes memory signature_EVVM
214
- ) public verifyIfNonceIsAvailable(user, nonce) {
161
+ ) external {
215
162
  if (
216
163
  !SignatureUtils.verifyMessageSignedForPreRegistrationUsername(
217
- Evvm(evvmAddress.current).getEvvmID(),
164
+ IEvvm(evvmAddress.current).getEvvmID(),
218
165
  user,
219
166
  hashPreRegisteredUsername,
220
167
  nonce,
@@ -222,6 +169,8 @@ contract NameService {
222
169
  )
223
170
  ) revert ErrorsLib.InvalidSignatureOnNameService();
224
171
 
172
+ verifyAsyncNonce(user, nonce);
173
+
225
174
  if (priorityFee_EVVM > 0) {
226
175
  makePay(
227
176
  user,
@@ -246,12 +195,12 @@ contract NameService {
246
195
  flagNotAUsername: 0x01
247
196
  });
248
197
 
249
- nameServiceNonce[user][nonce] = true;
198
+ markAsyncNonceAsUsed(user, nonce);
250
199
 
251
- if (Evvm(evvmAddress.current).isAddressStaker(msg.sender)) {
200
+ if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
252
201
  makeCaPay(
253
202
  msg.sender,
254
- Evvm(evvmAddress.current).getRewardAmount() + priorityFee_EVVM
203
+ IEvvm(evvmAddress.current).getRewardAmount() + priorityFee_EVVM
255
204
  );
256
205
  }
257
206
  }
@@ -279,16 +228,18 @@ contract NameService {
279
228
  uint256 nonce_EVVM,
280
229
  bool priorityFlag_EVVM,
281
230
  bytes memory signature_EVVM
282
- ) public verifyIfNonceIsAvailable(user, nonce) {
283
- if (admin.current != user) isValidUsername(username);
231
+ ) external {
232
+ if (
233
+ admin.current != user &&
234
+ !IdentityValidation.isValidUsername(username)
235
+ ) revert ErrorsLib.InvalidUsername();
284
236
 
285
- if (!isUsernameAvailable(username)) {
237
+ if (!isUsernameAvailable(username))
286
238
  revert ErrorsLib.UsernameAlreadyRegistered();
287
- }
288
239
 
289
240
  if (
290
241
  !SignatureUtils.verifyMessageSignedForRegistrationUsername(
291
- Evvm(evvmAddress.current).getEvvmID(),
242
+ IEvvm(evvmAddress.current).getEvvmID(),
292
243
  user,
293
244
  username,
294
245
  clowNumber,
@@ -297,6 +248,8 @@ contract NameService {
297
248
  )
298
249
  ) revert ErrorsLib.InvalidSignatureOnNameService();
299
250
 
251
+ verifyAsyncNonce(user, nonce);
252
+
300
253
  makePay(
301
254
  user,
302
255
  getPriceOfRegistration(username),
@@ -324,12 +277,12 @@ contract NameService {
324
277
  flagNotAUsername: 0x00
325
278
  });
326
279
 
327
- nameServiceNonce[user][nonce] = true;
280
+ markAsyncNonceAsUsed(user, nonce);
328
281
 
329
- if (Evvm(evvmAddress.current).isAddressStaker(msg.sender)) {
282
+ if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
330
283
  makeCaPay(
331
284
  msg.sender,
332
- (50 * Evvm(evvmAddress.current).getRewardAmount()) +
285
+ (50 * IEvvm(evvmAddress.current).getRewardAmount()) +
333
286
  priorityFee_EVVM
334
287
  );
335
288
  }
@@ -363,7 +316,7 @@ contract NameService {
363
316
  uint256 nonce_EVVM,
364
317
  bool priorityFlag_EVVM,
365
318
  bytes memory signature_EVVM
366
- ) public verifyIfNonceIsAvailable(user, nonce) returns (uint256 offerID) {
319
+ ) external returns (uint256 offerID) {
367
320
  if (
368
321
  identityDetails[username].flagNotAUsername == 0x01 ||
369
322
  !verifyIfIdentityExists(username) ||
@@ -373,7 +326,7 @@ contract NameService {
373
326
 
374
327
  if (
375
328
  !SignatureUtils.verifyMessageSignedForMakeOffer(
376
- Evvm(evvmAddress.current).getEvvmID(),
329
+ IEvvm(evvmAddress.current).getEvvmID(),
377
330
  user,
378
331
  username,
379
332
  expireDate,
@@ -383,6 +336,8 @@ contract NameService {
383
336
  )
384
337
  ) revert ErrorsLib.InvalidSignatureOnNameService();
385
338
 
339
+ verifyAsyncNonce(user, nonce);
340
+
386
341
  makePay(
387
342
  user,
388
343
  amount,
@@ -404,7 +359,7 @@ contract NameService {
404
359
 
405
360
  makeCaPay(
406
361
  msg.sender,
407
- Evvm(evvmAddress.current).getRewardAmount() +
362
+ IEvvm(evvmAddress.current).getRewardAmount() +
408
363
  ((amount * 125) / 100_000) +
409
364
  priorityFee_EVVM
410
365
  );
@@ -418,7 +373,7 @@ contract NameService {
418
373
  identityDetails[username].offerMaxSlots++;
419
374
  }
420
375
 
421
- nameServiceNonce[user][nonce] = true;
376
+ markAsyncNonceAsUsed(user, nonce);
422
377
  }
423
378
 
424
379
  /**
@@ -444,13 +399,13 @@ contract NameService {
444
399
  uint256 nonce_EVVM,
445
400
  bool priorityFlag_EVVM,
446
401
  bytes memory signature_EVVM
447
- ) public verifyIfNonceIsAvailable(user, nonce) {
402
+ ) external {
448
403
  if (usernameOffers[username][offerID].offerer != user)
449
404
  revert ErrorsLib.UserIsNotOwnerOfOffer();
450
405
 
451
406
  if (
452
407
  !SignatureUtils.verifyMessageSignedForWithdrawOffer(
453
- Evvm(evvmAddress.current).getEvvmID(),
408
+ IEvvm(evvmAddress.current).getEvvmID(),
454
409
  user,
455
410
  username,
456
411
  offerID,
@@ -459,6 +414,8 @@ contract NameService {
459
414
  )
460
415
  ) revert ErrorsLib.InvalidSignatureOnNameService();
461
416
 
417
+ verifyAsyncNonce(user, nonce);
418
+
462
419
  if (priorityFee_EVVM > 0) {
463
420
  makePay(
464
421
  user,
@@ -476,7 +433,7 @@ contract NameService {
476
433
 
477
434
  makeCaPay(
478
435
  msg.sender,
479
- Evvm(evvmAddress.current).getRewardAmount() +
436
+ IEvvm(evvmAddress.current).getRewardAmount() +
480
437
  ((usernameOffers[username][offerID].amount * 1) / 796) +
481
438
  priorityFee_EVVM
482
439
  );
@@ -485,7 +442,7 @@ contract NameService {
485
442
  (usernameOffers[username][offerID].amount) +
486
443
  (((usernameOffers[username][offerID].amount * 1) / 199) / 4);
487
444
 
488
- nameServiceNonce[user][nonce] = true;
445
+ markAsyncNonceAsUsed(user, nonce);
489
446
  }
490
447
 
491
448
  /**
@@ -511,11 +468,7 @@ contract NameService {
511
468
  uint256 nonce_EVVM,
512
469
  bool priorityFlag_EVVM,
513
470
  bytes memory signature_EVVM
514
- )
515
- public
516
- onlyOwnerOfIdentity(user, username)
517
- verifyIfNonceIsAvailable(user, nonce)
518
- {
471
+ ) external onlyOwnerOfIdentity(user, username) {
519
472
  if (
520
473
  usernameOffers[username][offerID].offerer == address(0) ||
521
474
  usernameOffers[username][offerID].expireDate < block.timestamp
@@ -523,7 +476,7 @@ contract NameService {
523
476
 
524
477
  if (
525
478
  !SignatureUtils.verifyMessageSignedForAcceptOffer(
526
- Evvm(evvmAddress.current).getEvvmID(),
479
+ IEvvm(evvmAddress.current).getEvvmID(),
527
480
  user,
528
481
  username,
529
482
  offerID,
@@ -532,6 +485,8 @@ contract NameService {
532
485
  )
533
486
  ) revert ErrorsLib.InvalidSignatureOnNameService();
534
487
 
488
+ verifyAsyncNonce(user, nonce);
489
+
535
490
  if (priorityFee_EVVM > 0) {
536
491
  makePay(
537
492
  user,
@@ -550,10 +505,10 @@ contract NameService {
550
505
 
551
506
  usernameOffers[username][offerID].offerer = address(0);
552
507
 
553
- if (Evvm(evvmAddress.current).isAddressStaker(msg.sender)) {
508
+ if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
554
509
  makeCaPay(
555
510
  msg.sender,
556
- (Evvm(evvmAddress.current).getRewardAmount()) +
511
+ (IEvvm(evvmAddress.current).getRewardAmount()) +
557
512
  (((usernameOffers[username][offerID].amount * 1) / 199) /
558
513
  4) +
559
514
  priorityFee_EVVM
@@ -564,7 +519,7 @@ contract NameService {
564
519
  (usernameOffers[username][offerID].amount) +
565
520
  (((usernameOffers[username][offerID].amount * 1) / 199) / 4);
566
521
 
567
- nameServiceNonce[user][nonce] = true;
522
+ markAsyncNonceAsUsed(user, nonce);
568
523
  }
569
524
 
570
525
  /**
@@ -595,11 +550,7 @@ contract NameService {
595
550
  uint256 nonce_EVVM,
596
551
  bool priorityFlag_EVVM,
597
552
  bytes memory signature_EVVM
598
- )
599
- public
600
- onlyOwnerOfIdentity(user, username)
601
- verifyIfNonceIsAvailable(user, nonce)
602
- {
553
+ ) external onlyOwnerOfIdentity(user, username) {
603
554
  if (
604
555
  identityDetails[username].flagNotAUsername == 0x01 ||
605
556
  identityDetails[username].expireDate > block.timestamp + 36500 days
@@ -607,7 +558,7 @@ contract NameService {
607
558
 
608
559
  if (
609
560
  !SignatureUtils.verifyMessageSignedForRenewUsername(
610
- Evvm(evvmAddress.current).getEvvmID(),
561
+ IEvvm(evvmAddress.current).getEvvmID(),
611
562
  user,
612
563
  username,
613
564
  nonce,
@@ -615,6 +566,8 @@ contract NameService {
615
566
  )
616
567
  ) revert ErrorsLib.InvalidSignatureOnNameService();
617
568
 
569
+ verifyAsyncNonce(user, nonce);
570
+
618
571
  uint256 priceOfRenew = seePriceToRenew(username);
619
572
 
620
573
  makePay(
@@ -626,17 +579,17 @@ contract NameService {
626
579
  signature_EVVM
627
580
  );
628
581
 
629
- if (Evvm(evvmAddress.current).isAddressStaker(msg.sender)) {
582
+ if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
630
583
  makeCaPay(
631
584
  msg.sender,
632
- Evvm(evvmAddress.current).getRewardAmount() +
585
+ IEvvm(evvmAddress.current).getRewardAmount() +
633
586
  ((priceOfRenew * 50) / 100) +
634
587
  priorityFee_EVVM
635
588
  );
636
589
  }
637
590
 
638
591
  identityDetails[username].expireDate += 366 days;
639
- nameServiceNonce[user][nonce] = true;
592
+ markAsyncNonceAsUsed(user, nonce);
640
593
  }
641
594
 
642
595
  /**
@@ -676,16 +629,12 @@ contract NameService {
676
629
  uint256 nonce_EVVM,
677
630
  bool priorityFlag_EVVM,
678
631
  bytes memory signature_EVVM
679
- )
680
- public
681
- onlyOwnerOfIdentity(user, identity)
682
- verifyIfNonceIsAvailable(user, nonce)
683
- {
632
+ ) external onlyOwnerOfIdentity(user, identity) {
684
633
  if (bytes(value).length == 0) revert ErrorsLib.EmptyCustomMetadata();
685
634
 
686
635
  if (
687
636
  !SignatureUtils.verifyMessageSignedForAddCustomMetadata(
688
- Evvm(evvmAddress.current).getEvvmID(),
637
+ IEvvm(evvmAddress.current).getEvvmID(),
689
638
  user,
690
639
  identity,
691
640
  value,
@@ -694,6 +643,8 @@ contract NameService {
694
643
  )
695
644
  ) revert ErrorsLib.InvalidSignatureOnNameService();
696
645
 
646
+ verifyAsyncNonce(user, nonce);
647
+
697
648
  makePay(
698
649
  user,
699
650
  getPriceToAddCustomMetadata(),
@@ -703,10 +654,10 @@ contract NameService {
703
654
  signature_EVVM
704
655
  );
705
656
 
706
- if (Evvm(evvmAddress.current).isAddressStaker(msg.sender)) {
657
+ if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
707
658
  makeCaPay(
708
659
  msg.sender,
709
- (5 * Evvm(evvmAddress.current).getRewardAmount()) +
660
+ (5 * IEvvm(evvmAddress.current).getRewardAmount()) +
710
661
  ((getPriceToAddCustomMetadata() * 50) / 100) +
711
662
  priorityFee_EVVM
712
663
  );
@@ -717,7 +668,7 @@ contract NameService {
717
668
  ] = value;
718
669
 
719
670
  identityDetails[identity].customMetadataMaxSlots++;
720
- nameServiceNonce[user][nonce] = true;
671
+ markAsyncNonceAsUsed(user, nonce);
721
672
  }
722
673
 
723
674
  /**
@@ -743,14 +694,10 @@ contract NameService {
743
694
  uint256 nonce_EVVM,
744
695
  bool priorityFlag_EVVM,
745
696
  bytes memory signature_EVVM
746
- )
747
- public
748
- onlyOwnerOfIdentity(user, identity)
749
- verifyIfNonceIsAvailable(user, nonce)
750
- {
697
+ ) external onlyOwnerOfIdentity(user, identity) {
751
698
  if (
752
699
  !SignatureUtils.verifyMessageSignedForRemoveCustomMetadata(
753
- Evvm(evvmAddress.current).getEvvmID(),
700
+ IEvvm(evvmAddress.current).getEvvmID(),
754
701
  user,
755
702
  identity,
756
703
  key,
@@ -759,6 +706,8 @@ contract NameService {
759
706
  )
760
707
  ) revert ErrorsLib.InvalidSignatureOnNameService();
761
708
 
709
+ verifyAsyncNonce(user, nonce);
710
+
762
711
  if (identityDetails[identity].customMetadataMaxSlots <= key)
763
712
  revert ErrorsLib.InvalidKey();
764
713
 
@@ -788,11 +737,11 @@ contract NameService {
788
737
  ];
789
738
  }
790
739
  identityDetails[identity].customMetadataMaxSlots--;
791
- nameServiceNonce[user][nonce] = true;
792
- if (Evvm(evvmAddress.current).isAddressStaker(msg.sender)) {
740
+ markAsyncNonceAsUsed(user, nonce);
741
+ if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
793
742
  makeCaPay(
794
743
  msg.sender,
795
- (5 * Evvm(evvmAddress.current).getRewardAmount()) +
744
+ (5 * IEvvm(evvmAddress.current).getRewardAmount()) +
796
745
  priorityFee_EVVM
797
746
  );
798
747
  }
@@ -819,14 +768,10 @@ contract NameService {
819
768
  uint256 nonce_EVVM,
820
769
  bool priorityFlag_EVVM,
821
770
  bytes memory signature_EVVM
822
- )
823
- public
824
- onlyOwnerOfIdentity(user, identity)
825
- verifyIfNonceIsAvailable(user, nonce)
826
- {
771
+ ) external onlyOwnerOfIdentity(user, identity) {
827
772
  if (
828
773
  !SignatureUtils.verifyMessageSignedForFlushCustomMetadata(
829
- Evvm(evvmAddress.current).getEvvmID(),
774
+ IEvvm(evvmAddress.current).getEvvmID(),
830
775
  user,
831
776
  identity,
832
777
  nonce,
@@ -834,6 +779,8 @@ contract NameService {
834
779
  )
835
780
  ) revert ErrorsLib.InvalidSignatureOnNameService();
836
781
 
782
+ verifyAsyncNonce(user, nonce);
783
+
837
784
  if (identityDetails[identity].customMetadataMaxSlots == 0)
838
785
  revert ErrorsLib.EmptyCustomMetadata();
839
786
 
@@ -854,17 +801,17 @@ contract NameService {
854
801
  delete identityCustomMetadata[identity][i];
855
802
  }
856
803
 
857
- if (Evvm(evvmAddress.current).isAddressStaker(msg.sender)) {
804
+ if (IEvvm(evvmAddress.current).isAddressStaker(msg.sender)) {
858
805
  makeCaPay(
859
806
  msg.sender,
860
- ((5 * Evvm(evvmAddress.current).getRewardAmount()) *
807
+ ((5 * IEvvm(evvmAddress.current).getRewardAmount()) *
861
808
  identityDetails[identity].customMetadataMaxSlots) +
862
809
  priorityFee_EVVM
863
810
  );
864
811
  }
865
812
 
866
813
  identityDetails[identity].customMetadataMaxSlots = 0;
867
- nameServiceNonce[user][nonce] = true;
814
+ markAsyncNonceAsUsed(user, nonce);
868
815
  }
869
816
 
870
817
  /**
@@ -888,11 +835,7 @@ contract NameService {
888
835
  uint256 nonce_EVVM,
889
836
  bool priorityFlag_EVVM,
890
837
  bytes memory signature_EVVM
891
- )
892
- public
893
- verifyIfNonceIsAvailable(user, nonce)
894
- onlyOwnerOfIdentity(user, username)
895
- {
838
+ ) external onlyOwnerOfIdentity(user, username) {
896
839
  if (
897
840
  block.timestamp >= identityDetails[username].expireDate ||
898
841
  identityDetails[username].flagNotAUsername == 0x01
@@ -900,7 +843,7 @@ contract NameService {
900
843
 
901
844
  if (
902
845
  !SignatureUtils.verifyMessageSignedForFlushUsername(
903
- Evvm(evvmAddress.current).getEvvmID(),
846
+ IEvvm(evvmAddress.current).getEvvmID(),
904
847
  user,
905
848
  username,
906
849
  nonce,
@@ -908,6 +851,8 @@ contract NameService {
908
851
  )
909
852
  ) revert ErrorsLib.InvalidSignatureOnNameService();
910
853
 
854
+ verifyAsyncNonce(user, nonce);
855
+
911
856
  makePay(
912
857
  user,
913
858
  getPriceToFlushUsername(username),
@@ -927,7 +872,7 @@ contract NameService {
927
872
 
928
873
  makeCaPay(
929
874
  msg.sender,
930
- ((5 * Evvm(evvmAddress.current).getRewardAmount()) *
875
+ ((5 * IEvvm(evvmAddress.current).getRewardAmount()) *
931
876
  identityDetails[username].customMetadataMaxSlots) +
932
877
  priorityFee_EVVM
933
878
  );
@@ -939,7 +884,7 @@ contract NameService {
939
884
  offerMaxSlots: identityDetails[username].offerMaxSlots,
940
885
  flagNotAUsername: 0x00
941
886
  });
942
- nameServiceNonce[user][nonce] = true;
887
+ markAsyncNonceAsUsed(user, nonce);
943
888
  }
944
889
 
945
890
  //█ Administrative Functions with Time-Delayed Governance ████████████████████████████████████
@@ -955,7 +900,7 @@ contract NameService {
955
900
  }
956
901
 
957
902
  admin.proposal = _adminToPropose;
958
- admin.timeToAccept = block.timestamp + 1 minutes;
903
+ admin.timeToAccept = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
959
904
  }
960
905
 
961
906
  /**
@@ -993,12 +938,12 @@ contract NameService {
993
938
  */
994
939
  function proposeWithdrawPrincipalTokens(uint256 _amount) public onlyAdmin {
995
940
  if (
996
- Evvm(evvmAddress.current).getBalance(
941
+ IEvvm(evvmAddress.current).getBalance(
997
942
  address(this),
998
943
  PRINCIPAL_TOKEN_ADDRESS
999
944
  ) -
1000
945
  (5083 +
1001
- Evvm(evvmAddress.current).getRewardAmount() +
946
+ IEvvm(evvmAddress.current).getRewardAmount() +
1002
947
  principalTokenTokenLockedForWithdrawOffers) <
1003
948
  _amount ||
1004
949
  _amount == 0
@@ -1007,7 +952,9 @@ contract NameService {
1007
952
  }
1008
953
 
1009
954
  amountToWithdrawTokens.proposal = _amount;
1010
- amountToWithdrawTokens.timeToAccept = block.timestamp + 1 minutes;
955
+ amountToWithdrawTokens.timeToAccept =
956
+ block.timestamp +
957
+ TIME_TO_ACCEPT_PROPOSAL;
1011
958
  }
1012
959
 
1013
960
  /**
@@ -1046,7 +993,7 @@ contract NameService {
1046
993
  revert();
1047
994
  }
1048
995
  evvmAddress.proposal = _newEvvmAddress;
1049
- evvmAddress.timeToAccept = block.timestamp + 1 minutes;
996
+ evvmAddress.timeToAccept = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
1050
997
  }
1051
998
 
1052
999
  /**
@@ -1071,6 +1018,8 @@ contract NameService {
1071
1018
  proposal: address(0),
1072
1019
  timeToAccept: 0
1073
1020
  });
1021
+
1022
+ evvm = IEvvm(evvmAddress.current);
1074
1023
  }
1075
1024
 
1076
1025
  //█ Utility Functions ████████████████████████████████████████████████████████████████████████
@@ -1095,7 +1044,7 @@ contract NameService {
1095
1044
  bool priorityFlag,
1096
1045
  bytes memory signature
1097
1046
  ) internal {
1098
- Evvm(evvmAddress.current).pay(
1047
+ IEvvm(evvmAddress.current).pay(
1099
1048
  user,
1100
1049
  address(this),
1101
1050
  "",
@@ -1116,182 +1065,7 @@ contract NameService {
1116
1065
  * @param amount Amount of Principal Tokens to distribute
1117
1066
  */
1118
1067
  function makeCaPay(address user, uint256 amount) internal {
1119
- Evvm(evvmAddress.current).caPay(user, PRINCIPAL_TOKEN_ADDRESS, amount);
1120
- }
1121
-
1122
- //█ Identity Validation Functions ███████████████████████████████████████████████████████████████
1123
-
1124
- /**
1125
- * @notice Validates username format according to system rules
1126
- * @dev Username must be at least 4 characters, start with a letter, and contain only letters/digits
1127
- * @param username The username string to validate
1128
- */
1129
- function isValidUsername(string memory username) internal pure {
1130
- bytes memory usernameBytes = bytes(username);
1131
-
1132
- // Check if username length is at least 4 characters
1133
- if (usernameBytes.length < 4) revert ErrorsLib.InvalidUsername(0x01);
1134
-
1135
- // Check if username begins with a letter
1136
- if (!_isLetter(usernameBytes[0]))
1137
- revert ErrorsLib.InvalidUsername(0x02);
1138
-
1139
- // Iterate through each character in the username
1140
- for (uint256 i = 0; i < usernameBytes.length; i++) {
1141
- // Check if character is not a digit or letter
1142
- if (!_isDigit(usernameBytes[i]) && !_isLetter(usernameBytes[i])) {
1143
- revert ErrorsLib.InvalidUsername(0x03);
1144
- }
1145
- }
1146
- }
1147
-
1148
- /**
1149
- * @notice Validates phone number format
1150
- * @dev Phone number must be 6-19 digits only
1151
- * @param _phoneNumber The phone number string to validate
1152
- * @return True if valid phone number format
1153
- */
1154
- function isValidPhoneNumberNumber(
1155
- string memory _phoneNumber
1156
- ) internal pure returns (bool) {
1157
- bytes memory _telephoneNumberBytes = bytes(_phoneNumber);
1158
- if (
1159
- _telephoneNumberBytes.length < 20 &&
1160
- _telephoneNumberBytes.length > 5
1161
- ) {
1162
- revert();
1163
- }
1164
- for (uint256 i = 0; i < _telephoneNumberBytes.length; i++) {
1165
- if (!_isDigit(_telephoneNumberBytes[i])) {
1166
- revert();
1167
- }
1168
- }
1169
- return true;
1170
- }
1171
-
1172
- /**
1173
- * @notice Validates email address format
1174
- * @dev Checks for proper email structure: prefix(3+ chars) + @ + domain(3+ chars) + . + TLD(2+ chars)
1175
- * @param _email The email address string to validate
1176
- * @return True if valid email format
1177
- */
1178
- function isValidEmail(string memory _email) internal pure returns (bool) {
1179
- bytes memory _emailBytes = bytes(_email);
1180
- uint256 lengthCount = 0;
1181
- bytes1 flagVerify = 0x00;
1182
- for (uint point = 0; point < _emailBytes.length; point++) {
1183
- //step 1 0x00 prefix
1184
- if (flagVerify == 0x00) {
1185
- if (_isOnlyEmailPrefixCharacters(_emailBytes[point])) {
1186
- lengthCount++;
1187
- } else {
1188
- if (_isAAt(_emailBytes[point])) {
1189
- flagVerify = 0x01;
1190
- } else {
1191
- revert();
1192
- }
1193
- }
1194
- }
1195
-
1196
- //step 2 0x01 count the prefix length
1197
- if (flagVerify == 0x01) {
1198
- if (lengthCount < 3) {
1199
- revert();
1200
- } else {
1201
- flagVerify = 0x02;
1202
- lengthCount = 0;
1203
- point++;
1204
- }
1205
- }
1206
-
1207
- //step 3 0x02 domain name
1208
- if (flagVerify == 0x02) {
1209
- if (_isLetter(_emailBytes[point])) {
1210
- lengthCount++;
1211
- } else {
1212
- if (_isAPoint(_emailBytes[point])) {
1213
- flagVerify = 0x03;
1214
- } else {
1215
- revert();
1216
- }
1217
- }
1218
- }
1219
-
1220
- //step 4 0x03 count the domain name length
1221
- if (flagVerify == 0x03) {
1222
- if (lengthCount < 3) {
1223
- revert();
1224
- } else {
1225
- flagVerify = 0x04;
1226
- lengthCount = 0;
1227
- point++;
1228
- }
1229
- }
1230
-
1231
- //step 5 0x04 top level domain
1232
- if (flagVerify == 0x04) {
1233
- if (_isLetter(_emailBytes[point])) {
1234
- lengthCount++;
1235
- } else {
1236
- if (_isAPoint(_emailBytes[point])) {
1237
- if (lengthCount < 2) {
1238
- revert();
1239
- } else {
1240
- lengthCount = 0;
1241
- }
1242
- } else {
1243
- revert();
1244
- }
1245
- }
1246
- }
1247
- }
1248
-
1249
- if (flagVerify != 0x04) {
1250
- revert();
1251
- }
1252
-
1253
- return true;
1254
- }
1255
-
1256
- /// @dev Checks if a byte represents a digit (0-9)
1257
- function _isDigit(bytes1 character) private pure returns (bool) {
1258
- return (character >= 0x30 && character <= 0x39); // ASCII range for digits 0-9
1259
- }
1260
-
1261
- /// @dev Checks if a byte represents a letter (A-Z or a-z)
1262
- function _isLetter(bytes1 character) private pure returns (bool) {
1263
- return ((character >= 0x41 && character <= 0x5A) ||
1264
- (character >= 0x61 && character <= 0x7A)); // ASCII ranges for letters A-Z and a-z
1265
- }
1266
-
1267
- /// @dev Checks if a byte represents any symbol character
1268
- function _isAnySimbol(bytes1 character) private pure returns (bool) {
1269
- return ((character >= 0x21 && character <= 0x2F) || /// @dev includes characters from "!" to "/"
1270
- (character >= 0x3A && character <= 0x40) || /// @dev includes characters from ":" to "@"
1271
- (character >= 0x5B && character <= 0x60) || /// @dev includes characters from "[" to "`"
1272
- (character >= 0x7B && character <= 0x7E)); /// @dev includes characters from "{" to "~"
1273
- }
1274
-
1275
- /// @dev Checks if a byte is valid for email prefix (letters, digits, and specific symbols)
1276
- function _isOnlyEmailPrefixCharacters(
1277
- bytes1 character
1278
- ) private pure returns (bool) {
1279
- return (_isLetter(character) ||
1280
- _isDigit(character) ||
1281
- (character >= 0x21 && character <= 0x2F) || /// @dev includes characters from "!" to "/"
1282
- (character >= 0x3A && character <= 0x3F) || /// @dev includes characters from ":" to "?"
1283
- (character >= 0x5B && character <= 0x60) || /// @dev includes characters from "[" to "`"
1284
- (character >= 0x7B && character <= 0x7E)); /// @dev includes characters from "{" to "~"
1285
- }
1286
-
1287
- /// @dev Checks if a byte represents a period/dot character (.)
1288
- function _isAPoint(bytes1 character) private pure returns (bool) {
1289
- return character == 0x2E;
1290
- }
1291
-
1292
- /// @dev Checks if a byte represents an at symbol (@)
1293
- function _isAAt(bytes1 character) private pure returns (bool) {
1294
- return character == 0x40;
1068
+ IEvvm(evvmAddress.current).caPay(user, PRINCIPAL_TOKEN_ADDRESS, amount);
1295
1069
  }
1296
1070
 
1297
1071
  //█ Username Hashing Functions ███████████████████████████████████████████████████████████████████
@@ -1427,14 +1201,14 @@ contract NameService {
1427
1201
  if (price == 0) {
1428
1202
  price = 500 * 10 ** 18;
1429
1203
  } else {
1430
- uint256 principalTokenReward = Evvm(evvmAddress.current)
1204
+ uint256 principalTokenReward = IEvvm(evvmAddress.current)
1431
1205
  .getRewardAmount();
1432
1206
  price = ((price * 5) / 1000) > (500000 * principalTokenReward)
1433
1207
  ? (500000 * principalTokenReward)
1434
1208
  : ((price * 5) / 1000);
1435
1209
  }
1436
1210
  } else {
1437
- price = 500_000 * Evvm(evvmAddress.current).getRewardAmount();
1211
+ price = 500_000 * IEvvm(evvmAddress.current).getRewardAmount();
1438
1212
  }
1439
1213
  }
1440
1214
 
@@ -1444,7 +1218,7 @@ contract NameService {
1444
1218
  * @return price Cost in Principal Tokens (10x current reward amount)
1445
1219
  */
1446
1220
  function getPriceToAddCustomMetadata() public view returns (uint256 price) {
1447
- price = 10 * Evvm(evvmAddress.current).getRewardAmount();
1221
+ price = 10 * IEvvm(evvmAddress.current).getRewardAmount();
1448
1222
  }
1449
1223
 
1450
1224
  /**
@@ -1457,7 +1231,7 @@ contract NameService {
1457
1231
  view
1458
1232
  returns (uint256 price)
1459
1233
  {
1460
- price = 10 * Evvm(evvmAddress.current).getRewardAmount();
1234
+ price = 10 * IEvvm(evvmAddress.current).getRewardAmount();
1461
1235
  }
1462
1236
 
1463
1237
  /**
@@ -1470,7 +1244,7 @@ contract NameService {
1470
1244
  string memory _identity
1471
1245
  ) public view returns (uint256 price) {
1472
1246
  price =
1473
- (10 * Evvm(evvmAddress.current).getRewardAmount()) *
1247
+ (10 * IEvvm(evvmAddress.current).getRewardAmount()) *
1474
1248
  identityDetails[_identity].customMetadataMaxSlots;
1475
1249
  }
1476
1250
 
@@ -1484,25 +1258,9 @@ contract NameService {
1484
1258
  string memory _identity
1485
1259
  ) public view returns (uint256 price) {
1486
1260
  price =
1487
- ((10 * Evvm(evvmAddress.current).getRewardAmount()) *
1261
+ ((10 * IEvvm(evvmAddress.current).getRewardAmount()) *
1488
1262
  identityDetails[_identity].customMetadataMaxSlots) +
1489
- Evvm(evvmAddress.current).getRewardAmount();
1490
- }
1491
-
1492
- //█ User Management Functions ████████████████████████████████████████████████████████████████████
1493
-
1494
- /**
1495
- * @notice Checks if a nonce has been used by a specific user
1496
- * @dev Prevents replay attacks by tracking used nonces per user
1497
- * @param _user Address of the user to check
1498
- * @param _nonce Nonce value to verify
1499
- * @return True if the nonce has been used, false if still available
1500
- */
1501
- function checkIfNameServiceNonceIsAvailable(
1502
- address _user,
1503
- uint256 _nonce
1504
- ) public view returns (bool) {
1505
- return nameServiceNonce[_user][_nonce];
1263
+ IEvvm(evvmAddress.current).getRewardAmount();
1506
1264
  }
1507
1265
 
1508
1266
  //█ Identity Availability Functions ██████████████████████████████████████████████████████████████
@@ -1672,7 +1430,7 @@ contract NameService {
1672
1430
  return
1673
1431
  identityDetails[username].offerMaxSlots > 0
1674
1432
  ? seePriceToRenew(username)
1675
- : Evvm(evvmAddress.current).getRewardAmount() * 100;
1433
+ : IEvvm(evvmAddress.current).getRewardAmount() * 100;
1676
1434
  }
1677
1435
 
1678
1436
  //█ Administrative Getters ███████████████████████████████████████████████████████████████████████