gn-contract 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.
@@ -0,0 +1,503 @@
1
+ //SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
6
+ import "./CROWD.sol";
7
+ import "./NFTFounder.sol";
8
+ import "./lib/NFTGetter.sol";
9
+ import "./lib/ValhallaPool.sol";
10
+ import "./lib/AccessControl.sol";
11
+ import "./lib/ValhallaBlackList.sol";
12
+
13
+ enum Rank {
14
+ NoRank,
15
+ Common,
16
+ Rare,
17
+ SuperRare,
18
+ Epic,
19
+ Legend,
20
+ SuperLegend
21
+ }
22
+
23
+ struct Account {
24
+ bool isRegistered;
25
+ bool isImported;
26
+ Rank rank;
27
+ address referrer;
28
+ uint downlineCount;
29
+ uint directDownlineCount;
30
+ uint rankUpdatedAt;
31
+ uint rankRewardClaimedAt;
32
+ }
33
+
34
+ struct RankDistribution {
35
+ uint common;
36
+ uint rare;
37
+ uint superRare;
38
+ uint epic;
39
+ uint legend;
40
+ uint superLegend;
41
+ }
42
+
43
+ contract Network is
44
+ ValhallaPool,
45
+ ValhallaBlackList,
46
+ Initializable,
47
+ AccessControl,
48
+ UUPSUpgradeable
49
+ {
50
+ mapping(address => Account) public accountMap;
51
+ mapping(address => uint) public rewardMap;
52
+ mapping(address => uint) public directCommonRankMap;
53
+ mapping(address => uint) public directRareRankMap;
54
+ mapping(address => uint) public directSuperRareRankMap;
55
+ mapping(address => uint) public directEpicRankMap;
56
+ mapping(address => uint) public directLegendRankMap;
57
+ mapping(address => uint) public directSuperLegendRankMap;
58
+ address public feeReceiverAddress;
59
+ address public feeReceiverAddress2;
60
+ address public reserveAddress;
61
+ bool public isRankRewardClaimable;
62
+ uint public rankRewardClaimableAt;
63
+ uint public deployedAtBlock;
64
+
65
+ // ipoPoolDistrbution + referrerPooDistribution = registrationFee
66
+ uint private ipoPoolDistribution;
67
+ uint private referrerPoolDistribution;
68
+
69
+ RankDistribution public rankDistribution;
70
+ NFTGetter public nftGetter;
71
+ CROWD public gnetERC20;
72
+ ERC20 public usdtERC20;
73
+ NFTFounder public nftFounder;
74
+
75
+ // events
76
+ event Registration(address indexed _from, address indexed referrer);
77
+ event ClaimReward(address indexed _from, uint value);
78
+ event ClaimRankReward(address indexed _from, uint value);
79
+ event Blacklisted(address indexed _target);
80
+ event RankUpgraded(address indexed _from, Rank rank);
81
+ event RankRewardOpened(uint indexed _timestamp);
82
+ event RankRewardClosed(uint indexed _timestamp);
83
+
84
+ /// @custom:oz-upgrades-unsafe-allow constructor
85
+ constructor() {
86
+ _disableInitializers();
87
+ }
88
+
89
+ function initialize(
90
+ address _admin,
91
+ address[] memory root_address,
92
+ address _feeReceiverAddress,
93
+ address _feeReceiverAddress2,
94
+ address _reserveAddress,
95
+ uint _ipoPoolDistribution,
96
+ uint _referrerPoolDistribution
97
+ ) public initializer {
98
+ __AccessControl_init();
99
+ __UUPSUpgradeable_init();
100
+
101
+ _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
102
+ _grantRole(UPGRADER_ROLE, msg.sender);
103
+ _grantRole(DEFAULT_ADMIN_ROLE, _admin);
104
+
105
+ deployedAtBlock = block.number;
106
+ ipoPoolDistribution = _ipoPoolDistribution;
107
+ referrerPoolDistribution = _referrerPoolDistribution;
108
+ feeReceiverAddress = _feeReceiverAddress;
109
+ feeReceiverAddress2 = _feeReceiverAddress2;
110
+ reserveAddress = _reserveAddress;
111
+
112
+ accountMap[_feeReceiverAddress2].isRegistered = true;
113
+ accountMap[_feeReceiverAddress2].referrer = address(0);
114
+
115
+ accountMap[_feeReceiverAddress].isRegistered = true;
116
+ accountMap[_feeReceiverAddress].referrer = address(0);
117
+ emit Registration(_feeReceiverAddress, address(0));
118
+
119
+ accountMap[_reserveAddress].isRegistered = true;
120
+ accountMap[_reserveAddress].referrer = address(0);
121
+ emit Registration(_feeReceiverAddress, address(0));
122
+
123
+ address _parent;
124
+ for (uint i = 0; i < root_address.length; i++) {
125
+ address _current = root_address[i];
126
+ accountMap[_current].isRegistered = true;
127
+ accountMap[_current].downlineCount = root_address.length - i - 1;
128
+ accountMap[_current].directDownlineCount = 1;
129
+ accountMap[_current].rank = Rank.NoRank;
130
+ accountMap[_current].referrer = _parent;
131
+ emit Registration(_current, _parent);
132
+ _parent = _current;
133
+ }
134
+ }
135
+
136
+ function _authorizeUpgrade(
137
+ address newImplementation
138
+ ) internal override onlyUpgrader {}
139
+
140
+ function _addDownlineAndAdjustRank(address _address) private {
141
+ Account storage _account = accountMap[_address];
142
+ _account.downlineCount += 1;
143
+ // if its already in max rank dont do anything
144
+ // for the sake of gas optimization
145
+ if (_account.rank == Rank.SuperLegend) return;
146
+
147
+ if (_account.downlineCount >= 64000 && _account.rank == Rank.Legend) {
148
+ uint totalEligibleDirectRank = directLegendRankMap[_address] +
149
+ directSuperLegendRankMap[_address];
150
+
151
+ if (totalEligibleDirectRank >= 2) {
152
+ _account.rank = Rank.SuperLegend;
153
+ rankDistribution.legend -= 1;
154
+ rankDistribution.superLegend += 1;
155
+ directLegendRankMap[_account.referrer] -= 1;
156
+ directSuperLegendRankMap[_account.referrer] += 1;
157
+ }
158
+ } else if (_account.downlineCount >= 16000 && _account.rank == Rank.Epic) {
159
+ uint totalEligibleDirectRank = directEpicRankMap[_address] +
160
+ directLegendRankMap[_address] +
161
+ directSuperLegendRankMap[_address];
162
+
163
+ if (totalEligibleDirectRank >= 2) {
164
+ _account.rank = Rank.Legend;
165
+ rankDistribution.epic -= 1;
166
+ rankDistribution.legend += 1;
167
+ directEpicRankMap[_account.referrer] -= 1;
168
+ directLegendRankMap[_account.referrer] += 1;
169
+ }
170
+ } else if (
171
+ _account.downlineCount >= 6400 && _account.rank == Rank.SuperRare
172
+ ) {
173
+ uint totalEligibleDirectRank = directSuperRareRankMap[_address] +
174
+ directEpicRankMap[_address] +
175
+ directLegendRankMap[_address] +
176
+ directSuperLegendRankMap[_address];
177
+
178
+ if (totalEligibleDirectRank >= 2) {
179
+ _account.rank = Rank.Epic;
180
+ rankDistribution.superRare -= 1;
181
+ rankDistribution.epic += 1;
182
+ directSuperRareRankMap[_account.referrer] -= 1;
183
+ directEpicRankMap[_account.referrer] += 1;
184
+ }
185
+ } else if (_account.downlineCount >= 1600 && _account.rank == Rank.Rare) {
186
+ uint totalEligibleDirectRank = directRareRankMap[_address] +
187
+ directSuperRareRankMap[_address] +
188
+ directEpicRankMap[_address] +
189
+ directLegendRankMap[_address] +
190
+ directSuperLegendRankMap[_address];
191
+ if (totalEligibleDirectRank >= 2) {
192
+ _account.rank = Rank.SuperRare;
193
+ rankDistribution.rare -= 1;
194
+ rankDistribution.superRare += 1;
195
+ directRareRankMap[_account.referrer] -= 1;
196
+ directSuperRareRankMap[_account.referrer] += 1;
197
+ }
198
+ } else if (_account.downlineCount >= 400 && _account.rank == Rank.Common) {
199
+ uint totalEligibleDirectRank = directCommonRankMap[_address] +
200
+ directRareRankMap[_address] +
201
+ directSuperRareRankMap[_address] +
202
+ directEpicRankMap[_address] +
203
+ directLegendRankMap[_address] +
204
+ directSuperLegendRankMap[_address];
205
+ if (totalEligibleDirectRank >= 2) {
206
+ _account.rank = Rank.Rare;
207
+ rankDistribution.common -= 1;
208
+ rankDistribution.rare += 1;
209
+ directCommonRankMap[_account.referrer] -= 1;
210
+ directRareRankMap[_account.referrer] += 1;
211
+ }
212
+ } else if (_account.downlineCount >= 100 && _account.rank == Rank.NoRank) {
213
+ _account.rank = Rank.Common;
214
+ rankDistribution.common += 1;
215
+ directCommonRankMap[_account.referrer] += 1;
216
+ } else {
217
+ return;
218
+ }
219
+
220
+ emit RankUpgraded(_address, _account.rank);
221
+ }
222
+
223
+ function _distributeRegistrationFeeToNthReferrer(
224
+ uint value
225
+ ) private returns (uint) {
226
+ uint _reference = value;
227
+ uint _valueLeft = value;
228
+
229
+ Account storage currentAccount = accountMap[msg.sender];
230
+
231
+ // rules of how registration fee going to be distributed
232
+ // into up to 15 upline in percentage
233
+ // root 1 - 2 = 10%, 3 = 6%, 4 = 5%, etc.
234
+ uint8[15] memory uplineRegistrationFeeDistributionPercentage = [
235
+ 30,
236
+ 8,
237
+ 3,
238
+ 2,
239
+ 2,
240
+ 1,
241
+ 1,
242
+ 1,
243
+ 1,
244
+ 1,
245
+ 1,
246
+ 1,
247
+ 1,
248
+ 1,
249
+ 1
250
+ ];
251
+ for (
252
+ uint i = 0;
253
+ i < uplineRegistrationFeeDistributionPercentage.length;
254
+ i++
255
+ ) {
256
+ address _parentAddress = currentAccount.referrer;
257
+
258
+ // exit loop once it encounter zero address
259
+ // because it's expected to be no other upline can be processed
260
+ if (_parentAddress == address(0)) break;
261
+
262
+ // ignore blacklisted upline
263
+ if (blacklistedAddressMap[_parentAddress] == false) {
264
+ _addDownlineAndAdjustRank(_parentAddress);
265
+ uint _percentage = uplineRegistrationFeeDistributionPercentage[i];
266
+ uint _distribution_value = (_reference * _percentage) / 100;
267
+ rewardMap[_parentAddress] += _distribution_value;
268
+ _valueLeft -= _distribution_value;
269
+ }
270
+
271
+ currentAccount = accountMap[_parentAddress];
272
+ }
273
+ return _valueLeft;
274
+ }
275
+
276
+ function wdUSDT(uint amount) public onlyAdmin {
277
+ require(
278
+ amount <= usdtERC20.balanceOf(address(this)),
279
+ "Insufficient CUSD balance"
280
+ );
281
+ usdtERC20.transfer(msg.sender, amount);
282
+ }
283
+
284
+ function setNFTFounderAddress(NFTFounder _nftFounder) public onlyAdmin {
285
+ nftFounder = _nftFounder;
286
+ }
287
+
288
+ function setNftAddress(NFTGetter _nftGetter) public onlyAdmin {
289
+ nftGetter = _nftGetter;
290
+ }
291
+
292
+ function setCRWDAddress(CROWD _gnetERC20) public onlyAdmin {
293
+ gnetERC20 = _gnetERC20;
294
+ }
295
+
296
+ function setCUSDAddress(ERC20 _usdtERC20) public onlyAdmin {
297
+ usdtERC20 = _usdtERC20;
298
+ }
299
+
300
+ function getRegistrationFee() public view returns (uint) {
301
+ return ipoPoolDistribution + referrerPoolDistribution;
302
+ }
303
+
304
+ function register(address referrer) public notInBlacklist {
305
+ uint registrationFee = getRegistrationFee();
306
+ Account storage account = accountMap[msg.sender];
307
+ uint balance = usdtERC20.balanceOf(msg.sender);
308
+ require(address(usdtERC20) != address(0), "admin didn't set token ERC");
309
+ require(balance >= registrationFee, "Unmatch Registration Fee");
310
+ require(account.isRegistered == false, "Address already registered");
311
+ require(referrer != address(0), "Invalid referrer");
312
+ require(accountMap[referrer].isRegistered, "Referrer should be registered");
313
+ require(blacklistedAddressMap[referrer] == false, "Referrer blacklisted");
314
+ require(!isRankRewardClaimable, "Registration closed");
315
+
316
+ account.referrer = referrer;
317
+ account.isRegistered = true;
318
+ account.rank = Rank.NoRank;
319
+ account.directDownlineCount = 0;
320
+ accountMap[referrer].directDownlineCount += 1;
321
+
322
+ _storeIpoPool(ipoPoolDistribution);
323
+ uint valueLeft = _distributeRegistrationFeeToNthReferrer(
324
+ referrerPoolDistribution
325
+ );
326
+ uint globalPoolDistribution = (referrerPoolDistribution * 17) / 100;
327
+ _storeGlobalPool(globalPoolDistribution);
328
+ valueLeft -= globalPoolDistribution;
329
+ uint reserveDistribution = (referrerPoolDistribution * 3) / 100;
330
+ // need approval
331
+ usdtERC20.transferFrom(msg.sender, address(this), registrationFee);
332
+
333
+ usdtERC20.transfer(address(nftFounder), reserveDistribution);
334
+ nftFounder.distributeFounderRewards(reserveDistribution);
335
+
336
+ valueLeft -= reserveDistribution;
337
+
338
+ usdtERC20.transfer(feeReceiverAddress, valueLeft / 2);
339
+ usdtERC20.transfer(feeReceiverAddress2, valueLeft / 2);
340
+ emit Registration(msg.sender, referrer);
341
+ }
342
+
343
+ function importAccount(address _address, address _referrer) public onlyAdmin {
344
+ Account storage account = accountMap[_address];
345
+ require(account.isRegistered == false, "Address already registered");
346
+ require(_referrer != address(0), "Invalid referrer");
347
+ require(
348
+ accountMap[_referrer].isRegistered,
349
+ "Referrer should be registered"
350
+ );
351
+ require(blacklistedAddressMap[_referrer] == false, "Referrer blacklisted");
352
+ require(!isRankRewardClaimable, "Registration closed");
353
+
354
+ account.referrer = _referrer;
355
+ account.isRegistered = true;
356
+ account.rank = Rank.NoRank;
357
+ account.directDownlineCount = 0;
358
+ account.isImported = true;
359
+ accountMap[_referrer].directDownlineCount += 1;
360
+
361
+ address _currentParent = _referrer;
362
+ for (uint i = 0; i < 15; i++) {
363
+ _addDownlineAndAdjustRank(_currentParent);
364
+ _currentParent = accountMap[_currentParent].referrer;
365
+ }
366
+ emit Registration(_address, _referrer);
367
+ }
368
+
369
+ function claimReward() public notInBlacklist {
370
+ uint _reward = rewardMap[msg.sender];
371
+ require(_reward > 0, "No reward to be claimed");
372
+ // apply 10% tax
373
+ uint tax = (_reward * 10) / 100;
374
+ // claim reward
375
+
376
+ uint halfTax = tax / 2;
377
+ usdtERC20.transfer(feeReceiverAddress, halfTax);
378
+ usdtERC20.transfer(feeReceiverAddress2, halfTax);
379
+ usdtERC20.transfer(msg.sender, _reward - tax);
380
+ rewardMap[msg.sender] = 0;
381
+ emit ClaimReward(msg.sender, _reward - tax);
382
+ }
383
+
384
+ function getMyRankReward(address _address) public view returns (uint) {
385
+ Account memory account = accountMap[_address];
386
+ PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
387
+ if (globalPool.valueLeft == 0) return 0;
388
+ if (isRankRewardClaimable == false) return 0;
389
+ if (account.rankRewardClaimedAt >= rankRewardClaimableAt) return 0;
390
+ if (account.rank == Rank.NoRank) return 0;
391
+ uint distribution = 0;
392
+ uint base = 0;
393
+ if (account.rank == Rank.Common) {
394
+ distribution = rankDistribution.common;
395
+ base = (globalPool.valueLeft * 3) / 100;
396
+ }
397
+ if (account.rank == Rank.Rare) {
398
+ distribution = rankDistribution.rare;
399
+ base = (globalPool.valueLeft * 7) / 100;
400
+ }
401
+ if (account.rank == Rank.SuperRare) {
402
+ distribution = rankDistribution.superRare;
403
+ base = (globalPool.valueLeft * 12) / 100;
404
+ }
405
+ if (account.rank == Rank.Epic) {
406
+ distribution = rankDistribution.epic;
407
+ base = (globalPool.valueLeft * 18) / 100;
408
+ }
409
+ if (account.rank == Rank.Legend) {
410
+ distribution = rankDistribution.legend;
411
+ base = (globalPool.valueLeft * 26) / 100;
412
+ }
413
+ if (account.rank == Rank.SuperLegend) {
414
+ distribution = rankDistribution.superLegend;
415
+ base = (globalPool.valueLeft * 34) / 100;
416
+ }
417
+
418
+ return base / distribution;
419
+ }
420
+
421
+ function claimRankReward() public notInBlacklist {
422
+ uint myReward = getMyRankReward(msg.sender);
423
+ uint nftValue = nftGetter.totalValueMap(msg.sender);
424
+ Account storage account = accountMap[msg.sender];
425
+
426
+ require(myReward > 0, "No Reward can be claimed");
427
+ if (account.rank == Rank.Common) {
428
+ require(nftValue >= 50_000 * 10 ** gnetERC20.decimals(), "Not Eligible");
429
+ }
430
+ if (account.rank == Rank.Rare) {
431
+ require(nftValue >= 200_000 * 10 ** gnetERC20.decimals(), "Not Eligible");
432
+ }
433
+ if (account.rank == Rank.SuperRare) {
434
+ require(
435
+ nftValue >= 1000_000 * 10 ** gnetERC20.decimals(),
436
+ "Not Eligible"
437
+ );
438
+ }
439
+ if (account.rank == Rank.Epic) {
440
+ require(
441
+ nftValue >= 5_000_000 * 10 ** gnetERC20.decimals(),
442
+ "Not Eligible"
443
+ );
444
+ }
445
+ if (account.rank == Rank.Legend) {
446
+ require(
447
+ nftValue >= 25_000_000 * 10 ** gnetERC20.decimals(),
448
+ "Not Eligible"
449
+ );
450
+ }
451
+ if (account.rank == Rank.SuperLegend) {
452
+ require(
453
+ nftValue >= 100_000_000 * 10 ** gnetERC20.decimals(),
454
+ "Not Eligible"
455
+ );
456
+ }
457
+
458
+ uint tax = (myReward * 10) / 100;
459
+ uint halfTax = tax / 2;
460
+ // claim rank reward
461
+ usdtERC20.transfer(feeReceiverAddress, halfTax);
462
+ usdtERC20.transfer(feeReceiverAddress2, halfTax);
463
+ usdtERC20.transfer(msg.sender, myReward - tax);
464
+ account.rankRewardClaimedAt = block.timestamp;
465
+ PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
466
+ globalPool.valueLeft -= myReward;
467
+ emit ClaimRankReward(msg.sender, myReward);
468
+ }
469
+
470
+ function startClaimingRankReward() public onlyStaff {
471
+ require(isRankRewardClaimable == false, "Already started");
472
+ isRankRewardClaimable = true;
473
+ rankRewardClaimableAt = block.timestamp;
474
+
475
+ PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
476
+ globalPool.valueLeft = globalPool.claimable;
477
+ globalPool.claimable = globalPool.claimable - globalPool.valueLeft;
478
+ nftGetter.startClaimingRankReward();
479
+ emit RankRewardOpened(block.timestamp);
480
+ }
481
+
482
+ function stopClaimingRankReward() public onlyStaff {
483
+ require(isRankRewardClaimable, "Rank reward not started");
484
+ isRankRewardClaimable = false;
485
+ PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
486
+ globalPool.claimable += globalPool.valueLeft;
487
+ globalPool.valueLeft = 0;
488
+ nftGetter.stopClaimingRankReward();
489
+ emit RankRewardClosed(block.timestamp);
490
+ }
491
+
492
+ function blackListAddress(address addr) public onlyAdmin {
493
+ require(addr != msg.sender, "You cannot blacklist yourself");
494
+ require(addr != address(0), "You cannot blacklist address zero");
495
+ addToBlacklistMap(addr);
496
+ emit Blacklisted(addr);
497
+ }
498
+
499
+ function changeFeeRegister(uint _ipoPol, uint _referalPol) public onlyAdmin {
500
+ ipoPoolDistribution = _ipoPol;
501
+ referrerPoolDistribution = _referalPol;
502
+ }
503
+ }
@@ -0,0 +1,86 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.9;
3
+
4
+ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
5
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
6
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
7
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
8
+
9
+ contract Swap is Initializable, OwnableUpgradeable, UUPSUpgradeable {
10
+ /// @custom:oz-upgrades-unsafe-allow constructor
11
+ constructor() {
12
+ _disableInitializers();
13
+ }
14
+
15
+ event SwapToken(
16
+ ERC20 _from,
17
+ ERC20 _to,
18
+ uint _quantity,
19
+ address _user,
20
+ uint _timeStamp
21
+ );
22
+
23
+ ERC20 public usdt;
24
+ ERC20 public cusdt;
25
+ ERC20 public crowd;
26
+ address public feeReceiver;
27
+ address public feeMarketing;
28
+
29
+ function initialize(
30
+ ERC20 _usdt,
31
+ ERC20 _cusdt,
32
+ ERC20 _crowd,
33
+ address _feeReceiver,
34
+ address _feeMarketing
35
+ ) public initializer {
36
+ __Ownable_init();
37
+ __UUPSUpgradeable_init();
38
+ usdt = _usdt;
39
+ cusdt = _cusdt;
40
+ crowd = _crowd;
41
+ feeReceiver = _feeReceiver;
42
+ feeMarketing = _feeMarketing;
43
+ }
44
+
45
+ function swapToCUSDT(uint _amount) public {
46
+ // USDT has 18 decimals. CUSDT has 18 decimals.
47
+ // 1:1 ratio.
48
+ uint cusdtAmount = _amount;
49
+ require(cusdt.balanceOf(address(this)) >= cusdtAmount, "Insufficient Pool");
50
+
51
+ usdt.transferFrom(msg.sender, address(this), _amount);
52
+ cusdt.transfer(msg.sender, cusdtAmount);
53
+ emit SwapToken(usdt, cusdt, _amount, msg.sender, block.timestamp);
54
+ }
55
+
56
+ function swapToCROWD(uint _amount) public {
57
+ // 1 CROWD = 0.002 USDT -> 1 USDT = 500 CROWD.
58
+ // USDT (18 dec) -> CROWD (18 dec).
59
+ // Multiplier = 500.
60
+ uint crowdAmount = _amount * 500;
61
+ require(crowd.balanceOf(address(this)) >= crowdAmount, "Insufficient Pool");
62
+
63
+ usdt.transferFrom(msg.sender, address(this), _amount);
64
+ crowd.transfer(msg.sender, crowdAmount);
65
+ emit SwapToken(usdt, crowd, _amount, msg.sender, block.timestamp);
66
+ }
67
+
68
+ function withdrawCUSDT(uint _amount) public onlyOwner {
69
+ require(cusdt.balanceOf(address(this)) >= _amount, "Insufficient Pool");
70
+ cusdt.transfer(msg.sender, _amount);
71
+ }
72
+
73
+ function withdrawCROWD(uint _amount) public onlyOwner {
74
+ require(crowd.balanceOf(address(this)) >= _amount, "Insufficient Pool");
75
+ crowd.transfer(msg.sender, _amount);
76
+ }
77
+
78
+ function withdrawUSDT(uint _amount) public onlyOwner {
79
+ require(usdt.balanceOf(address(this)) >= _amount, "Insufficient Pool");
80
+ usdt.transfer(msg.sender, _amount);
81
+ }
82
+
83
+ function _authorizeUpgrade(
84
+ address newImplementation
85
+ ) internal override onlyOwner {}
86
+ }
@@ -0,0 +1,32 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5
+ import "@openzeppelin/contracts/access/Ownable.sol";
6
+ import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
7
+
8
+ contract USDT is ERC20, ERC20Burnable, Ownable {
9
+ address public minterContract;
10
+
11
+ // this is not real name, please check the contract first before deploying !
12
+ constructor() ERC20("United State Dolar", "USDT") {
13
+ _mint(msg.sender, 1_000_000_000 * 10 ** 18);
14
+ }
15
+
16
+ function decimals() public pure override returns (uint8) {
17
+ return 18;
18
+ }
19
+
20
+ function setMinterContract(address _minterContract) public onlyOwner {
21
+ require(
22
+ _minterContract != address(minterContract),
23
+ "minter contract already set"
24
+ );
25
+ minterContract = _minterContract;
26
+ }
27
+
28
+ function mintForFarm(uint amount, address target) external {
29
+ require(msg.sender == minterContract, "Unauthorized minter");
30
+ _mint(target, amount);
31
+ }
32
+ }
@@ -0,0 +1,35 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.17;
3
+
4
+ import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
5
+
6
+ abstract contract AccessControl is AccessControlUpgradeable {
7
+ // role definition
8
+ bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");
9
+ bytes32 public constant STAFF_ROLE = keccak256("STAFF_ROLE");
10
+
11
+ modifier onlyAdmin() {
12
+ require(
13
+ hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
14
+ "Only Admin can perform action"
15
+ );
16
+ _;
17
+ }
18
+
19
+ modifier onlyUpgrader() {
20
+ require(
21
+ hasRole(UPGRADER_ROLE, msg.sender),
22
+ "Only UPGRADER can perform action"
23
+ );
24
+ _;
25
+ }
26
+
27
+ modifier onlyStaff() {
28
+ require(
29
+ hasRole(DEFAULT_ADMIN_ROLE, msg.sender) ||
30
+ hasRole(STAFF_ROLE, msg.sender),
31
+ "Only Admin can perform action"
32
+ );
33
+ _;
34
+ }
35
+ }