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