@evvm/testnet-contracts 1.0.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 +166 -0
  2. package/README.md +216 -0
  3. package/package.json +51 -0
  4. package/src/contracts/evvm/Evvm.sol +1327 -0
  5. package/src/contracts/evvm/EvvmLegacy.sol +1553 -0
  6. package/src/contracts/evvm/lib/ErrorsLib.sol +17 -0
  7. package/src/contracts/evvm/lib/EvvmStorage.sol +60 -0
  8. package/src/contracts/evvm/lib/EvvmStructs.sol +64 -0
  9. package/src/contracts/evvm/lib/SignatureUtils.sol +124 -0
  10. package/src/contracts/nameService/NameService.sol +1751 -0
  11. package/src/contracts/nameService/lib/ErrorsLib.sol +27 -0
  12. package/src/contracts/nameService/lib/SignatureUtils.sol +239 -0
  13. package/src/contracts/staking/Estimator.sol +358 -0
  14. package/src/contracts/staking/Staking.sol +1148 -0
  15. package/src/contracts/staking/lib/ErrorsLib.sol +19 -0
  16. package/src/contracts/staking/lib/SignatureUtils.sol +68 -0
  17. package/src/contracts/treasury/Treasury.sol +104 -0
  18. package/src/contracts/treasury/lib/ErrorsLib.sol +11 -0
  19. package/src/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +551 -0
  20. package/src/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +512 -0
  21. package/src/contracts/treasuryTwoChains/lib/ErrorsLib.sol +15 -0
  22. package/src/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +41 -0
  23. package/src/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +52 -0
  24. package/src/contracts/treasuryTwoChains/lib/SignatureUtils.sol +47 -0
  25. package/src/interfaces/IEstimator.sol +102 -0
  26. package/src/interfaces/IEvvm.sol +195 -0
  27. package/src/interfaces/INameService.sol +283 -0
  28. package/src/interfaces/IStaking.sol +202 -0
  29. package/src/interfaces/ITreasury.sol +17 -0
  30. package/src/interfaces/ITreasuryExternalChainStation.sol +262 -0
  31. package/src/interfaces/ITreasuryHostChainStation.sol +251 -0
  32. package/src/lib/AdvancedStrings.sol +77 -0
  33. package/src/lib/Erc191TestBuilder.sol +402 -0
  34. package/src/lib/SignatureRecover.sol +56 -0
@@ -0,0 +1,1148 @@
1
+ // SPDX-License-Identifier: EVVM-NONCOMMERCIAL-1.0
2
+ // Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
3
+
4
+ pragma solidity ^0.8.0;
5
+ /**
6
+
7
+
8
+ /$$$$$$ /$$ /$$ /$$
9
+ /$$__ $$| $$ | $$ |__/
10
+ | $$ \__/$$$$$$ /$$$$$$| $$ /$$/$$/$$$$$$$ /$$$$$$
11
+ | $$$$$|_ $$_/ |____ $| $$ /$$| $| $$__ $$/$$__ $$
12
+ \____ $$| $$ /$$$$$$| $$$$$$/| $| $$ \ $| $$ \ $$
13
+ /$$ \ $$| $$ /$$/$$__ $| $$_ $$| $| $$ | $| $$ | $$
14
+ | $$$$$$/| $$$$| $$$$$$| $$ \ $| $| $$ | $| $$$$$$$
15
+ \______/ \___/ \_______|__/ \__|__|__/ |__/\____ $$
16
+ /$$ \ $$
17
+ | $$$$$$/
18
+ \______/
19
+
20
+ ████████╗███████╗███████╗████████╗███╗ ██╗███████╗████████╗
21
+ ╚══██╔══╝██╔════╝██╔════╝╚══██╔══╝████╗ ██║██╔════╝╚══██╔══╝
22
+ ██║ █████╗ ███████╗ ██║ ██╔██╗ ██║█████╗ ██║
23
+ ██║ ██╔══╝ ╚════██║ ██║ ██║╚██╗██║██╔══╝ ██║
24
+ ██║ ███████╗███████║ ██║ ██║ ╚████║███████╗ ██║
25
+ ╚═╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
26
+ * @title Staking Mate contract
27
+ * @author jistro.eth ariutokintumi.eth
28
+ * @notice This contract manages the staking mechanism for the EVVM ecosystem
29
+ * @dev Handles presale staking, public staking, and service staking with time locks and signature verification
30
+ *
31
+ * The contract supports three types of staking:
32
+ * 1. Golden Staking: Exclusive to the goldenFisher address
33
+ * 2. Presale Staking: Limited to 800 presale users with 2 staking token limit
34
+ * 3. Public Staking: Open to all users when enabled
35
+ * 4. Service Staking: Allows smart contracts to stake on behalf of users
36
+ *
37
+ * Key features:
38
+ * - Time-locked unstaking mechanisms
39
+ * - Signature-based authorization
40
+ * - Integration with EVVM core contract for payments and rewards
41
+ * - Estimator integration for yield calculations
42
+ */
43
+
44
+ import {Evvm} from "@evvm/testnet-contracts/contracts/evvm/Evvm.sol";
45
+ import {NameService} from "@evvm/testnet-contracts/contracts/nameService/NameService.sol";
46
+ import {Estimator} from "@evvm/testnet-contracts/contracts/staking/Estimator.sol";
47
+ import {ErrorsLib} from "@evvm/testnet-contracts/contracts/staking/lib/ErrorsLib.sol";
48
+ import {SignatureUtils} from "@evvm/testnet-contracts/contracts/staking/lib/SignatureUtils.sol";
49
+
50
+ contract Staking {
51
+ /**
52
+ * @dev Metadata for presale stakers
53
+ * @param isAllow Whether the address is allowed to participate in presale staking
54
+ * @param stakingAmount Current number of staking tokens staked (max 2 for presale)
55
+ */
56
+ struct presaleStakerMetadata {
57
+ bool isAllow;
58
+ uint256 stakingAmount;
59
+ }
60
+
61
+ /**
62
+ * @dev Struct to store the history of the user
63
+ * @param transactionType Type of transaction:
64
+ * - 0x01 for staking
65
+ * - 0x02 for unstaking
66
+ * - Other values for yield/reward transactions
67
+ * @param amount Amount of staking staked/unstaked or reward received
68
+ * @param timestamp Timestamp when the transaction occurred
69
+ * @param totalStaked Total amount of staking currently staked after this transaction
70
+ */
71
+ struct HistoryMetadata {
72
+ bytes32 transactionType;
73
+ uint256 amount;
74
+ uint256 timestamp;
75
+ uint256 totalStaked;
76
+ }
77
+
78
+ /**
79
+ * @dev Struct for managing address change proposals with time delay
80
+ * @param actual Current active address
81
+ * @param proposal Proposed new address
82
+ * @param timeToAccept Timestamp when the proposal can be accepted
83
+ */
84
+ struct AddressTypeProposal {
85
+ address actual;
86
+ address proposal;
87
+ uint256 timeToAccept;
88
+ }
89
+
90
+ /**
91
+ * @dev Struct for managing uint256 change proposals with time delay
92
+ * @param actual Current active value
93
+ * @param proposal Proposed new value
94
+ * @param timeToAccept Timestamp when the proposal can be accepted
95
+ */
96
+ struct UintTypeProposal {
97
+ uint256 actual;
98
+ uint256 proposal;
99
+ uint256 timeToAccept;
100
+ }
101
+
102
+ /**
103
+ * @dev Struct for managing boolean flag changes with time delay
104
+ * @param flag Current boolean state
105
+ * @param timeToAccept Timestamp when the flag change can be executed
106
+ */
107
+ struct BoolTypeProposal {
108
+ bool flag;
109
+ uint256 timeToAccept;
110
+ }
111
+
112
+ /// @dev Address of the EVVM core contract
113
+ address private EVVM_ADDRESS;
114
+
115
+ /// @dev Maximum number of presale stakers allowed
116
+ uint256 private constant LIMIT_PRESALE_STAKER = 800;
117
+ /// @dev Current count of registered presale stakers
118
+ uint256 private presaleStakerCount;
119
+ /// @dev Price of one staking main token (5083 main token = 1 staking)
120
+ uint256 private constant PRICE_OF_STAKING = 5083 * (10 ** 18);
121
+
122
+ /// @dev Admin address management with proposal system
123
+ AddressTypeProposal private admin;
124
+ /// @dev Golden Fisher address management with proposal system
125
+ AddressTypeProposal private goldenFisher;
126
+ /// @dev Estimator contract address management with proposal system
127
+ AddressTypeProposal private estimator;
128
+ /// @dev Time delay for regular staking after unstaking
129
+ UintTypeProposal private secondsToUnlockStaking;
130
+ /// @dev Time delay for full unstaking (21 days default)
131
+ UintTypeProposal private secondsToUnllockFullUnstaking;
132
+ /// @dev Flag to enable/disable presale staking
133
+ BoolTypeProposal private allowPresaleStaking;
134
+ /// @dev Flag to enable/disable public staking
135
+ BoolTypeProposal private allowPublicStaking;
136
+
137
+ /// @dev Address representing the principal Principal Token
138
+ address private constant PRINCIPAL_TOKEN_ADDRESS =
139
+ 0x0000000000000000000000000000000000000001;
140
+
141
+ /// @dev One-time setup breaker for estimator and EVVM addresses
142
+ bytes1 private breakerSetupEstimatorAndEvvm;
143
+
144
+ /// @dev Mapping to track used nonces for staking operations per user
145
+ mapping(address => mapping(uint256 => bool)) private stakingNonce;
146
+
147
+ /// @dev Mapping to store presale staker metadata
148
+ mapping(address => presaleStakerMetadata) private userPresaleStaker;
149
+
150
+ /// @dev Mapping to store complete staking history for each user
151
+ mapping(address => HistoryMetadata[]) private userHistory;
152
+
153
+ /// @dev Modifier to restrict access to admin functions
154
+ modifier onlyOwner() {
155
+ if (msg.sender != admin.actual) revert ErrorsLib.SenderIsNotAdmin();
156
+
157
+ _;
158
+ }
159
+
160
+ /**
161
+ * @notice Contract constructor
162
+ * @dev Initializes the staking contract with admin and golden fisher addresses
163
+ * @param initialAdmin Address that will have admin privileges
164
+ * @param initialGoldenFisher Address that will have golden fisher privileges
165
+ */
166
+ constructor(address initialAdmin, address initialGoldenFisher) {
167
+ admin.actual = initialAdmin;
168
+
169
+ goldenFisher.actual = initialGoldenFisher;
170
+
171
+ allowPublicStaking.flag = true;
172
+ allowPresaleStaking.flag = false;
173
+
174
+ secondsToUnlockStaking.actual = 0;
175
+
176
+ secondsToUnllockFullUnstaking.actual = 21 days;
177
+
178
+ breakerSetupEstimatorAndEvvm = 0x01;
179
+ }
180
+
181
+ /**
182
+ * @notice One-time setup function for estimator and EVVM addresses
183
+ * @dev Can only be called once during contract initialization
184
+ * @param _estimator Address of the Estimator contract
185
+ * @param _evvm Address of the EVVM core contract
186
+ */
187
+ function _setupEstimatorAndEvvm(
188
+ address _estimator,
189
+ address _evvm
190
+ ) external {
191
+ if (breakerSetupEstimatorAndEvvm == 0x00) revert();
192
+
193
+ estimator.actual = _estimator;
194
+ EVVM_ADDRESS = _evvm;
195
+ breakerSetupEstimatorAndEvvm = 0x00;
196
+ }
197
+
198
+ /**
199
+ * @notice Allows the golden fisher to stake/unstake with synchronized EVVM nonces
200
+ * @dev Only the golden fisher address can call this function
201
+ * @param isStaking True for staking, false for unstaking
202
+ * @param amountOfStaking Amount of staking tokens to stake/unstake
203
+ * @param signature_EVVM Signature for the EVVM contract transaction
204
+ */
205
+ function goldenStaking(
206
+ bool isStaking,
207
+ uint256 amountOfStaking,
208
+ bytes memory signature_EVVM
209
+ ) external {
210
+ if (msg.sender != goldenFisher.actual)
211
+ revert ErrorsLib.SenderIsNotGoldenFisher();
212
+
213
+ stakingUserProcess(
214
+ goldenFisher.actual,
215
+ amountOfStaking,
216
+ isStaking,
217
+ 0,
218
+ Evvm(EVVM_ADDRESS).getNextCurrentSyncNonce(msg.sender),
219
+ false,
220
+ signature_EVVM
221
+ );
222
+ }
223
+
224
+ /**
225
+ * @notice Allows presale users to stake/unstake with a limit of 2 staking tokens
226
+ * @dev Only registered presale users can call this function when presale staking is enabled
227
+ * @param user Address of the user performing the staking operation
228
+ * @param isStaking True for staking, false for unstaking
229
+ * @param nonce Unique nonce for this staking operation
230
+ * @param signature Signature proving authorization for this staking operation
231
+ * @param priorityFee_EVVM Priority fee for the EVVM transaction
232
+ * @param nonce_EVVM Nonce for the EVVM contract transaction
233
+ * @param priorityFlag_EVVM True for async EVVM transaction, false for sync
234
+ * @param signature_EVVM Signature for the EVVM contract transaction
235
+ */
236
+ function presaleStaking(
237
+ address user,
238
+ bool isStaking,
239
+ uint256 nonce,
240
+ bytes memory signature,
241
+ uint256 priorityFee_EVVM,
242
+ uint256 nonce_EVVM,
243
+ bool priorityFlag_EVVM,
244
+ bytes memory signature_EVVM
245
+ ) external {
246
+ if (
247
+ !SignatureUtils.verifyMessageSignedForStake(
248
+ Evvm(EVVM_ADDRESS).getEvvmID(),
249
+ user,
250
+ false,
251
+ isStaking,
252
+ 1,
253
+ nonce,
254
+ signature
255
+ )
256
+ ) revert ErrorsLib.InvalidSignatureOnStaking();
257
+
258
+ if (checkIfStakeNonceUsed(user, nonce))
259
+ revert ErrorsLib.StakingNonceAlreadyUsed();
260
+
261
+ presaleClaims(isStaking, user);
262
+
263
+ if (!allowPresaleStaking.flag)
264
+ revert ErrorsLib.PresaleStakingDisabled();
265
+
266
+ stakingUserProcess(
267
+ user,
268
+ 1,
269
+ isStaking,
270
+ priorityFee_EVVM,
271
+ nonce_EVVM,
272
+ priorityFlag_EVVM,
273
+ signature_EVVM
274
+ );
275
+
276
+ stakingNonce[user][nonce] = true;
277
+ }
278
+
279
+ /**
280
+ * @notice Internal function to manage presale staking limits and permissions
281
+ * @dev Enforces the 2 staking token limit for presale users and tracks staking amounts
282
+ * @param _isStaking True for staking (increments count), false for unstaking (decrements count)
283
+ * @param _user Address of the presale user
284
+ */
285
+ function presaleClaims(bool _isStaking, address _user) internal {
286
+ if (allowPublicStaking.flag) {
287
+ revert ErrorsLib.PresaleStakingDisabled();
288
+ } else {
289
+ if (userPresaleStaker[_user].isAllow) {
290
+ if (_isStaking) {
291
+ // staking
292
+
293
+ if (userPresaleStaker[_user].stakingAmount >= 2)
294
+ revert ErrorsLib.UserPresaleStakerLimitExceeded();
295
+
296
+ userPresaleStaker[_user].stakingAmount++;
297
+ } else {
298
+ // unstaking
299
+
300
+ if (userPresaleStaker[_user].stakingAmount == 0)
301
+ revert ErrorsLib.UserPresaleStakerLimitExceeded();
302
+
303
+ userPresaleStaker[_user].stakingAmount--;
304
+ }
305
+ } else {
306
+ revert ErrorsLib.UserIsNotPresaleStaker();
307
+ }
308
+ }
309
+ }
310
+
311
+ /**
312
+ * @notice Allows any user to stake/unstake when public staking is enabled
313
+ * @dev Requires signature verification and handles nonce management
314
+ * @param user Address of the user performing the staking operation
315
+ * @param isStaking True for staking, false for unstaking
316
+ * @param amountOfStaking Amount of staking tokens to stake/unstake
317
+ * @param nonce Unique nonce for this staking operation
318
+ * @param signature Signature proving authorization for this staking operation
319
+ * @param priorityFee_EVVM Priority fee for the EVVM transaction
320
+ * @param nonce_EVVM Nonce for the EVVM contract transaction
321
+ * @param priorityFlag_EVVM True for async EVVM transaction, false for sync
322
+ * @param signature_EVVM Signature for the EVVM contract transaction
323
+ */
324
+ function publicStaking(
325
+ address user,
326
+ bool isStaking,
327
+ uint256 amountOfStaking,
328
+ uint256 nonce,
329
+ bytes memory signature,
330
+ uint256 priorityFee_EVVM,
331
+ uint256 nonce_EVVM,
332
+ bool priorityFlag_EVVM,
333
+ bytes memory signature_EVVM
334
+ ) external {
335
+ if (!allowPublicStaking.flag) {
336
+ revert();
337
+ }
338
+
339
+ if (
340
+ !SignatureUtils.verifyMessageSignedForStake(
341
+ Evvm(EVVM_ADDRESS).getEvvmID(),
342
+ user,
343
+ true,
344
+ isStaking,
345
+ amountOfStaking,
346
+ nonce,
347
+ signature
348
+ )
349
+ ) revert ErrorsLib.InvalidSignatureOnStaking();
350
+
351
+ if (checkIfStakeNonceUsed(user, nonce))
352
+ revert ErrorsLib.StakingNonceAlreadyUsed();
353
+
354
+ stakingUserProcess(
355
+ user,
356
+ amountOfStaking,
357
+ isStaking,
358
+ priorityFee_EVVM,
359
+ nonce_EVVM,
360
+ priorityFlag_EVVM,
361
+ signature_EVVM
362
+ );
363
+
364
+ stakingNonce[user][nonce] = true;
365
+ }
366
+
367
+ /**
368
+ * @notice Allows smart contracts (services) to stake on behalf of users
369
+ * @dev Verifies that the service address has contract code and handles service-specific logic
370
+ * @param user Address of the user who owns the stake
371
+ * @param service Address of the smart contract performing the staking
372
+ * @param isStaking True for staking, false for unstaking
373
+ * @param amountOfStaking Amount of staking tokens to stake/unstake
374
+ * @param nonce Unique nonce for this staking operation
375
+ * @param signature Signature proving authorization for service staking
376
+ * @param priorityFee_EVVM Priority fee for the EVVM transaction (only for staking)
377
+ * @param nonce_EVVM Nonce for the EVVM contract transaction (only for staking)
378
+ * @param priorityFlag_EVVM Priority flag for EVVM transaction (only for staking)
379
+ * @param signature_EVVM Signature for the EVVM contract transaction (only for staking)
380
+ */
381
+ function publicServiceStaking(
382
+ address user,
383
+ address service,
384
+ bool isStaking,
385
+ uint256 amountOfStaking,
386
+ uint256 nonce,
387
+ bytes memory signature,
388
+ uint256 priorityFee_EVVM,
389
+ uint256 nonce_EVVM,
390
+ bool priorityFlag_EVVM,
391
+ bytes memory signature_EVVM
392
+ ) external {
393
+ if (!allowPublicStaking.flag) revert ErrorsLib.PublicStakingDisabled();
394
+
395
+ uint256 size;
396
+
397
+ assembly {
398
+ /// @dev check the size of the opcode of the address
399
+ size := extcodesize(service)
400
+ }
401
+
402
+ if (size == 0) revert ErrorsLib.AddressIsNotAService();
403
+
404
+ if (isStaking) {
405
+ if (
406
+ !SignatureUtils.verifyMessageSignedForPublicServiceStake(
407
+ Evvm(EVVM_ADDRESS).getEvvmID(),
408
+ user,
409
+ service,
410
+ isStaking,
411
+ amountOfStaking,
412
+ nonce,
413
+ signature
414
+ )
415
+ ) revert ErrorsLib.InvalidSignatureOnStaking();
416
+ } else {
417
+ if (service != user) revert ErrorsLib.UserAndServiceMismatch();
418
+ }
419
+
420
+ if (checkIfStakeNonceUsed(user, nonce))
421
+ revert ErrorsLib.StakingNonceAlreadyUsed();
422
+
423
+ stakingServiceProcess(
424
+ user,
425
+ service,
426
+ isStaking,
427
+ amountOfStaking,
428
+ isStaking ? priorityFee_EVVM : 0,
429
+ isStaking ? nonce_EVVM : 0,
430
+ isStaking ? priorityFlag_EVVM : false,
431
+ isStaking ? signature_EVVM : bytes("")
432
+ );
433
+
434
+ stakingNonce[user][nonce] = true;
435
+ }
436
+
437
+ /**
438
+ * @notice Internal function to process service staking operations
439
+ * @dev Wrapper function that calls the base staking process for service operations
440
+ * @param user Address of the user who owns the stake
441
+ * @param service Address of the smart contract performing the staking
442
+ * @param isStaking True for staking, false for unstaking
443
+ * @param amountOfStaking Amount of staking tokens to stake/unstake
444
+ * @param priorityFee_EVVM Priority fee for the EVVM transaction
445
+ * @param nonce_EVVM Nonce for the EVVM contract transaction
446
+ * @param priorityFlag_EVVM Priority flag for EVVM transaction
447
+ * @param signature_EVVM Signature for the EVVM contract transaction
448
+ */
449
+ function stakingServiceProcess(
450
+ address user,
451
+ address service,
452
+ bool isStaking,
453
+ uint256 amountOfStaking,
454
+ uint256 priorityFee_EVVM,
455
+ uint256 nonce_EVVM,
456
+ bool priorityFlag_EVVM,
457
+ bytes memory signature_EVVM
458
+ ) internal {
459
+ stakingBaseProcess(
460
+ user,
461
+ service,
462
+ isStaking,
463
+ amountOfStaking,
464
+ priorityFee_EVVM,
465
+ nonce_EVVM,
466
+ priorityFlag_EVVM,
467
+ signature_EVVM
468
+ );
469
+ }
470
+
471
+ /**
472
+ * @notice Internal function to process user staking operations
473
+ * @dev Wrapper function that calls the base staking process for user operations
474
+ * @param user Address of the user performing the staking operation
475
+ * @param amountOfStaking Amount of staking tokens to stake/unstake
476
+ * @param isStaking True for staking, false for unstaking
477
+ * @param priorityFee_EVVM Priority fee for the EVVM transaction
478
+ * @param nonce_EVVM Nonce for the EVVM contract transaction
479
+ * @param priorityFlag_EVVM Priority flag for EVVM transaction
480
+ * @param signature_EVVM Signature for the EVVM contract transaction
481
+ */
482
+ function stakingUserProcess(
483
+ address user,
484
+ uint256 amountOfStaking,
485
+ bool isStaking,
486
+ uint256 priorityFee_EVVM,
487
+ uint256 nonce_EVVM,
488
+ bool priorityFlag_EVVM,
489
+ bytes memory signature_EVVM
490
+ ) internal {
491
+ stakingBaseProcess(
492
+ user,
493
+ user,
494
+ isStaking,
495
+ amountOfStaking,
496
+ priorityFee_EVVM,
497
+ nonce_EVVM,
498
+ priorityFlag_EVVM,
499
+ signature_EVVM
500
+ );
501
+ }
502
+
503
+ /**
504
+ * @notice Core staking logic that handles both service and user staking operations
505
+ * @dev Processes payments, updates history, handles time locks, and manages EVVM integration
506
+ * @param userAccount Address of the user paying for the transaction
507
+ * @param stakingAccount Address that will receive the stake/unstake (can be same as userAccount)
508
+ * @param isStaking True for staking (requires payment), false for unstaking (provides refund)
509
+ * @param amountOfStaking Amount of staking tokens to stake/unstake
510
+ * @param priorityFee_EVVM Priority fee for EVVM transaction
511
+ * @param nonce_EVVM Nonce for EVVM contract transaction
512
+ * @param priorityFlag_EVVM True for async EVVM transaction, false for sync
513
+ * @param signature_EVVM Signature for EVVM contract transaction
514
+ */
515
+ function stakingBaseProcess(
516
+ address userAccount,
517
+ address stakingAccount,
518
+ bool isStaking,
519
+ uint256 amountOfStaking,
520
+ uint256 priorityFee_EVVM,
521
+ uint256 nonce_EVVM,
522
+ bool priorityFlag_EVVM,
523
+ bytes memory signature_EVVM
524
+ ) internal {
525
+ uint256 auxSMsteBalance;
526
+
527
+ if (isStaking) {
528
+ if (
529
+ getTimeToUserUnlockStakingTime(stakingAccount) > block.timestamp
530
+ ) revert ErrorsLib.UserMustWaitToStakeAgain();
531
+
532
+ makePay(
533
+ userAccount,
534
+ (PRICE_OF_STAKING * amountOfStaking),
535
+ priorityFee_EVVM,
536
+ priorityFlag_EVVM,
537
+ nonce_EVVM,
538
+ signature_EVVM
539
+ );
540
+
541
+ Evvm(EVVM_ADDRESS).pointStaker(stakingAccount, 0x01);
542
+
543
+ auxSMsteBalance = userHistory[stakingAccount].length == 0
544
+ ? amountOfStaking
545
+ : userHistory[stakingAccount][
546
+ userHistory[stakingAccount].length - 1
547
+ ].totalStaked + amountOfStaking;
548
+ } else {
549
+ if (amountOfStaking == getUserAmountStaked(stakingAccount)) {
550
+ if (
551
+ getTimeToUserUnlockFullUnstakingTime(stakingAccount) >
552
+ block.timestamp
553
+ ) revert ErrorsLib.UserMustWaitToFullUnstake();
554
+
555
+ Evvm(EVVM_ADDRESS).pointStaker(stakingAccount, 0x00);
556
+ }
557
+
558
+ // Only for user unstaking, not service
559
+ if (userAccount == stakingAccount && priorityFee_EVVM != 0) {
560
+ makePay(
561
+ userAccount,
562
+ priorityFee_EVVM,
563
+ 0,
564
+ priorityFlag_EVVM,
565
+ nonce_EVVM,
566
+ signature_EVVM
567
+ );
568
+ }
569
+
570
+ auxSMsteBalance =
571
+ userHistory[stakingAccount][
572
+ userHistory[stakingAccount].length - 1
573
+ ].totalStaked -
574
+ amountOfStaking;
575
+
576
+ makeCaPay(
577
+ PRINCIPAL_TOKEN_ADDRESS,
578
+ stakingAccount,
579
+ (PRICE_OF_STAKING * amountOfStaking)
580
+ );
581
+ }
582
+
583
+ userHistory[stakingAccount].push(
584
+ HistoryMetadata({
585
+ transactionType: isStaking
586
+ ? bytes32(uint256(1))
587
+ : bytes32(uint256(2)),
588
+ amount: amountOfStaking,
589
+ timestamp: block.timestamp,
590
+ totalStaked: auxSMsteBalance
591
+ })
592
+ );
593
+
594
+ if (Evvm(EVVM_ADDRESS).isAddressStaker(msg.sender)) {
595
+ makeCaPay(
596
+ PRINCIPAL_TOKEN_ADDRESS,
597
+ msg.sender,
598
+ (Evvm(EVVM_ADDRESS).getRewardAmount() * 2) + priorityFee_EVVM
599
+ );
600
+ }
601
+ }
602
+
603
+ /**
604
+ * @notice Allows users to claim their staking rewards (yield)
605
+ * @dev Interacts with the Estimator contract to calculate and distribute rewards
606
+ * @param user Address of the user claiming rewards
607
+ * @return epochAnswer Epoch identifier for the reward calculation
608
+ * @return tokenToBeRewarded Address of the token being rewarded
609
+ * @return amountTotalToBeRewarded Total amount of rewards to be distributed
610
+ * @return idToOverwriteUserHistory Index in user history to update with reward info
611
+ * @return timestampToBeOverwritten Timestamp to record for the reward transaction
612
+ */
613
+ function gimmeYiel(
614
+ address user
615
+ )
616
+ external
617
+ returns (
618
+ bytes32 epochAnswer,
619
+ address tokenToBeRewarded,
620
+ uint256 amountTotalToBeRewarded,
621
+ uint256 idToOverwriteUserHistory,
622
+ uint256 timestampToBeOverwritten
623
+ )
624
+ {
625
+ if (userHistory[user].length > 0) {
626
+ (
627
+ epochAnswer,
628
+ tokenToBeRewarded,
629
+ amountTotalToBeRewarded,
630
+ idToOverwriteUserHistory,
631
+ timestampToBeOverwritten
632
+ ) = Estimator(estimator.actual).makeEstimation(user);
633
+
634
+ if (amountTotalToBeRewarded > 0) {
635
+ makeCaPay(tokenToBeRewarded, user, amountTotalToBeRewarded);
636
+
637
+ userHistory[user][idToOverwriteUserHistory]
638
+ .transactionType = epochAnswer;
639
+ userHistory[user][idToOverwriteUserHistory]
640
+ .amount = amountTotalToBeRewarded;
641
+ userHistory[user][idToOverwriteUserHistory]
642
+ .timestamp = timestampToBeOverwritten;
643
+
644
+ if (Evvm(EVVM_ADDRESS).isAddressStaker(msg.sender)) {
645
+ makeCaPay(
646
+ PRINCIPAL_TOKEN_ADDRESS,
647
+ msg.sender,
648
+ (Evvm(EVVM_ADDRESS).getRewardAmount() * 1)
649
+ );
650
+ }
651
+ }
652
+ }
653
+ }
654
+
655
+ //▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
656
+ // Tools for Evvm Integration
657
+ //▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
658
+
659
+ /**
660
+ * @notice Internal function to handle payments through the EVVM contract
661
+ * @dev Supports both synchronous and asynchronous payment modes
662
+ * @param user Address of the user making the payment
663
+ * @param amount Amount to be paid in Principal Tokens
664
+ * @param priorityFee Additional priority fee for the transaction
665
+ * @param priorityFlag True for async payment, false for sync payment
666
+ * @param nonce Nonce for the EVVM transaction
667
+ * @param signature Signature authorizing the payment
668
+ */
669
+ function makePay(
670
+ address user,
671
+ uint256 amount,
672
+ uint256 priorityFee,
673
+ bool priorityFlag,
674
+ uint256 nonce,
675
+ bytes memory signature
676
+ ) internal {
677
+ Evvm(EVVM_ADDRESS).pay(
678
+ user,
679
+ address(this),
680
+ "",
681
+ PRINCIPAL_TOKEN_ADDRESS,
682
+ amount,
683
+ priorityFee,
684
+ nonce,
685
+ priorityFlag,
686
+ address(this),
687
+ signature
688
+ );
689
+ }
690
+
691
+ /**
692
+ * @notice Internal function to handle token distributions through EVVM contract
693
+ * @dev Used for unstaking refunds and reward distributions
694
+ * @param tokenAddress Address of the token to be distributed
695
+ * @param user Address of the recipient
696
+ * @param amount Amount of tokens to distribute
697
+ */
698
+ function makeCaPay(
699
+ address tokenAddress,
700
+ address user,
701
+ uint256 amount
702
+ ) internal {
703
+ Evvm(EVVM_ADDRESS).caPay(user, tokenAddress, amount);
704
+ }
705
+
706
+ //▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
707
+ // Administrative Functions with Time-Delayed Governance
708
+ //▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
709
+
710
+ /**
711
+ * @notice Adds a single address to the presale staker list
712
+ * @dev Only admin can call this function, limited to 800 presale stakers total
713
+ * @param _staker Address to be added to the presale staker list
714
+ */
715
+ function addPresaleStaker(address _staker) external onlyOwner {
716
+ if (presaleStakerCount > LIMIT_PRESALE_STAKER) {
717
+ revert();
718
+ }
719
+ userPresaleStaker[_staker].isAllow = true;
720
+ presaleStakerCount++;
721
+ }
722
+
723
+ /**
724
+ * @notice Adds multiple addresses to the presale staker list in batch
725
+ * @dev Only admin can call this function, limited to 800 presale stakers total
726
+ * @param _stakers Array of addresses to be added to the presale staker list
727
+ */
728
+ function addPresaleStakers(address[] calldata _stakers) external onlyOwner {
729
+ for (uint256 i = 0; i < _stakers.length; i++) {
730
+ if (presaleStakerCount > LIMIT_PRESALE_STAKER) {
731
+ revert();
732
+ }
733
+ userPresaleStaker[_stakers[i]].isAllow = true;
734
+ presaleStakerCount++;
735
+ }
736
+ }
737
+
738
+ /**
739
+ * @notice Proposes a new admin address with 1-day time delay
740
+ * @dev Part of the time-delayed governance system for admin changes
741
+ * @param _newAdmin Address of the proposed new admin
742
+ */
743
+ function proposeAdmin(address _newAdmin) external onlyOwner {
744
+ admin.proposal = _newAdmin;
745
+ admin.timeToAccept = block.timestamp + 1 days;
746
+ }
747
+
748
+ /**
749
+ * @notice Rejects the current admin proposal
750
+ * @dev Only current admin can reject the pending proposal
751
+ */
752
+ function rejectProposalAdmin() external onlyOwner {
753
+ admin.proposal = address(0);
754
+ admin.timeToAccept = 0;
755
+ }
756
+
757
+ /**
758
+ * @notice Accepts the admin proposal and becomes the new admin
759
+ * @dev Can only be called by the proposed admin after the time delay has passed
760
+ */
761
+ function acceptNewAdmin() external {
762
+ if (
763
+ msg.sender != admin.proposal || admin.timeToAccept > block.timestamp
764
+ ) {
765
+ revert();
766
+ }
767
+ admin.actual = admin.proposal;
768
+ admin.proposal = address(0);
769
+ admin.timeToAccept = 0;
770
+ }
771
+
772
+ function proposeGoldenFisher(address _goldenFisher) external onlyOwner {
773
+ goldenFisher.proposal = _goldenFisher;
774
+ goldenFisher.timeToAccept = block.timestamp + 1 days;
775
+ }
776
+
777
+ function rejectProposalGoldenFisher() external onlyOwner {
778
+ goldenFisher.proposal = address(0);
779
+ goldenFisher.timeToAccept = 0;
780
+ }
781
+
782
+ function acceptNewGoldenFisher() external onlyOwner {
783
+ if (goldenFisher.timeToAccept > block.timestamp) {
784
+ revert();
785
+ }
786
+ goldenFisher.actual = goldenFisher.proposal;
787
+ goldenFisher.proposal = address(0);
788
+ goldenFisher.timeToAccept = 0;
789
+ }
790
+
791
+ function proposeSetSecondsToUnlockStaking(
792
+ uint256 _secondsToUnlockStaking
793
+ ) external onlyOwner {
794
+ secondsToUnlockStaking.proposal = _secondsToUnlockStaking;
795
+ secondsToUnlockStaking.timeToAccept = block.timestamp + 1 days;
796
+ }
797
+
798
+ function rejectProposalSetSecondsToUnlockStaking() external onlyOwner {
799
+ secondsToUnlockStaking.proposal = 0;
800
+ secondsToUnlockStaking.timeToAccept = 0;
801
+ }
802
+
803
+ function acceptSetSecondsToUnlockStaking() external onlyOwner {
804
+ if (secondsToUnlockStaking.timeToAccept > block.timestamp) {
805
+ revert();
806
+ }
807
+ secondsToUnlockStaking.actual = secondsToUnlockStaking.proposal;
808
+ secondsToUnlockStaking.proposal = 0;
809
+ secondsToUnlockStaking.timeToAccept = 0;
810
+ }
811
+
812
+ function prepareSetSecondsToUnllockFullUnstaking(
813
+ uint256 _secondsToUnllockFullUnstaking
814
+ ) external onlyOwner {
815
+ secondsToUnllockFullUnstaking.proposal = _secondsToUnllockFullUnstaking;
816
+ secondsToUnllockFullUnstaking.timeToAccept = block.timestamp + 1 days;
817
+ }
818
+
819
+ function cancelSetSecondsToUnllockFullUnstaking() external onlyOwner {
820
+ secondsToUnllockFullUnstaking.proposal = 0;
821
+ secondsToUnllockFullUnstaking.timeToAccept = 0;
822
+ }
823
+
824
+ function confirmSetSecondsToUnllockFullUnstaking() external onlyOwner {
825
+ if (secondsToUnllockFullUnstaking.timeToAccept > block.timestamp) {
826
+ revert();
827
+ }
828
+ secondsToUnllockFullUnstaking.actual = secondsToUnllockFullUnstaking
829
+ .proposal;
830
+ secondsToUnllockFullUnstaking.proposal = 0;
831
+ secondsToUnllockFullUnstaking.timeToAccept = 0;
832
+ }
833
+
834
+ function prepareChangeAllowPublicStaking() external onlyOwner {
835
+ allowPublicStaking.timeToAccept = block.timestamp + 1 days;
836
+ }
837
+
838
+ function cancelChangeAllowPublicStaking() external onlyOwner {
839
+ allowPublicStaking.timeToAccept = 0;
840
+ }
841
+
842
+ function confirmChangeAllowPublicStaking() external onlyOwner {
843
+ if (allowPublicStaking.timeToAccept > block.timestamp) {
844
+ revert();
845
+ }
846
+ allowPublicStaking = BoolTypeProposal({
847
+ flag: !allowPublicStaking.flag,
848
+ timeToAccept: 0
849
+ });
850
+ }
851
+
852
+ function prepareChangeAllowPresaleStaking() external onlyOwner {
853
+ allowPresaleStaking.timeToAccept = block.timestamp + 1 days;
854
+ }
855
+
856
+ function cancelChangeAllowPresaleStaking() external onlyOwner {
857
+ allowPresaleStaking.timeToAccept = 0;
858
+ }
859
+
860
+ function confirmChangeAllowPresaleStaking() external onlyOwner {
861
+ if (allowPresaleStaking.timeToAccept > block.timestamp) {
862
+ revert();
863
+ }
864
+ allowPresaleStaking = BoolTypeProposal({
865
+ flag: !allowPresaleStaking.flag,
866
+ timeToAccept: 0
867
+ });
868
+ }
869
+
870
+ function proposeEstimator(address _estimator) external onlyOwner {
871
+ estimator.proposal = _estimator;
872
+ estimator.timeToAccept = block.timestamp + 1 days;
873
+ }
874
+
875
+ function rejectProposalEstimator() external onlyOwner {
876
+ estimator.proposal = address(0);
877
+ estimator.timeToAccept = 0;
878
+ }
879
+
880
+ function acceptNewEstimator() external onlyOwner {
881
+ if (estimator.timeToAccept > block.timestamp) {
882
+ revert();
883
+ }
884
+ estimator.actual = estimator.proposal;
885
+ estimator.proposal = address(0);
886
+ estimator.timeToAccept = 0;
887
+ }
888
+
889
+ //▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
890
+ // View Functions - Public Data Access
891
+ //▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
892
+
893
+ /**
894
+ * @notice Returns the complete staking history for an address
895
+ * @dev Returns an array of all staking transactions and rewards for the user
896
+ * @param _account Address to query the history for
897
+ * @return Array of HistoryMetadata containing all transactions
898
+ */
899
+ function getAddressHistory(
900
+ address _account
901
+ ) public view returns (HistoryMetadata[] memory) {
902
+ return userHistory[_account];
903
+ }
904
+
905
+ /**
906
+ * @notice Returns the number of transactions in an address's staking history
907
+ * @dev Useful for pagination or checking if an address has any staking history
908
+ * @param _account Address to query the history size for
909
+ * @return Number of transactions in the history
910
+ */
911
+ function getSizeOfAddressHistory(
912
+ address _account
913
+ ) public view returns (uint256) {
914
+ return userHistory[_account].length;
915
+ }
916
+
917
+ /**
918
+ * @notice Returns a specific transaction from an address's staking history
919
+ * @dev Allows accessing individual transactions by index
920
+ * @param _account Address to query the history for
921
+ * @param _index Index of the transaction to retrieve (0-based)
922
+ * @return HistoryMetadata of the transaction at the specified index
923
+ */
924
+ function getAddressHistoryByIndex(
925
+ address _account,
926
+ uint256 _index
927
+ ) public view returns (HistoryMetadata memory) {
928
+ return userHistory[_account][_index];
929
+ }
930
+
931
+ /**
932
+ * @notice Returns the fixed price of one staking token in Principal Tokens
933
+ * @dev Returns the constant price of 5083 Principal Tokens per staking
934
+ * @return Price of one staking token in Principal Tokens (with 18 decimals)
935
+ */
936
+ function priceOfStaking() external pure returns (uint256) {
937
+ return PRICE_OF_STAKING;
938
+ }
939
+
940
+ /**
941
+ * @notice Calculates when a user can perform full unstaking (withdraw all tokens)
942
+ * @dev Full unstaking requires waiting 21 days after the last time their balance reached 0
943
+ * @param _account Address to check the unlock time for
944
+ * @return Timestamp when full unstaking will be allowed
945
+ */
946
+ function getTimeToUserUnlockFullUnstakingTime(
947
+ address _account
948
+ ) public view returns (uint256) {
949
+ for (uint256 i = userHistory[_account].length; i > 0; i--) {
950
+ if (userHistory[_account][i - 1].totalStaked == 0) {
951
+ return
952
+ userHistory[_account][i - 1].timestamp +
953
+ secondsToUnllockFullUnstaking.actual;
954
+ }
955
+ }
956
+
957
+ return
958
+ userHistory[_account][0].timestamp +
959
+ secondsToUnllockFullUnstaking.actual;
960
+ }
961
+
962
+ /**
963
+ * @notice Calculates when a user can stake again after unstaking
964
+ * @dev Users must wait a configurable period after unstaking before they can stake again
965
+ * @param _account Address to check the unlock time for
966
+ * @return Timestamp when staking will be allowed again (0 if already allowed)
967
+ */
968
+ function getTimeToUserUnlockStakingTime(
969
+ address _account
970
+ ) public view returns (uint256) {
971
+ uint256 lengthOfHistory = userHistory[_account].length;
972
+
973
+ if (lengthOfHistory == 0) {
974
+ return 0;
975
+ }
976
+ if (userHistory[_account][lengthOfHistory - 1].totalStaked == 0) {
977
+ return
978
+ userHistory[_account][lengthOfHistory - 1].timestamp +
979
+ secondsToUnlockStaking.actual;
980
+ } else {
981
+ return 0;
982
+ }
983
+ }
984
+
985
+ /**
986
+ * @notice Returns the current time delay for full unstaking operations
987
+ * @dev Full unstaking requires waiting this many seconds (default: 21 days)
988
+ * @return Number of seconds required to wait for full unstaking
989
+ */
990
+ function getSecondsToUnlockFullUnstaking() external view returns (uint256) {
991
+ return secondsToUnllockFullUnstaking.actual;
992
+ }
993
+
994
+ /**
995
+ * @notice Returns the current time delay for regular staking operations
996
+ * @dev Users must wait this many seconds after unstaking before they can stake again
997
+ * @return Number of seconds required to wait between unstaking and staking
998
+ */
999
+ function getSecondsToUnlockStaking() external view returns (uint256) {
1000
+ return secondsToUnlockStaking.actual;
1001
+ }
1002
+
1003
+ /**
1004
+ * @notice Returns the current amount of staking tokens staked by a user
1005
+ * @dev Returns the total staked amount from the user's most recent transaction
1006
+ * @param _account Address to check the staked amount for
1007
+ * @return Amount of staking tokens currently staked by the user
1008
+ */
1009
+ function getUserAmountStaked(
1010
+ address _account
1011
+ ) public view returns (uint256) {
1012
+ uint256 lengthOfHistory = userHistory[_account].length;
1013
+
1014
+ if (lengthOfHistory == 0) {
1015
+ return 0;
1016
+ }
1017
+
1018
+ return userHistory[_account][lengthOfHistory - 1].totalStaked;
1019
+ }
1020
+
1021
+ /**
1022
+ * @notice Checks if a specific nonce has been used for staking by a user
1023
+ * @dev Prevents replay attacks by tracking used nonces
1024
+ * @param _account Address to check the nonce for
1025
+ * @param _nonce Nonce value to check
1026
+ * @return True if the nonce has been used, false otherwise
1027
+ */
1028
+ function checkIfStakeNonceUsed(
1029
+ address _account,
1030
+ uint256 _nonce
1031
+ ) public view returns (bool) {
1032
+ return stakingNonce[_account][_nonce];
1033
+ }
1034
+
1035
+ /**
1036
+ * @notice Returns the current golden fisher address
1037
+ * @dev The golden fisher has special staking privileges
1038
+ * @return Address of the current golden fisher
1039
+ */
1040
+ function getGoldenFisher() external view returns (address) {
1041
+ return goldenFisher.actual;
1042
+ }
1043
+
1044
+ /**
1045
+ * @notice Returns the proposed new golden fisher address (if any)
1046
+ * @dev Shows pending golden fisher changes in the governance system
1047
+ * @return Address of the proposed golden fisher (zero address if none)
1048
+ */
1049
+ function getGoldenFisherProposal() external view returns (address) {
1050
+ return goldenFisher.proposal;
1051
+ }
1052
+
1053
+ /**
1054
+ * @notice Returns presale staker information for a given address
1055
+ * @dev Shows if an address is allowed for presale and how many tokens they've staked
1056
+ * @param _account Address to check presale status for
1057
+ * @return isAllow True if the address is allowed for presale staking
1058
+ * @return stakingAmount Number of staking tokens currently staked in presale (max 2)
1059
+ */
1060
+ function getPresaleStaker(
1061
+ address _account
1062
+ ) external view returns (bool, uint256) {
1063
+ return (
1064
+ userPresaleStaker[_account].isAllow,
1065
+ userPresaleStaker[_account].stakingAmount
1066
+ );
1067
+ }
1068
+
1069
+ /**
1070
+ * @notice Returns the current estimator contract address
1071
+ * @dev The estimator calculates staking rewards and yields
1072
+ * @return Address of the current estimator contract
1073
+ */
1074
+ function getEstimatorAddress() external view returns (address) {
1075
+ return estimator.actual;
1076
+ }
1077
+
1078
+ /**
1079
+ * @notice Returns the proposed new estimator contract address (if any)
1080
+ * @dev Shows pending estimator changes in the governance system
1081
+ * @return Address of the proposed estimator contract (zero address if none)
1082
+ */
1083
+ function getEstimatorProposal() external view returns (address) {
1084
+ return estimator.proposal;
1085
+ }
1086
+
1087
+ /**
1088
+ * @notice Returns the current number of registered presale stakers
1089
+ * @dev Maximum allowed is 800 presale stakers
1090
+ * @return Current count of presale stakers
1091
+ */
1092
+ function getPresaleStakerCount() external view returns (uint256) {
1093
+ return presaleStakerCount;
1094
+ }
1095
+
1096
+ /**
1097
+ * @notice Returns the complete public staking configuration and status
1098
+ * @dev Includes current flag state and any pending changes with timestamps
1099
+ * @return BoolTypeProposal struct containing flag and timeToAccept
1100
+ */
1101
+ function getAllDataOfAllowPublicStaking()
1102
+ external
1103
+ view
1104
+ returns (BoolTypeProposal memory)
1105
+ {
1106
+ return allowPublicStaking;
1107
+ }
1108
+
1109
+ /**
1110
+ * @notice Returns the complete presale staking configuration and status
1111
+ * @dev Includes current flag state and any pending changes with timestamps
1112
+ * @return BoolTypeProposal struct containing flag and timeToAccept
1113
+ */
1114
+ function getAllowPresaleStaking()
1115
+ external
1116
+ view
1117
+ returns (BoolTypeProposal memory)
1118
+ {
1119
+ return allowPresaleStaking;
1120
+ }
1121
+
1122
+ /**
1123
+ * @notice Returns the address of the EVVM core contract
1124
+ * @dev The EVVM contract handles payments and staker registration
1125
+ * @return Address of the EVVM core contract
1126
+ */
1127
+ function getEvvmAddress() external view returns (address) {
1128
+ return EVVM_ADDRESS;
1129
+ }
1130
+
1131
+ /**
1132
+ * @notice Returns the address representing the Principal Token
1133
+ * @dev This is a constant address used to represent the principal token
1134
+ * @return Address representing the Principal Token (0x...0001)
1135
+ */
1136
+ function getMateAddress() external pure returns (address) {
1137
+ return PRINCIPAL_TOKEN_ADDRESS;
1138
+ }
1139
+
1140
+ /**
1141
+ * @notice Returns the current admin/owner address
1142
+ * @dev The admin has full control over contract parameters and governance
1143
+ * @return Address of the current contract admin
1144
+ */
1145
+ function getOwner() external view returns (address) {
1146
+ return admin.actual;
1147
+ }
1148
+ }