1
1
// SPDX-License-Identifier: MIT
2
- pragma solidity ^ 0.8.18 ;
2
+ pragma solidity ^ 0.8.21 ;
3
3
4
4
import "@openzeppelin/contracts/token/ERC20/ERC20.sol " ;
5
5
import "@openzeppelin/contracts/security/ReentrancyGuard.sol " ;
6
6
import "@openzeppelin/contracts/access/Ownable.sol " ;
7
+ import "@openzeppelin/contracts/utils/math/Math.sol " ;
7
8
8
9
contract SuperconductorX is ERC20 , ReentrancyGuard , Ownable {
9
10
// Maximum token cap
@@ -27,6 +28,7 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
27
28
uint256 lastActionBlock;
28
29
}
29
30
mapping (address => UserState) public userStates;
31
+
30
32
// Events for creating entanglement
31
33
event EntanglementRequested (
32
34
address indexed requester ,
@@ -64,9 +66,16 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
64
66
uint256 amount
65
67
);
66
68
67
- // For community minting of SCX
68
- uint256 public constant SCX_PRICE_IN_ETH = 5e12 ; // 0.000005 ETH
69
- uint256 public soldSCXTokens = 0 ;
69
+ // Tier system for community minting of SCX
70
+ struct Tier {
71
+ uint256 tokenCap;
72
+ uint256 tokensSold;
73
+ uint256 priceInETH;
74
+ }
75
+ Tier[] public tiers;
76
+ uint256 public currentTier;
77
+ mapping (uint256 => mapping (address => uint256 )) public tierParticipants;
78
+ mapping (uint256 => address []) public tierParticipantAddresses;
70
79
71
80
// Events for community minting of SCX
72
81
event CommunityMint (
@@ -86,15 +95,25 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
86
95
87
96
constructor () ERC20 ("SuperconductorX " , "SCX " ) {
88
97
_mint (msg .sender , 100000000 * 10 ** decimals ()); // 100 million initial supply
98
+ tiers.push (Tier (25000000e18 , 0 , 5e12 )); // Tier 1: 25 million at 0.000005 ETH
89
99
}
90
100
91
101
// Applying an external force, similar to applying a magnetic field on a superconductor.
92
102
// A user's energy and temperature levels are adjusted based on the days elapsed since their last interaction.
93
103
function applyMagneticField () public {
104
+ require (balanceOf (msg .sender ) > 1000e18 , "Insufficient SCX " );
105
+ require (
106
+ userStates[msg .sender ].lastActionBlock != 0 ,
107
+ "Interact with the contract first "
108
+ );
109
+
94
110
uint256 daysElapsed = (block .number -
95
111
userStates[msg .sender ].lastActionBlock) / NUM_BLOCKS_DAY;
96
112
if (daysElapsed > 0 ) {
97
- uint256 totalDaysReward = daysElapsed;
113
+ uint256 baseReward = daysElapsed;
114
+ uint256 tokenMultiplier = Math.sqrt (balanceOf (msg .sender ) / 1e18 );
115
+ uint256 totalDaysReward = baseReward * tokenMultiplier;
116
+
98
117
userStates[msg .sender ].energyLevel += totalDaysReward;
99
118
userStates[msg .sender ].temperature = userStates[msg .sender ]
100
119
.temperature < totalDaysReward
@@ -115,7 +134,7 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
115
134
// Requesting entanglement mimics quantum entanglement in superconductors.
116
135
// By becoming entangled, the users' energy decreases and temperature increases.
117
136
function requestEntanglement (address pair ) public {
118
- require (pair != msg .sender , "Cannot entangle with oneself " );
137
+ require (pair != msg .sender , "Cannot entangle self " );
119
138
userStates[msg .sender ].entanglementRequest = pair;
120
139
userStates[msg .sender ].energyLevel = userStates[msg .sender ]
121
140
.energyLevel < UNIVERSAL_CONSTANT_ENERGY
@@ -136,7 +155,7 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
136
155
function acceptEntanglement (address requester ) public {
137
156
require (
138
157
userStates[requester].entanglementRequest == msg .sender ,
139
- "No entanglement request from this address "
158
+ "No request "
140
159
);
141
160
userStates[requester].entangledPair = msg .sender ;
142
161
userStates[msg .sender ].entangledPair = requester;
@@ -205,7 +224,7 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
205
224
}
206
225
207
226
// Represents quantum tunneling. Tokens are locked and then either successfully transferred or returned based on a probabilistic outcome.
208
- function quantumTunnelTransfer (
227
+ function initiateQuantumTunnel (
209
228
address to ,
210
229
uint256 amount
211
230
) external nonReentrant {
@@ -233,7 +252,7 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
233
252
// Represents the execution of a quantum tunneling event in the contract.
234
253
// A tunnel is initiated by a user, and this function determines whether the tunneling is successful or not.
235
254
// If users are entangled, the probability of success increases, mirroring the probabilistic nature of quantum mechanics.
236
- function executeTunnel () external nonReentrant {
255
+ function completeQuantumTunnel () external nonReentrant {
237
256
require (
238
257
tunnelTargetBlock[msg .sender ] > 0 ,
239
258
"No tunnel initiated by this user "
@@ -346,22 +365,67 @@ contract SuperconductorX is ERC20, ReentrancyGuard, Ownable {
346
365
347
366
// Users can mint tokens in exchange for ETH.
348
367
function communityMint () external payable nonReentrant {
349
- uint256 amountToMint = (msg .value / SCX_PRICE_IN_ETH) *
350
- 10 ** decimals ();
351
- require (amountToMint > 0 , "Not enough ETH sent " );
352
- require (
353
- balanceOf (address (this )) >= amountToMint,
354
- "The contract doesn't have enough SCX to be minted. Please try minting by sending a lower amount of ETH. "
368
+ require (currentTier < tiers.length , "All tiers are exhausted " );
369
+
370
+ Tier storage tier = tiers[currentTier];
371
+
372
+ uint256 maxTokensAvailable = Math.min (
373
+ balanceOf (address (this )),
374
+ tier.tokenCap - tier.tokensSold
355
375
);
376
+
377
+ uint256 amountToMint = (msg .value / tier.priceInETH) * 10 ** decimals ();
378
+ if (amountToMint > maxTokensAvailable) {
379
+ amountToMint = maxTokensAvailable;
380
+ }
381
+
356
382
require (
357
- soldSCXTokens + amountToMint <= 75000000 * 10 ** decimals () ,
358
- "Exceeds available SCX tokens for community minting "
383
+ amountToMint > 0 ,
384
+ "Not enough ETH sent or no tokens available for minting "
359
385
);
360
386
361
- soldSCXTokens += amountToMint;
387
+ uint256 ethRequired = (amountToMint * tier.priceInETH) /
388
+ 10 ** decimals ();
389
+ uint256 ethToRefund = msg .value - ethRequired;
390
+
391
+ tier.tokensSold += amountToMint;
362
392
_transfer (address (this ), msg .sender , amountToMint);
363
393
364
- emit CommunityMint (msg .sender , amountToMint, msg .value );
394
+ // Record the participant's purchase
395
+ if (tierParticipants[currentTier][msg .sender ] == 0 ) {
396
+ tierParticipantAddresses[currentTier].push (msg .sender );
397
+ }
398
+ tierParticipants[currentTier][msg .sender ] += amountToMint;
399
+
400
+ if (ethToRefund > 0 ) {
401
+ payable (msg .sender ).transfer (ethToRefund);
402
+ }
403
+
404
+ // Move to the next tier if the current tier is exhausted
405
+ if (tier.tokensSold == tier.tokenCap) {
406
+ currentTier++ ;
407
+ }
408
+
409
+ emit CommunityMint (msg .sender , amountToMint, ethRequired);
410
+ }
411
+
412
+ // Get the number of participants in a specific tier
413
+ function getTierParticipantCount (
414
+ uint256 tierIndex
415
+ ) external view returns (uint256 ) {
416
+ return tierParticipantAddresses[tierIndex].length ;
417
+ }
418
+
419
+ // Get the participant address and their purchase amount for a specific tier and index
420
+ function getTierParticipant (
421
+ uint256 tierIndex ,
422
+ uint256 participantIndex
423
+ ) external view returns (address , uint256 ) {
424
+ address participant = tierParticipantAddresses[tierIndex][
425
+ participantIndex
426
+ ];
427
+ uint256 amount = tierParticipants[tierIndex][participant];
428
+ return (participant, amount);
365
429
}
366
430
367
431
// Contract owner can withdraw all the SCX tokens.
0 commit comments