@evvm/testnet-contracts 2.2.2 → 2.3.0

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 (34) hide show
  1. package/LICENSE +145 -118
  2. package/README.md +135 -42
  3. package/contracts/evvm/Evvm.sol +154 -181
  4. package/contracts/evvm/lib/ErrorsLib.sol +119 -6
  5. package/contracts/evvm/lib/EvvmStorage.sol +164 -9
  6. package/contracts/evvm/lib/EvvmStructs.sol +124 -6
  7. package/contracts/evvm/lib/SignatureUtils.sol +103 -61
  8. package/contracts/nameService/NameService.sol +165 -155
  9. package/contracts/nameService/lib/ErrorsLib.sol +142 -8
  10. package/contracts/nameService/lib/IdentityValidation.sol +21 -0
  11. package/contracts/nameService/lib/NameServiceStructs.sol +75 -19
  12. package/contracts/nameService/lib/SignatureUtils.sol +235 -60
  13. package/contracts/p2pSwap/P2PSwap.sol +205 -164
  14. package/contracts/staking/Estimator.sol +131 -24
  15. package/contracts/staking/Staking.sol +98 -113
  16. package/contracts/staking/lib/ErrorsLib.sol +79 -3
  17. package/contracts/staking/lib/SignatureUtils.sol +82 -16
  18. package/contracts/staking/lib/StakingStructs.sol +12 -0
  19. package/contracts/treasury/Treasury.sol +30 -12
  20. package/contracts/treasury/lib/ErrorsLib.sol +30 -0
  21. package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +3 -3
  22. package/interfaces/IEvvm.sol +9 -4
  23. package/interfaces/INameService.sol +12 -3
  24. package/interfaces/IStaking.sol +2 -1
  25. package/library/Erc191TestBuilder.sol +188 -0
  26. package/library/EvvmService.sol +55 -0
  27. package/library/primitives/SignatureRecover.sol +33 -0
  28. package/library/utils/AdvancedStrings.sol +61 -0
  29. package/library/utils/SignatureUtil.sol +34 -0
  30. package/library/utils/nonces/AsyncNonce.sol +42 -0
  31. package/library/utils/nonces/SyncNonce.sol +44 -0
  32. package/library/utils/service/EvvmPayments.sol +68 -1
  33. package/library/utils/service/StakingServiceUtils.sol +44 -0
  34. package/package.json +2 -1
@@ -41,10 +41,14 @@ pragma solidity ^0.8.0;
41
41
  * - Estimator integration for yield calculations
42
42
  */
43
43
 
44
- import {IEvvm} from "@evvm/testnet-contracts/interfaces/IEvvm.sol";
44
+ import {Evvm} from "@evvm/testnet-contracts/contracts/evvm/Evvm.sol";
45
45
  import {IEstimator} from "@evvm/testnet-contracts/interfaces/IEstimator.sol";
46
- import {AsyncNonce} from "@evvm/testnet-contracts/library/utils/nonces/AsyncNonce.sol";
47
- import {StakingStructs} from "@evvm/testnet-contracts/contracts/staking/lib/StakingStructs.sol";
46
+ import {
47
+ AsyncNonce
48
+ } from "@evvm/testnet-contracts/library/utils/nonces/AsyncNonce.sol";
49
+ import {
50
+ StakingStructs
51
+ } from "@evvm/testnet-contracts/contracts/staking/lib/StakingStructs.sol";
48
52
  import {ErrorsLib} from "./lib/ErrorsLib.sol";
49
53
  import {SignatureUtils} from "./lib/SignatureUtils.sol";
50
54
 
@@ -61,10 +65,6 @@ contract Staking is AsyncNonce, StakingStructs {
61
65
  /// @dev Price of one staking main token (5083 main token = 1 staking)
62
66
  uint256 private constant PRICE_OF_STAKING = 5083 * (10 ** 18);
63
67
 
64
- /// @dev Address representing the principal Principal Token
65
- address private constant PRINCIPAL_TOKEN_ADDRESS =
66
- 0x0000000000000000000000000000000000000001;
67
-
68
68
  /// @dev Admin address management with proposal system
69
69
  AddressTypeProposal private admin;
70
70
  /// @dev Golden Fisher address management with proposal system
@@ -91,7 +91,7 @@ contract Staking is AsyncNonce, StakingStructs {
91
91
  /// @dev Mapping to store complete staking history for each user
92
92
  mapping(address => HistoryMetadata[]) private userHistory;
93
93
 
94
- IEvvm private evvm;
94
+ Evvm private evvm;
95
95
  IEstimator private estimator;
96
96
 
97
97
  /// @dev Modifier to verify access to admin functions
@@ -127,8 +127,22 @@ contract Staking is AsyncNonce, StakingStructs {
127
127
 
128
128
  goldenFisher.actual = initialGoldenFisher;
129
129
 
130
- allowPublicStaking.flag = false;
131
- allowPresaleStaking.flag = true;
130
+ /**
131
+ * @dev Because presale staking is disabled by default
132
+ * if you want to enable it, you need to do it via
133
+ * this admin functions
134
+ *
135
+ * prepareChangeAllowPresaleStaking()
136
+ * prepareChangeAllowPublicStaking()
137
+ *
138
+ * wait TIME_TO_ACCEPT_PROPOSAL
139
+ *
140
+ * confirmChangeAllowPresaleStaking()
141
+ * confirmChangeAllowPublicStaking()
142
+ */
143
+
144
+ allowPublicStaking.flag = true;
145
+ allowPresaleStaking.flag = false;
132
146
 
133
147
  secondsToUnlockStaking.actual = 0;
134
148
 
@@ -152,7 +166,7 @@ contract Staking is AsyncNonce, StakingStructs {
152
166
  estimatorAddress.actual = _estimator;
153
167
  EVVM_ADDRESS = _evvm;
154
168
  breakerSetupEstimatorAndEvvm = 0x00;
155
- evvm = IEvvm(_evvm);
169
+ evvm = Evvm(_evvm);
156
170
  estimator = IEstimator(_estimator);
157
171
  }
158
172
 
@@ -204,11 +218,13 @@ contract Staking is AsyncNonce, StakingStructs {
204
218
  bool priorityFlag_EVVM,
205
219
  bytes memory signature_EVVM
206
220
  ) external {
221
+ if (!allowPresaleStaking.flag || allowPublicStaking.flag)
222
+ revert ErrorsLib.PresaleStakingDisabled();
223
+
207
224
  if (
208
- !SignatureUtils.verifyMessageSignedForStake(
225
+ !SignatureUtils.verifyMessageSignedForPresaleStake(
209
226
  evvm.getEvvmID(),
210
227
  user,
211
- false,
212
228
  isStaking,
213
229
  1,
214
230
  nonce,
@@ -216,12 +232,19 @@ contract Staking is AsyncNonce, StakingStructs {
216
232
  )
217
233
  ) revert ErrorsLib.InvalidSignatureOnStaking();
218
234
 
235
+ if (!userPresaleStaker[user].isAllow)
236
+ revert ErrorsLib.UserIsNotPresaleStaker();
237
+
219
238
  verifyAsyncNonce(user, nonce);
220
239
 
221
- presaleClaims(isStaking, user);
240
+ uint256 current = userPresaleStaker[user].stakingAmount;
222
241
 
223
- if (!allowPresaleStaking.flag)
224
- revert ErrorsLib.PresaleStakingDisabled();
242
+ if (isStaking ? current >= 2 : current == 0)
243
+ revert ErrorsLib.UserPresaleStakerLimitExceeded();
244
+
245
+ userPresaleStaker[user].stakingAmount = isStaking
246
+ ? current + 1
247
+ : current - 1;
225
248
 
226
249
  stakingBaseProcess(
227
250
  AccountMetadata({Address: user, IsAService: false}),
@@ -236,38 +259,6 @@ contract Staking is AsyncNonce, StakingStructs {
236
259
  markAsyncNonceAsUsed(user, nonce);
237
260
  }
238
261
 
239
- /**
240
- * @notice Internal function to manage presale staking limits and permissions
241
- * @dev Enforces the 2 staking token limit for presale users and tracks staking amounts
242
- * @param _isStaking True for staking (increments count), false for unstaking (decrements count)
243
- * @param _user Address of the presale user
244
- */
245
- function presaleClaims(bool _isStaking, address _user) internal {
246
- if (allowPublicStaking.flag) {
247
- revert ErrorsLib.PresaleStakingDisabled();
248
- } else {
249
- if (userPresaleStaker[_user].isAllow) {
250
- if (_isStaking) {
251
- // staking
252
-
253
- if (userPresaleStaker[_user].stakingAmount >= 2)
254
- revert ErrorsLib.UserPresaleStakerLimitExceeded();
255
-
256
- userPresaleStaker[_user].stakingAmount++;
257
- } else {
258
- // unstaking
259
-
260
- if (userPresaleStaker[_user].stakingAmount == 0)
261
- revert ErrorsLib.UserPresaleStakerLimitExceeded();
262
-
263
- userPresaleStaker[_user].stakingAmount--;
264
- }
265
- } else {
266
- revert ErrorsLib.UserIsNotPresaleStaker();
267
- }
268
- }
269
- }
270
-
271
262
  /**
272
263
  * @notice Allows any user to stake/unstake when public staking is enabled
273
264
  * @dev Requires signature verification and handles nonce management
@@ -292,15 +283,12 @@ contract Staking is AsyncNonce, StakingStructs {
292
283
  bool priorityFlag_EVVM,
293
284
  bytes memory signature_EVVM
294
285
  ) external {
295
- if (!allowPublicStaking.flag) {
296
- revert();
297
- }
286
+ if (!allowPublicStaking.flag) revert ErrorsLib.PublicStakingDisabled();
298
287
 
299
288
  if (
300
- !SignatureUtils.verifyMessageSignedForStake(
289
+ !SignatureUtils.verifyMessageSignedForPublicStake(
301
290
  evvm.getEvvmID(),
302
291
  user,
303
- true,
304
292
  isStaking,
305
293
  amountOfStaking,
306
294
  nonce,
@@ -346,11 +334,11 @@ contract Staking is AsyncNonce, StakingStructs {
346
334
  amountOfStaking: amountOfStaking,
347
335
  amountServiceBeforeStaking: evvm.getBalance(
348
336
  msg.sender,
349
- PRINCIPAL_TOKEN_ADDRESS
337
+ evvm.getPrincipalTokenAddress()
350
338
  ),
351
339
  amountStakingBeforeStaking: evvm.getBalance(
352
340
  address(this),
353
- PRINCIPAL_TOKEN_ADDRESS
341
+ evvm.getPrincipalTokenAddress()
354
342
  )
355
343
  });
356
344
  }
@@ -372,23 +360,13 @@ contract Staking is AsyncNonce, StakingStructs {
372
360
  uint256 totalStakingRequired = PRICE_OF_STAKING *
373
361
  serviceStakingData.amountOfStaking;
374
362
 
375
- uint256 actualServiceBalance = evvm.getBalance(
376
- msg.sender,
377
- PRINCIPAL_TOKEN_ADDRESS
378
- );
379
-
380
- uint256 actualStakingBalance = evvm.getBalance(
381
- address(this),
382
- PRINCIPAL_TOKEN_ADDRESS
383
- );
384
-
385
363
  if (
386
364
  serviceStakingData.amountServiceBeforeStaking -
387
365
  totalStakingRequired !=
388
- actualServiceBalance &&
366
+ evvm.getBalance(msg.sender, evvm.getPrincipalTokenAddress()) &&
389
367
  serviceStakingData.amountStakingBeforeStaking +
390
368
  totalStakingRequired !=
391
- actualStakingBalance
369
+ evvm.getBalance(address(this), evvm.getPrincipalTokenAddress())
392
370
  )
393
371
  revert ErrorsLib.ServiceDoesNotFulfillCorrectStakingAmount(
394
372
  totalStakingRequired
@@ -492,8 +470,8 @@ contract Staking is AsyncNonce, StakingStructs {
492
470
  if (priorityFee_EVVM != 0 && !account.IsAService)
493
471
  makePay(
494
472
  account.Address,
495
- priorityFee_EVVM,
496
473
  0,
474
+ priorityFee_EVVM,
497
475
  priorityFlag_EVVM,
498
476
  nonce_EVVM,
499
477
  signature_EVVM
@@ -506,7 +484,7 @@ contract Staking is AsyncNonce, StakingStructs {
506
484
  amountOfStaking;
507
485
 
508
486
  makeCaPay(
509
- PRINCIPAL_TOKEN_ADDRESS,
487
+ evvm.getPrincipalTokenAddress(),
510
488
  account.Address,
511
489
  (PRICE_OF_STAKING * amountOfStaking)
512
490
  );
@@ -523,12 +501,9 @@ contract Staking is AsyncNonce, StakingStructs {
523
501
  })
524
502
  );
525
503
 
526
- if (
527
- evvm.isAddressStaker(msg.sender) &&
528
- !account.IsAService
529
- ) {
504
+ if (evvm.isAddressStaker(msg.sender) && !account.IsAService) {
530
505
  makeCaPay(
531
- PRINCIPAL_TOKEN_ADDRESS,
506
+ evvm.getPrincipalTokenAddress(),
532
507
  msg.sender,
533
508
  (evvm.getRewardAmount() * 2) + priorityFee_EVVM
534
509
  );
@@ -578,7 +553,7 @@ contract Staking is AsyncNonce, StakingStructs {
578
553
 
579
554
  if (evvm.isAddressStaker(msg.sender)) {
580
555
  makeCaPay(
581
- PRINCIPAL_TOKEN_ADDRESS,
556
+ evvm.getPrincipalTokenAddress(),
582
557
  msg.sender,
583
558
  (evvm.getRewardAmount() * 1)
584
559
  );
@@ -613,7 +588,7 @@ contract Staking is AsyncNonce, StakingStructs {
613
588
  user,
614
589
  address(this),
615
590
  "",
616
- PRINCIPAL_TOKEN_ADDRESS,
591
+ evvm.getPrincipalTokenAddress(),
617
592
  amount,
618
593
  priorityFee,
619
594
  nonce,
@@ -648,9 +623,9 @@ contract Staking is AsyncNonce, StakingStructs {
648
623
  * @param _staker Address to be added to the presale staker list
649
624
  */
650
625
  function addPresaleStaker(address _staker) external onlyOwner {
651
- if (presaleStakerCount > LIMIT_PRESALE_STAKER) {
652
- revert();
653
- }
626
+ if (presaleStakerCount > LIMIT_PRESALE_STAKER)
627
+ revert ErrorsLib.LimitPresaleStakersExceeded();
628
+
654
629
  userPresaleStaker[_staker].isAllow = true;
655
630
  presaleStakerCount++;
656
631
  }
@@ -662,9 +637,9 @@ contract Staking is AsyncNonce, StakingStructs {
662
637
  */
663
638
  function addPresaleStakers(address[] calldata _stakers) external onlyOwner {
664
639
  for (uint256 i = 0; i < _stakers.length; i++) {
665
- if (presaleStakerCount > LIMIT_PRESALE_STAKER) {
666
- revert();
667
- }
640
+ if (presaleStakerCount > LIMIT_PRESALE_STAKER)
641
+ revert ErrorsLib.LimitPresaleStakersExceeded();
642
+
668
643
  userPresaleStaker[_stakers[i]].isAllow = true;
669
644
  presaleStakerCount++;
670
645
  }
@@ -694,11 +669,12 @@ contract Staking is AsyncNonce, StakingStructs {
694
669
  * @dev Can only be called by the proposed admin after the time delay has passed
695
670
  */
696
671
  function acceptNewAdmin() external {
697
- if (
698
- msg.sender != admin.proposal || admin.timeToAccept > block.timestamp
699
- ) {
700
- revert();
701
- }
672
+ if (msg.sender != admin.proposal)
673
+ revert ErrorsLib.SenderIsNotProposedAdmin();
674
+
675
+ if (admin.timeToAccept > block.timestamp)
676
+ revert ErrorsLib.TimeToAcceptProposalNotReached();
677
+
702
678
  admin.actual = admin.proposal;
703
679
  admin.proposal = address(0);
704
680
  admin.timeToAccept = 0;
@@ -728,9 +704,9 @@ contract Staking is AsyncNonce, StakingStructs {
728
704
  * @dev Can only be called by the current admin after the 1-day time delay
729
705
  */
730
706
  function acceptNewGoldenFisher() external onlyOwner {
731
- if (goldenFisher.timeToAccept > block.timestamp) {
732
- revert();
733
- }
707
+ if (goldenFisher.timeToAccept > block.timestamp)
708
+ revert ErrorsLib.TimeToAcceptProposalNotReached();
709
+
734
710
  goldenFisher.actual = goldenFisher.proposal;
735
711
  goldenFisher.proposal = address(0);
736
712
  goldenFisher.timeToAccept = 0;
@@ -764,9 +740,9 @@ contract Staking is AsyncNonce, StakingStructs {
764
740
  * @dev Can only be called by the current admin after the 1-day time delay
765
741
  */
766
742
  function acceptSetSecondsToUnlockStaking() external onlyOwner {
767
- if (secondsToUnlockStaking.timeToAccept > block.timestamp) {
768
- revert();
769
- }
743
+ if (secondsToUnlockStaking.timeToAccept > block.timestamp)
744
+ revert ErrorsLib.TimeToAcceptProposalNotReached();
745
+
770
746
  secondsToUnlockStaking.actual = secondsToUnlockStaking.proposal;
771
747
  secondsToUnlockStaking.proposal = 0;
772
748
  secondsToUnlockStaking.timeToAccept = 0;
@@ -800,9 +776,9 @@ contract Staking is AsyncNonce, StakingStructs {
800
776
  * @dev Can only be called by the current admin after the 1-day time delay
801
777
  */
802
778
  function confirmSetSecondsToUnllockFullUnstaking() external onlyOwner {
803
- if (secondsToUnllockFullUnstaking.timeToAccept > block.timestamp) {
804
- revert();
805
- }
779
+ if (secondsToUnllockFullUnstaking.timeToAccept > block.timestamp)
780
+ revert ErrorsLib.TimeToAcceptProposalNotReached();
781
+
806
782
  secondsToUnllockFullUnstaking.actual = secondsToUnllockFullUnstaking
807
783
  .proposal;
808
784
  secondsToUnllockFullUnstaking.proposal = 0;
@@ -832,9 +808,9 @@ contract Staking is AsyncNonce, StakingStructs {
832
808
  * @dev Toggles between enabled/disabled state for public staking after 1-day delay
833
809
  */
834
810
  function confirmChangeAllowPublicStaking() external onlyOwner {
835
- if (allowPublicStaking.timeToAccept > block.timestamp) {
836
- revert();
837
- }
811
+ if (allowPublicStaking.timeToAccept > block.timestamp)
812
+ revert ErrorsLib.TimeToAcceptProposalNotReached();
813
+
838
814
  allowPublicStaking = BoolTypeProposal({
839
815
  flag: !allowPublicStaking.flag,
840
816
  timeToAccept: 0
@@ -864,13 +840,11 @@ contract Staking is AsyncNonce, StakingStructs {
864
840
  * @dev Toggles between enabled/disabled state for presale staking after 1-day delay
865
841
  */
866
842
  function confirmChangeAllowPresaleStaking() external onlyOwner {
867
- if (allowPresaleStaking.timeToAccept > block.timestamp) {
868
- revert();
869
- }
870
- allowPresaleStaking = BoolTypeProposal({
871
- flag: !allowPresaleStaking.flag,
872
- timeToAccept: 0
873
- });
843
+ if (allowPresaleStaking.timeToAccept > block.timestamp)
844
+ revert ErrorsLib.TimeToAcceptProposalNotReached();
845
+
846
+ allowPresaleStaking.flag = !allowPresaleStaking.flag;
847
+ allowPresaleStaking.timeToAccept = 0;
874
848
  }
875
849
 
876
850
  /**
@@ -880,7 +854,9 @@ contract Staking is AsyncNonce, StakingStructs {
880
854
  */
881
855
  function proposeEstimator(address _estimator) external onlyOwner {
882
856
  estimatorAddress.proposal = _estimator;
883
- estimatorAddress.timeToAccept = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
857
+ estimatorAddress.timeToAccept =
858
+ block.timestamp +
859
+ TIME_TO_ACCEPT_PROPOSAL;
884
860
  }
885
861
 
886
862
  /**
@@ -897,9 +873,9 @@ contract Staking is AsyncNonce, StakingStructs {
897
873
  * @dev Can only be called by the current admin after the 1-day time delay
898
874
  */
899
875
  function acceptNewEstimator() external onlyOwner {
900
- if (estimatorAddress.timeToAccept > block.timestamp) {
901
- revert();
902
- }
876
+ if (estimatorAddress.timeToAccept > block.timestamp)
877
+ revert ErrorsLib.TimeToAcceptProposalNotReached();
878
+
903
879
  estimatorAddress.actual = estimatorAddress.proposal;
904
880
  estimatorAddress.proposal = address(0);
905
881
  estimatorAddress.timeToAccept = 0;
@@ -1104,7 +1080,7 @@ contract Staking is AsyncNonce, StakingStructs {
1104
1080
  * @dev Includes current flag state and any pending changes with timestamps
1105
1081
  * @return BoolTypeProposal struct containing flag and timeToAccept
1106
1082
  */
1107
- function getAllDataOfAllowPublicStaking()
1083
+ function getAllowPublicStaking()
1108
1084
  external
1109
1085
  view
1110
1086
  returns (BoolTypeProposal memory)
@@ -1125,6 +1101,15 @@ contract Staking is AsyncNonce, StakingStructs {
1125
1101
  return allowPresaleStaking;
1126
1102
  }
1127
1103
 
1104
+ /**
1105
+ * @notice Gets the unique identifier string for this EVVM instance
1106
+ * @dev Returns the EvvmID used for distinguishing different EVVM deployments
1107
+ * @return Unique EvvmID string
1108
+ */
1109
+ function getEvvmID() external view returns (uint256) {
1110
+ return evvm.getEvvmID();
1111
+ }
1112
+
1128
1113
  /**
1129
1114
  * @notice Returns the address of the EVVM core contract
1130
1115
  * @dev The EVVM contract handles payments and staker registration
@@ -1139,8 +1124,8 @@ contract Staking is AsyncNonce, StakingStructs {
1139
1124
  * @dev This is a constant address used to represent the principal token
1140
1125
  * @return Address representing the Principal Token (0x...0001)
1141
1126
  */
1142
- function getMateAddress() external pure returns (address) {
1143
- return PRINCIPAL_TOKEN_ADDRESS;
1127
+ function getMateAddress() external view returns (address) {
1128
+ return evvm.getPrincipalTokenAddress();
1144
1129
  }
1145
1130
 
1146
1131
  /**
@@ -2,21 +2,97 @@
2
2
  // Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
3
3
 
4
4
  pragma solidity ^0.8.0;
5
+ /**
6
+ * @title ErrorsLib
7
+ * @author Mate Labs
8
+ * @notice Library containing all custom error definitions for the Staking contract
9
+ * @dev This library is exclusive to the Staking.sol contract and provides descriptive
10
+ * error types for better gas efficiency and debugging compared to revert strings.
11
+ *
12
+ * Error Categories:
13
+ * - Access Control: Permission and authorization errors
14
+ * - Signature Verification: EIP-191 signature validation errors
15
+ * - Presale Staking: Presale-specific staking limitations
16
+ * - Public Staking: General staking state errors
17
+ * - Service Staking: Smart contract (service) staking errors
18
+ * - Time Lock: Time-delayed governance and cooldown errors
19
+ */
5
20
 
6
21
  library ErrorsLib {
22
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
23
+ /// Access Control Errors
24
+ /// ▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
25
+
26
+ /// @dev Thrown when a non-admin address attempts to call an admin-only function
7
27
  error SenderIsNotAdmin();
28
+
29
+ /// @dev Thrown when a non-golden-fisher address attempts to call a golden fisher function
8
30
  error SenderIsNotGoldenFisher();
31
+
32
+ /// @dev Thrown when a non-proposed-admin address attempts to accept an admin proposal
33
+ error SenderIsNotProposedAdmin();
34
+
35
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
36
+ /// Signature Verification Errors
37
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
38
+
39
+ /// @dev Thrown when EIP-191 signature verification fails for a staking operation
9
40
  error InvalidSignatureOnStaking();
41
+
42
+ /// @dev Thrown when attempting to use a nonce that has already been consumed
10
43
  error StakingNonceAlreadyUsed();
44
+
45
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
46
+ /// Presale Staking Errors
47
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
48
+
49
+ /// @dev Thrown when presale staking is attempted while disabled or when public staking is active
11
50
  error PresaleStakingDisabled();
51
+
52
+ /// @dev Thrown when a presale user tries to stake more than the 2-staking limit
12
53
  error UserPresaleStakerLimitExceeded();
54
+
55
+ /// @dev Thrown when a non-presale-registered address attempts presale staking
13
56
  error UserIsNotPresaleStaker();
57
+
58
+ /// @dev Thrown when attempting to add more presale stakers beyond the 800 limit
59
+ error LimitPresaleStakersExceeded();
60
+
61
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
62
+ /// Public Staking Errors
63
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
64
+
65
+ /// @dev Thrown when public staking is attempted while the feature is disabled
14
66
  error PublicStakingDisabled();
67
+
68
+ ///Service Staking Errors
69
+
70
+ /// @dev Thrown when a non-contract address attempts to call a service-only function
15
71
  error AddressIsNotAService();
72
+
73
+ /// @dev Thrown when the user address doesn't match the service address in staking metadata
16
74
  error UserAndServiceMismatch();
17
- error AddressMustWaitToStakeAgain();
18
- error AddressMustWaitToFullUnstake();
75
+
76
+ /// @dev Thrown when confirmServiceStaking is called by a different address than prepareServiceStaking
77
+ error AddressMismatch();
78
+
79
+ /// @dev Thrown when the payment amount doesn't match the required staking cost
80
+ /// @param requiredAmount The exact amount of Principal Tokens that should have been transferred
19
81
  error ServiceDoesNotFulfillCorrectStakingAmount(uint256 requiredAmount);
82
+
83
+ /// @dev Thrown when confirmServiceStaking is not called in the same transaction as prepareServiceStaking
20
84
  error ServiceDoesNotStakeInSameTx();
21
- error AddressMismatch();
85
+
86
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
87
+ /// Time Lock Errors
88
+ ///▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
89
+
90
+ /// @dev Thrown when a user attempts to stake before their cooldown period expires
91
+ error AddressMustWaitToStakeAgain();
92
+
93
+ /// @dev Thrown when a user attempts full unstaking before the 21-day lock period expires
94
+ error AddressMustWaitToFullUnstake();
95
+
96
+ /// @dev Thrown when attempting to accept a proposal before the time delay has passed
97
+ error TimeToAcceptProposalNotReached();
22
98
  }
@@ -1,39 +1,105 @@
1
1
  // SPDX-License-Identifier: EVVM-NONCOMMERCIAL-1.0
2
2
  // Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
3
3
  pragma solidity ^0.8.0;
4
+ /**
5
+ * @title SignatureUtils
6
+ * @author Mate Labs
7
+ * @notice Library for EIP-191 signature verification in the Staking contract
8
+ * @dev This library is exclusive to the Staking.sol contract and provides
9
+ * functions to verify signatures for staking operations.
10
+ *
11
+ * Signature Format:
12
+ * All signatures follow the EIP-191 standard with message format:
13
+ * "[evvmID],[functionName],[isStaking],[amountOfStaking],[nonce]"
14
+ *
15
+ * Supported Operations:
16
+ * - Presale staking: Limited staking for pre-approved addresses
17
+ * - Public staking: Open staking for all users when enabled
18
+ */
4
19
 
5
- import {SignatureUtil} from "@evvm/testnet-contracts/library/utils/SignatureUtil.sol";
6
- import {AdvancedStrings} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
20
+ import {
21
+ SignatureUtil
22
+ } from "@evvm/testnet-contracts/library/utils/SignatureUtil.sol";
23
+ import {
24
+ AdvancedStrings
25
+ } from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
7
26
 
8
27
  library SignatureUtils {
9
28
  /**
10
- * @dev using EIP-191 (https://eips.ethereum.org/EIPS/eip-191) can be used to sign and
11
- * verify messages, the next functions are used to verify the messages signed
12
- * by the users
29
+ * @dev Uses EIP-191 (https://eips.ethereum.org/EIPS/eip-191) for message signing
30
+ * and verification. The following functions verify messages signed by users
31
+ * for staking operations.
13
32
  */
14
33
 
15
- function verifyMessageSignedForStake(
34
+ /**
35
+ * @notice Verifies an EIP-191 signature for presale staking operations
36
+ * @dev Message format: "[evvmID],presaleStaking,[isStaking],[amountOfStaking],[nonce]"
37
+ * Presale staking has a limit of 2 staking tokens per user
38
+ * @param evvmID Unique identifier of the EVVM instance
39
+ * @param signer Address that should have signed the message
40
+ * @param isStaking True for staking operation, false for unstaking
41
+ * @param amountOfStaking Amount of staking tokens (always 1 for presale)
42
+ * @param nonce Unique nonce to prevent replay attacks
43
+ * @param signature 65-byte EIP-191 signature to verify
44
+ * @return True if the signature is valid and matches the expected signer
45
+ */
46
+ function verifyMessageSignedForPresaleStake(
47
+ uint256 evvmID,
48
+ address signer,
49
+ bool isStaking,
50
+ uint256 amountOfStaking,
51
+ uint256 nonce,
52
+ bytes memory signature
53
+ ) internal pure returns (bool) {
54
+ return
55
+ SignatureUtil.verifySignature(
56
+ evvmID,
57
+ "presaleStaking",
58
+ string.concat(
59
+ AdvancedStrings.boolToString(isStaking),
60
+ ",",
61
+ AdvancedStrings.uintToString(amountOfStaking),
62
+ ",",
63
+ AdvancedStrings.uintToString(nonce)
64
+ ),
65
+ signature,
66
+ signer
67
+ );
68
+ }
69
+
70
+ /**
71
+ * @notice Verifies an EIP-191 signature for public staking operations
72
+ * @dev Message format: "[evvmID],publicStaking,[isStaking],[amountOfStaking],[nonce]"
73
+ * Public staking is available to all users when the feature is enabled
74
+ * @param evvmID Unique identifier of the EVVM instance
75
+ * @param signer Address that should have signed the message
76
+ * @param isStaking True for staking operation, false for unstaking
77
+ * @param amountOfStaking Amount of staking tokens to stake/unstake
78
+ * @param nonce Unique nonce to prevent replay attacks
79
+ * @param signature 65-byte EIP-191 signature to verify
80
+ * @return True if the signature is valid and matches the expected signer
81
+ */
82
+ function verifyMessageSignedForPublicStake(
16
83
  uint256 evvmID,
17
- address user,
18
- bool isExternalStaking,
19
- bool _isStaking,
20
- uint256 _amountOfStaking,
21
- uint256 _nonce,
84
+ address signer,
85
+ bool isStaking,
86
+ uint256 amountOfStaking,
87
+ uint256 nonce,
22
88
  bytes memory signature
23
89
  ) internal pure returns (bool) {
24
90
  return
25
91
  SignatureUtil.verifySignature(
26
92
  evvmID,
27
- isExternalStaking ? "publicStaking" : "presaleStaking",
93
+ "publicStaking",
28
94
  string.concat(
29
- _isStaking ? "true" : "false",
95
+ AdvancedStrings.boolToString(isStaking),
30
96
  ",",
31
- AdvancedStrings.uintToString(_amountOfStaking),
97
+ AdvancedStrings.uintToString(amountOfStaking),
32
98
  ",",
33
- AdvancedStrings.uintToString(_nonce)
99
+ AdvancedStrings.uintToString(nonce)
34
100
  ),
35
101
  signature,
36
- user
102
+ signer
37
103
  );
38
104
  }
39
105
  }
@@ -2,6 +2,18 @@
2
2
  // Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
3
3
 
4
4
  pragma solidity ^0.8.0;
5
+ /**
6
+ * @title StakingStructs
7
+ * @author Mate Labs
8
+ * @notice Abstract contract containing all data structures used by the Staking contract
9
+ * @dev This contract is exclusive to the Staking.sol contract and defines the data
10
+ * structures for managing staking operations, governance proposals, and user history.
11
+ *
12
+ * Structure Categories:
13
+ * - Staker Metadata: presaleStakerMetadata, HistoryMetadata
14
+ * - Governance Proposals: AddressTypeProposal, UintTypeProposal, BoolTypeProposal
15
+ * - Service Staking: ServiceStakingMetadata, AccountMetadata
16
+ */
5
17
 
6
18
  abstract contract StakingStructs {
7
19
  /**