@evvm/testnet-contracts 3.0.0 → 3.0.2

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.
@@ -88,9 +88,9 @@ contract Core is Storage {
88
88
 
89
89
  admin.current = _initialOwner;
90
90
 
91
- balances[_stakingContractAddress][evvmMetadata.principalTokenAddress] =
92
- getRewardAmount() *
93
- 2;
91
+ rewardFlowDistribution.flag = true;
92
+
93
+ _giveReward(_stakingContractAddress, 2);
94
94
 
95
95
  stakerList[_stakingContractAddress] = FLAG_IS_STAKER;
96
96
 
@@ -114,9 +114,9 @@ contract Core is Storage {
114
114
  revert Error.AddressCantBeZero();
115
115
 
116
116
  nameServiceAddress = _nameServiceAddress;
117
- balances[nameServiceAddress][evvmMetadata.principalTokenAddress] =
118
- 10000 *
119
- 10 ** 18;
117
+
118
+ _giveReward(_nameServiceAddress, 20);
119
+
120
120
  stakerList[nameServiceAddress] = FLAG_IS_STAKER;
121
121
 
122
122
  treasuryAddress = _treasuryAddress;
@@ -182,6 +182,8 @@ contract Core is Storage {
182
182
  }
183
183
  }
184
184
 
185
+ //░▒▓█ Testnet Functions ██████████████████████████████████████████████████████▓▒░
186
+
185
187
  /**
186
188
  * @notice Faucet: Adds balance to a user for testing (Testnet only).
187
189
  * @param user Recipient address.
@@ -194,6 +196,9 @@ contract Core is Storage {
194
196
  uint256 quantity
195
197
  ) external {
196
198
  balances[user][token] += quantity;
199
+
200
+ if (token == evvmMetadata.principalTokenAddress)
201
+ currentSupply += quantity;
197
202
  }
198
203
 
199
204
  /**
@@ -254,7 +259,7 @@ contract Core is Storage {
254
259
  ) != from
255
260
  ) revert Error.InvalidSignature();
256
261
 
257
- if (!canExecuteUserTransaction(from))
262
+ if (!_canExecuteUserTransaction(from))
258
263
  revert Error.UserCannotExecuteTransaction();
259
264
 
260
265
  if (isAsyncExec) {
@@ -288,9 +293,9 @@ contract Core is Storage {
288
293
  _updateBalance(from, to, token, amount);
289
294
 
290
295
  if (isAddressStaker(msg.sender)) {
291
- if (priorityFee > 0) {
296
+ if (priorityFee > 0)
292
297
  _updateBalance(from, msg.sender, token, priorityFee);
293
- }
298
+
294
299
  _giveReward(msg.sender, 1);
295
300
  }
296
301
  }
@@ -332,7 +337,7 @@ contract Core is Storage {
332
337
  payment.signature
333
338
  ) !=
334
339
  payment.from ||
335
- !canExecuteUserTransaction(payment.from)
340
+ !_canExecuteUserTransaction(payment.from)
336
341
  ) {
337
342
  results[iteration] = false;
338
343
  continue;
@@ -367,6 +372,14 @@ contract Core is Storage {
367
372
  }
368
373
  }
369
374
 
375
+ if (
376
+ (listStatus.current == 0x01 && !allowList[payment.token]) ||
377
+ (listStatus.current == 0x02 && denyList[payment.token])
378
+ ) {
379
+ results[iteration] = false;
380
+ continue;
381
+ }
382
+
370
383
  if (
371
384
  (payment.senderExecutor != address(0) &&
372
385
  msg.sender != payment.senderExecutor) ||
@@ -450,7 +463,7 @@ contract Core is Storage {
450
463
  ) != from
451
464
  ) revert Error.InvalidSignature();
452
465
 
453
- if (!canExecuteUserTransaction(from))
466
+ if (!_canExecuteUserTransaction(from))
454
467
  revert Error.UserCannotExecuteTransaction();
455
468
 
456
469
  if (isAsyncExec) {
@@ -480,6 +493,8 @@ contract Core is Storage {
480
493
  if (balances[from][token] < amount + (isSenderStaker ? priorityFee : 0))
481
494
  revert Error.InsufficientBalance();
482
495
 
496
+ if (listStatus.current != 0x00) _verifyTokenInteractionAllowance(token);
497
+
483
498
  uint256 acomulatedAmount = 0;
484
499
  balances[from][token] -= (amount + (isSenderStaker ? priorityFee : 0));
485
500
  address to_aux;
@@ -546,6 +561,8 @@ contract Core is Storage {
546
561
  address token,
547
562
  uint256 amount
548
563
  ) external {
564
+ if (listStatus.current != 0x00) _verifyTokenInteractionAllowance(token);
565
+
549
566
  address from = msg.sender;
550
567
 
551
568
  if (!CAUtils.verifyIfCA(from)) revert Error.NotAnCA();
@@ -608,7 +625,7 @@ contract Core is Storage {
608
625
  if (originExecutor != address(0) && tx.origin != originExecutor)
609
626
  revert Error.OriginIsNotTheOriginExecutor();
610
627
 
611
- if (!canExecuteUserTransaction(user))
628
+ if (!_canExecuteUserTransaction(user))
612
629
  revert Error.UserCannotExecuteTransaction();
613
630
 
614
631
  if (isAsyncExec) {
@@ -688,17 +705,15 @@ contract Core is Storage {
688
705
  * - Canceling pending service operations
689
706
  * - Correcting accidental reservations
690
707
  * - Freeing nonces for different services
691
- *
692
- * @param user Address that reserved the nonce
693
708
  * @param nonce The async nonce to revoke reservation for
694
709
  */
695
- function revokeAsyncNonce(address user, uint256 nonce) external {
696
- if (asyncNonce[user][nonce]) revert Error.AsyncNonceAlreadyUsed();
710
+ function revokeAsyncNonce(uint256 nonce) external {
711
+ if (asyncNonce[msg.sender][nonce]) revert Error.AsyncNonceAlreadyUsed();
697
712
 
698
- if (asyncNonceReservedPointers[user][nonce] == address(0))
713
+ if (asyncNonceReservedPointers[msg.sender][nonce] == address(0))
699
714
  revert Error.AsyncNonceNotReserved();
700
715
 
701
- asyncNonceReservedPointers[user][nonce] = address(0);
716
+ asyncNonceReservedPointers[msg.sender][nonce] = address(0);
702
717
  }
703
718
 
704
719
  //░▒▓█ UserValidator Management Functions █████████████████████████████████████▓▒░
@@ -764,7 +779,7 @@ contract Core is Storage {
764
779
  */
765
780
  function acceptUserValidatorProposal() external onlyAdmin {
766
781
  if (block.timestamp < userValidatorAddress.timeToAccept)
767
- revert Error.ProposalForUserValidatorNotReady();
782
+ revert Error.ProposalNotReadyToAccept();
768
783
 
769
784
  userValidatorAddress.current = userValidatorAddress.proposal;
770
785
  userValidatorAddress.proposal = address(0);
@@ -806,6 +821,8 @@ contract Core is Storage {
806
821
  address token,
807
822
  uint256 amount
808
823
  ) external {
824
+ if (listStatus.current != 0x00) _verifyTokenInteractionAllowance(token);
825
+
809
826
  if (msg.sender != treasuryAddress) revert Error.SenderIsNotTreasury();
810
827
 
811
828
  balances[user][token] += amount;
@@ -830,6 +847,113 @@ contract Core is Storage {
830
847
 
831
848
  //░▒▓█ Administrative Functions ████████████████████████████████████████████████████████▓▒░
832
849
 
850
+ //██ Total Supply Management ████████████████████████████████████████
851
+
852
+ function proposeDeleteTotalSupply() external onlyAdmin {
853
+ if (
854
+ currentSupply < (evvmMetadata.totalSupply * 9999) / 10000 ||
855
+ evvmMetadata.totalSupply == type(uint256).max
856
+ ) revert Error.MaxSupplyDeletionNotAllowed();
857
+
858
+ timeToDeleteMaxSupply = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
859
+ }
860
+
861
+ function rejectDeleteTotalSupply() external onlyAdmin {
862
+ timeToDeleteMaxSupply = 0;
863
+ }
864
+
865
+ function acceptDeleteTotalSupply() external onlyAdmin {
866
+ if (block.timestamp < timeToDeleteMaxSupply)
867
+ revert Error.ProposalNotReadyToAccept();
868
+
869
+ evvmMetadata.totalSupply = type(uint256).max;
870
+ }
871
+
872
+ //██ Reward distribution ████████████████████████████████████████
873
+
874
+ function proposeChangeBaseRewardAmount(
875
+ uint256 newBaseReward
876
+ ) external onlyAdmin {
877
+ if (
878
+ evvmMetadata.totalSupply != type(uint256).max ||
879
+ newBaseReward >= evvmMetadata.reward
880
+ ) revert Error.BaseRewardIncreaseNotAllowed();
881
+ proposalChangeReward = newBaseReward;
882
+ timeToAcceptChangeReward = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
883
+ }
884
+
885
+ function rejectChangeBaseRewardAmount() external onlyAdmin {
886
+ proposalChangeReward = 0;
887
+ timeToAcceptChangeReward = 0;
888
+ }
889
+
890
+ function acceptChangeBaseRewardAmount() external onlyAdmin {
891
+ if (block.timestamp < timeToAcceptChangeReward)
892
+ revert Error.ProposalNotReadyToAccept();
893
+
894
+ evvmMetadata.reward = proposalChangeReward;
895
+ proposalChangeReward = 0;
896
+ timeToAcceptChangeReward = 0;
897
+ }
898
+
899
+ function proposeChangeRewardFlowDistribution() external onlyAdmin {
900
+ if (currentSupply < (evvmMetadata.totalSupply * 9999) / 10000)
901
+ revert Error.RewardFlowDistributionChangeNotAllowed();
902
+
903
+ rewardFlowDistribution.timeToAccept =
904
+ block.timestamp +
905
+ TIME_TO_ACCEPT_PROPOSAL;
906
+ }
907
+
908
+ function rejectChangeRewardFlowDistribution() external onlyAdmin {
909
+ rewardFlowDistribution.timeToAccept = 0;
910
+ }
911
+
912
+ function acceptChangeRewardFlowDistribution() external onlyAdmin {
913
+ if (block.timestamp < rewardFlowDistribution.timeToAccept)
914
+ revert Error.ProposalNotReadyToAccept();
915
+
916
+ rewardFlowDistribution.flag = !rewardFlowDistribution.flag;
917
+ rewardFlowDistribution.timeToAccept = 0;
918
+ }
919
+
920
+ //██ List state Management ████████████████████████████████████████
921
+
922
+ function proposeListStatus(bytes1 newStatus) external onlyAdmin {
923
+ if (uint8(newStatus) >= uint8(0x03)) revert Error.InvalidListStatus();
924
+
925
+ listStatus.proposal = newStatus;
926
+ listStatus.timeToAccept = block.timestamp + TIME_TO_ACCEPT_PROPOSAL;
927
+ }
928
+
929
+ function rejectListStatusProposal() external onlyAdmin {
930
+ listStatus.proposal = 0x00;
931
+ listStatus.timeToAccept = 0;
932
+ }
933
+
934
+ function acceptListStatusProposal() external onlyAdmin {
935
+ if (block.timestamp < listStatus.timeToAccept)
936
+ revert Error.ProposalNotReadyToAccept();
937
+
938
+ listStatus.current = listStatus.proposal;
939
+ listStatus.proposal = 0x00;
940
+ listStatus.timeToAccept = 0;
941
+ }
942
+
943
+ function setTokenStatusOnAllowList(
944
+ address token,
945
+ bool status
946
+ ) external onlyAdmin {
947
+ allowList[token] = status;
948
+ }
949
+
950
+ function setTokenStatusOnDenyList(
951
+ address token,
952
+ bool status
953
+ ) external onlyAdmin {
954
+ denyList[token] = status;
955
+ }
956
+
833
957
  //██ Proxy Management █████████████████████████████████████████████
834
958
 
835
959
  /**
@@ -857,7 +981,7 @@ contract Core is Storage {
857
981
  */
858
982
  function acceptImplementation() external onlyAdmin {
859
983
  if (block.timestamp < timeToAcceptImplementation)
860
- revert Error.TimeLockNotExpired();
984
+ revert Error.ProposalNotReadyToAccept();
861
985
 
862
986
  currentImplementation = proposalImplementation;
863
987
  proposalImplementation = address(0);
@@ -898,7 +1022,7 @@ contract Core is Storage {
898
1022
  */
899
1023
  function acceptAdmin() external {
900
1024
  if (block.timestamp < admin.timeToAccept)
901
- revert Error.TimeLockNotExpired();
1025
+ revert Error.ProposalNotReadyToAccept();
902
1026
 
903
1027
  if (msg.sender != admin.proposal)
904
1028
  revert Error.SenderIsNotTheProposedAdmin();
@@ -933,42 +1057,21 @@ contract Core is Storage {
933
1057
  * - Can be called by anyone when conditions are met
934
1058
  */
935
1059
  function recalculateReward() public {
936
- if (evvmMetadata.totalSupply > evvmMetadata.eraTokens) {
1060
+ if (
1061
+ evvmMetadata.totalSupply > evvmMetadata.eraTokens &&
1062
+ evvmMetadata.totalSupply != type(uint256).max
1063
+ ) {
937
1064
  evvmMetadata.eraTokens += ((evvmMetadata.totalSupply -
938
1065
  evvmMetadata.eraTokens) / 2);
939
1066
  balances[msg.sender][evvmMetadata.principalTokenAddress] +=
940
1067
  evvmMetadata.reward *
941
- getRandom(1, 5083);
1068
+ _getRandom(1, 5083);
942
1069
  evvmMetadata.reward = evvmMetadata.reward / 2;
943
1070
  } else {
944
1071
  revert();
945
1072
  }
946
1073
  }
947
1074
 
948
- /**
949
- * @notice Generates a pseudo-random number within a specified range
950
- * @dev Uses block timestamp and prevrandao for randomness (suitable for non-critical randomness)
951
- *
952
- * Randomness Source:
953
- * - Combines block.timestamp and block.prevrandao
954
- * - Suitable for reward bonuses and non-security-critical randomness
955
- * - Not suitable for high-stakes randomness requiring true unpredictability
956
- *
957
- * @param min Minimum value (inclusive)
958
- * @param max Maximum value (inclusive)
959
- * @return Random number between min and max (inclusive)
960
- */
961
- function getRandom(
962
- uint256 min,
963
- uint256 max
964
- ) internal view returns (uint256) {
965
- return
966
- min +
967
- (uint256(
968
- keccak256(abi.encodePacked(block.timestamp, block.prevrandao))
969
- ) % (max - min + 1));
970
- }
971
-
972
1075
  //░▒▓█ Staking Integration Functions █████████████████████████████████████████████████▓▒░
973
1076
 
974
1077
  /**
@@ -1045,19 +1148,6 @@ contract Core is Storage {
1045
1148
  return evvmMetadata.EvvmID;
1046
1149
  }
1047
1150
 
1048
- /**
1049
- * @notice Gets the acceptance deadline for pending token whitelist proposals
1050
- * @dev Returns timestamp when prepared tokens can be added to whitelist
1051
- * @return Timestamp when pending token can be whitelisted (0 if no pending proposal)
1052
- */
1053
- function getWhitelistTokenToBeAddedDateToSet()
1054
- external
1055
- view
1056
- returns (uint256)
1057
- {
1058
- return whitelistTokenToBeAdded_dateToSet;
1059
- }
1060
-
1061
1151
  /**
1062
1152
  * @notice Gets the current NameService contract address
1063
1153
  * @dev Returns the address used for identity resolution in payments
@@ -1076,18 +1166,6 @@ contract Core is Storage {
1076
1166
  return stakingContractAddress;
1077
1167
  }
1078
1168
 
1079
- /**
1080
- * @notice Gets the next Fisher Bridge deposit nonce for a user
1081
- * @dev Returns the expected nonce for the next cross-chain deposit
1082
- * @param user Address to check deposit nonce for
1083
- * @return Next Fisher Bridge deposit nonce
1084
- */
1085
- function getNextFisherDepositNonce(
1086
- address user
1087
- ) external view returns (uint256) {
1088
- return nextFisherDepositNonce[user];
1089
- }
1090
-
1091
1169
  /**
1092
1170
  * @notice Gets the balance of a specific token for a user
1093
1171
  * @dev Returns the current balance stored in the EVVM system
@@ -1112,15 +1190,6 @@ contract Core is Storage {
1112
1190
  return stakerList[user] == FLAG_IS_STAKER;
1113
1191
  }
1114
1192
 
1115
- /**
1116
- * @notice Gets the current era token threshold for reward transitions
1117
- * @dev Returns the token supply threshold that triggers the next reward halving
1118
- * @return Current era tokens threshold
1119
- */
1120
- function getEraPrincipalToken() public view returns (uint256) {
1121
- return evvmMetadata.eraTokens;
1122
- }
1123
-
1124
1193
  /**
1125
1194
  * @notice Gets the current Principal Token reward amount per transaction
1126
1195
  * @dev Returns the base reward distributed to stakers for transaction processing
@@ -1130,6 +1199,25 @@ contract Core is Storage {
1130
1199
  return evvmMetadata.reward;
1131
1200
  }
1132
1201
 
1202
+ /**
1203
+ * @notice Gets comprehensive details of the reward change proposal
1204
+ * @dev Returns current reward, proposed reward and time-lock info
1205
+ *
1206
+ * @return Proposal struct with current reward, proposed reward,
1207
+ * and time to accept the proposal
1208
+ */
1209
+ function getFullDetailReward()
1210
+ public
1211
+ view
1212
+ returns (ProposalStructs.UintTypeProposal memory)
1213
+ {
1214
+ return ProposalStructs.UintTypeProposal({
1215
+ current: evvmMetadata.reward,
1216
+ proposal: proposalChangeReward,
1217
+ timeToAccept: timeToAcceptChangeReward
1218
+ });
1219
+ }
1220
+
1133
1221
  /**
1134
1222
  * @notice Gets the total supply of the Principal Token
1135
1223
  * @dev Returns the current total supply used for era transition calculations
@@ -1139,6 +1227,14 @@ contract Core is Storage {
1139
1227
  return evvmMetadata.totalSupply;
1140
1228
  }
1141
1229
 
1230
+ /**
1231
+ * @notice Gets the current supply of the Principal Token in circulation
1232
+ * @dev Returns the current circulating supply used for reward recalculations
1233
+ */
1234
+ function getCurrentSupply() public view returns (uint256) {
1235
+ return currentSupply;
1236
+ }
1237
+
1142
1238
  /**
1143
1239
  * @notice Gets the current active implementation contract address
1144
1240
  * @dev Returns the implementation used by the proxy for delegatecalls
@@ -1149,21 +1245,23 @@ contract Core is Storage {
1149
1245
  }
1150
1246
 
1151
1247
  /**
1152
- * @notice Gets the proposed implementation contract address
1153
- * @dev Returns the implementation pending approval for proxy upgrade
1154
- * @return Address of the proposed implementation contract (zero if none)
1155
- */
1156
- function getProposalImplementation() public view returns (address) {
1157
- return proposalImplementation;
1158
- }
1159
-
1160
- /**
1161
- * @notice Gets the acceptance deadline for the pending implementation upgrade
1162
- * @dev Returns timestamp when the proposed implementation can be accepted
1163
- * @return Timestamp when implementation upgrade can be executed (0 if no pending proposal)
1248
+ * @notice Gets comprehensive details of the implementation upgrade proposal
1249
+ * @dev Returns current, proposed implementation addresses and time-lock info
1250
+ *
1251
+ * @return Proposal struct with current implementation, proposed implementation,
1252
+ * and time to accept the proposal
1164
1253
  */
1165
- function getTimeToAcceptImplementation() public view returns (uint256) {
1166
- return timeToAcceptImplementation;
1254
+ function getFullDetailImplementation()
1255
+ public
1256
+ view
1257
+ returns (ProposalStructs.AddressTypeProposal memory)
1258
+ {
1259
+ return
1260
+ ProposalStructs.AddressTypeProposal({
1261
+ current: currentImplementation,
1262
+ proposal: proposalImplementation,
1263
+ timeToAccept: timeToAcceptImplementation
1264
+ });
1167
1265
  }
1168
1266
 
1169
1267
  /**
@@ -1175,31 +1273,12 @@ contract Core is Storage {
1175
1273
  return admin.current;
1176
1274
  }
1177
1275
 
1178
- /**
1179
- * @notice Gets the proposed admin address
1180
- * @dev Returns the address pending approval for admin privileges
1181
- * @return Address of the proposed admin (zero if no pending proposal)
1182
- */
1183
- function getProposalAdmin() public view returns (address) {
1184
- return admin.proposal;
1185
- }
1186
-
1187
- /**
1188
- * @notice Gets the acceptance deadline for the pending admin change
1189
- * @dev Returns timestamp when the proposed admin can accept the role
1190
- * @return Timestamp when admin change can be executed (0 if no pending proposal)
1191
- */
1192
- function getTimeToAcceptAdmin() public view returns (uint256) {
1193
- return admin.timeToAccept;
1194
- }
1195
-
1196
- /**
1197
- * @notice Gets the address of the token pending whitelist approval
1198
- * @dev Returns the token address that can be whitelisted after time delay
1199
- * @return Address of the token prepared for whitelisting (zero if none)
1200
- */
1201
- function getWhitelistTokenToBeAdded() public view returns (address) {
1202
- return whitelistTokenToBeAdded_address;
1276
+ function getFullDetailAdmin()
1277
+ public
1278
+ view
1279
+ returns (ProposalStructs.AddressTypeProposal memory)
1280
+ {
1281
+ return admin;
1203
1282
  }
1204
1283
 
1205
1284
  /**
@@ -1288,7 +1367,7 @@ contract Core is Storage {
1288
1367
  * @return Proposal struct with current validator address,
1289
1368
  * proposed address, and time to accept
1290
1369
  */
1291
- function getUserValidatorAddressDetails()
1370
+ function getFullDetailUserValidator()
1292
1371
  public
1293
1372
  view
1294
1373
  returns (ProposalStructs.AddressTypeProposal memory)
@@ -1296,8 +1375,113 @@ contract Core is Storage {
1296
1375
  return userValidatorAddress;
1297
1376
  }
1298
1377
 
1378
+ /**
1379
+ * @notice Gets the current token list status (none, denylist, allowlist)
1380
+ * @dev Returns byte code indicating current token restriction mode
1381
+ * - 0x00: No restrictions
1382
+ * - 0x01: Denylist active
1383
+ * - 0x02: Allowlist active
1384
+ */
1385
+ function getCurrentListStatus() public view returns (bytes1) {
1386
+ return listStatus.current;
1387
+ }
1388
+
1389
+ /**
1390
+ * @notice Gets comprehensive token list status details
1391
+ * @dev Returns current list status along with pending proposal info
1392
+ */
1393
+ function getFullDetailListStatus()
1394
+ public
1395
+ view
1396
+ returns (ProposalStructs.Bytes1TypeProposal memory)
1397
+ {
1398
+ return listStatus;
1399
+ }
1400
+
1401
+ /**
1402
+ * @notice Checks if a token is on the allowList or denyList based on current list status
1403
+ * @dev Returns boolean indicating if token is allowed for execution
1404
+ * - true if allowed
1405
+ * - false if denied
1406
+ */
1407
+ function getAllowListStatus(address token) public view returns (bool) {
1408
+ return allowList[token];
1409
+ }
1410
+
1411
+ /**
1412
+ * @notice Checks if a token is on the denylist or allowlist based on current list status
1413
+ * @dev Returns boolean indicating if token is restricted for execution
1414
+ * - true if denied
1415
+ * - false if allowed
1416
+ */
1417
+ function getDenyListStatus(address token) public view returns (bool) {
1418
+ return denyList[token];
1419
+ }
1420
+
1421
+ /**
1422
+ * @notice Gets the current status of the reward flow distribution flag
1423
+ * @dev Returns boolean indicating if reward distribution is active
1424
+ * - true if rewards are distributed to stakers
1425
+ * - false if rewards are disabled
1426
+ */
1427
+ function getRewardFlowDistributionFlag() public view returns (bool) {
1428
+ return rewardFlowDistribution.flag;
1429
+ }
1430
+
1431
+ /**
1432
+ * @notice Gets full details of the reward flow distribution proposal
1433
+ * @dev Returns current flag, proposed flag, and time-lock info
1434
+ *
1435
+ * @return Proposal struct with current flag, proposed flag, and time to accept
1436
+ */
1437
+ function getFullDetailRewardFlowDistribution()
1438
+ public
1439
+ view
1440
+ returns (ProposalStructs.BoolTypeProposal memory)
1441
+ {
1442
+ return rewardFlowDistribution;
1443
+ }
1444
+
1445
+ /**
1446
+ * @notice Gets the time remaining to delete the maximum supply
1447
+ * @dev Returns the timestamp when the max supply can be deleted
1448
+ *
1449
+ * @return Timestamp for max supply deletion
1450
+ */
1451
+ function getTimeToDeleteMaxSupply() public view returns (uint256) {
1452
+ return timeToDeleteMaxSupply;
1453
+ }
1454
+
1299
1455
  //░▒▓█ Internal Functions █████████████████████████████████████████████████████▓▒░
1300
1456
 
1457
+ /**
1458
+ * @notice Generates a pseudo-random number within a specified range
1459
+ * @dev Uses block timestamp and prevrandao for randomness (suitable for non-critical randomness)
1460
+ *
1461
+ * @param min Minimum value (inclusive)
1462
+ * @param max Maximum value (inclusive)
1463
+ * @return Random number between min and max (inclusive)
1464
+ */
1465
+ function _getRandom(
1466
+ uint256 min,
1467
+ uint256 max
1468
+ ) internal view returns (uint256) {
1469
+ uint256 randomHash = uint256(
1470
+ keccak256(
1471
+ abi.encodePacked(
1472
+ blockhash(block.number - 1),
1473
+ block.timestamp,
1474
+ block.prevrandao,
1475
+ msg.sender,
1476
+ tx.origin,
1477
+ gasleft()
1478
+ )
1479
+ )
1480
+ );
1481
+
1482
+ return min + (randomHash % (max - min + 1));
1483
+ }
1484
+
1301
1485
  //██ Balance Management █████████████████████████████████████████████
1302
1486
 
1303
1487
  /**
@@ -1325,6 +1509,8 @@ contract Core is Storage {
1325
1509
  address token,
1326
1510
  uint256 value
1327
1511
  ) internal {
1512
+ if (listStatus.current != 0x00) _verifyTokenInteractionAllowance(token);
1513
+
1328
1514
  uint256 fromBalance = balances[from][token];
1329
1515
  if (fromBalance < value) revert Error.InsufficientBalance();
1330
1516
 
@@ -1350,20 +1536,28 @@ contract Core is Storage {
1350
1536
  *
1351
1537
  * @param user Address of the staker to receive principal token rewards
1352
1538
  * @param amount Number of transactions or reward multiplier
1353
- * @return success True if reward distribution completed successfully
1354
1539
  */
1355
- function _giveReward(address user, uint256 amount) internal returns (bool) {
1356
- uint256 principalReward = evvmMetadata.reward * amount;
1357
- uint256 userBalance = balances[user][
1358
- evvmMetadata.principalTokenAddress
1359
- ];
1540
+ function _giveReward(address user, uint256 amount) internal {
1541
+ if (
1542
+ !rewardFlowDistribution.flag ||
1543
+ currentSupply >= evvmMetadata.totalSupply
1544
+ ) return;
1360
1545
 
1361
- balances[user][evvmMetadata.principalTokenAddress] =
1362
- userBalance +
1363
- principalReward;
1546
+ uint256 principalReward = evvmMetadata.reward * amount;
1547
+ balances[user][evvmMetadata.principalTokenAddress] += principalReward;
1548
+ currentSupply += principalReward;
1549
+ }
1364
1550
 
1365
- return (userBalance + principalReward ==
1366
- balances[user][evvmMetadata.principalTokenAddress]);
1551
+ /**
1552
+ * @notice Internal function to check from the token allowlist/denylist
1553
+ * based on current list status and revert if the token is not allowed for execution
1554
+ * @dev Used by functions that execute transactions to enforce token restrictions
1555
+ */
1556
+ function _verifyTokenInteractionAllowance(address token) internal view {
1557
+ if (
1558
+ (listStatus.current == 0x01 && !allowList[token]) ||
1559
+ (listStatus.current == 0x02 && denyList[token])
1560
+ ) revert Error.TokenIsDeniedForExecution();
1367
1561
  }
1368
1562
 
1369
1563
  //██ User Validation █████████████████████████████████████████████
@@ -1385,7 +1579,7 @@ contract Core is Storage {
1385
1579
  * @param user Address to check execution permission for
1386
1580
  * @return True if user can execute, false if blocked
1387
1581
  */
1388
- function canExecuteUserTransaction(
1582
+ function _canExecuteUserTransaction(
1389
1583
  address user
1390
1584
  ) internal view returns (bool) {
1391
1585
  if (userValidatorAddress.current == address(0)) return true;