@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.
- package/LICENSE +145 -118
- package/README.md +135 -42
- package/contracts/evvm/Evvm.sol +154 -181
- package/contracts/evvm/lib/ErrorsLib.sol +119 -6
- package/contracts/evvm/lib/EvvmStorage.sol +164 -9
- package/contracts/evvm/lib/EvvmStructs.sol +124 -6
- package/contracts/evvm/lib/SignatureUtils.sol +103 -61
- package/contracts/nameService/NameService.sol +165 -155
- package/contracts/nameService/lib/ErrorsLib.sol +142 -8
- package/contracts/nameService/lib/IdentityValidation.sol +21 -0
- package/contracts/nameService/lib/NameServiceStructs.sol +75 -19
- package/contracts/nameService/lib/SignatureUtils.sol +235 -60
- package/contracts/p2pSwap/P2PSwap.sol +205 -164
- package/contracts/staking/Estimator.sol +131 -24
- package/contracts/staking/Staking.sol +98 -113
- package/contracts/staking/lib/ErrorsLib.sol +79 -3
- package/contracts/staking/lib/SignatureUtils.sol +82 -16
- package/contracts/staking/lib/StakingStructs.sol +12 -0
- package/contracts/treasury/Treasury.sol +30 -12
- package/contracts/treasury/lib/ErrorsLib.sol +30 -0
- package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +3 -3
- package/interfaces/IEvvm.sol +9 -4
- package/interfaces/INameService.sol +12 -3
- package/interfaces/IStaking.sol +2 -1
- package/library/Erc191TestBuilder.sol +188 -0
- package/library/EvvmService.sol +55 -0
- package/library/primitives/SignatureRecover.sol +33 -0
- package/library/utils/AdvancedStrings.sol +61 -0
- package/library/utils/SignatureUtil.sol +34 -0
- package/library/utils/nonces/AsyncNonce.sol +42 -0
- package/library/utils/nonces/SyncNonce.sol +44 -0
- package/library/utils/service/EvvmPayments.sol +68 -1
- package/library/utils/service/StakingServiceUtils.sol +44 -0
- 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 {
|
|
44
|
+
import {Evvm} from "@evvm/testnet-contracts/contracts/evvm/Evvm.sol";
|
|
45
45
|
import {IEstimator} from "@evvm/testnet-contracts/interfaces/IEstimator.sol";
|
|
46
|
-
import {
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
|
|
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 =
|
|
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.
|
|
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
|
-
|
|
240
|
+
uint256 current = userPresaleStaker[user].stakingAmount;
|
|
222
241
|
|
|
223
|
-
if (
|
|
224
|
-
revert ErrorsLib.
|
|
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.
|
|
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
|
-
|
|
337
|
+
evvm.getPrincipalTokenAddress()
|
|
350
338
|
),
|
|
351
339
|
amountStakingBeforeStaking: evvm.getBalance(
|
|
352
340
|
address(this),
|
|
353
|
-
|
|
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
|
-
|
|
366
|
+
evvm.getBalance(msg.sender, evvm.getPrincipalTokenAddress()) &&
|
|
389
367
|
serviceStakingData.amountStakingBeforeStaking +
|
|
390
368
|
totalStakingRequired !=
|
|
391
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
699
|
-
|
|
700
|
-
|
|
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 =
|
|
871
|
-
|
|
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 =
|
|
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
|
|
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
|
|
1143
|
-
return
|
|
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
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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 {
|
|
6
|
-
|
|
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
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
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
|
-
|
|
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
|
|
18
|
-
bool
|
|
19
|
-
|
|
20
|
-
uint256
|
|
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
|
-
|
|
93
|
+
"publicStaking",
|
|
28
94
|
string.concat(
|
|
29
|
-
|
|
95
|
+
AdvancedStrings.boolToString(isStaking),
|
|
30
96
|
",",
|
|
31
|
-
AdvancedStrings.uintToString(
|
|
97
|
+
AdvancedStrings.uintToString(amountOfStaking),
|
|
32
98
|
",",
|
|
33
|
-
AdvancedStrings.uintToString(
|
|
99
|
+
AdvancedStrings.uintToString(nonce)
|
|
34
100
|
),
|
|
35
101
|
signature,
|
|
36
|
-
|
|
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
|
/**
|