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.
- package/.openzeppelin/bsc-testnet.json +1847 -0
- package/.prettierrc +15 -0
- package/README.md +14 -0
- package/constants/getter.ts +4 -0
- package/constants/rootAddress.ts +22 -0
- package/contracts/CROWD.sol +32 -0
- package/contracts/CUSDT.sol +32 -0
- package/contracts/NFT.sol +499 -0
- package/contracts/NFTFounder.sol +254 -0
- package/contracts/NFTGenesis.sol +337 -0
- package/contracts/Network.sol +503 -0
- package/contracts/Swap.sol +86 -0
- package/contracts/USDT.sol +32 -0
- package/contracts/lib/AccessControl.sol +35 -0
- package/contracts/lib/NFTGetter.sol +60 -0
- package/contracts/lib/NFTHelpers.sol +111 -0
- package/contracts/lib/ValhallaBlackList.sol +18 -0
- package/contracts/lib/ValhallaPool.sol +44 -0
- package/hardhat.config.ts +44 -0
- package/package.json +50 -0
- package/scripts/DeployNetwork.ts +123 -0
- package/scripts/DeploySwap.ts +57 -0
- package/scripts/DeployUSDT.ts +16 -0
- package/test/Swap.test.ts +182 -0
- package/test/lib/initializer.ts +193 -0
- package/test/nft_genesis.test.ts +399 -0
- package/test/nft_purchase.test.ts +210 -0
- package/test/rank_distribution.test.ts +142 -0
- package/test/registration.test.ts +267 -0
- package/test/registration_reward.test.ts +114 -0
- package/tsconfig.json +11 -0
package/.prettierrc
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Sample Hardhat Project
|
|
2
|
+
|
|
3
|
+
This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a Hardhat Ignition module that deploys that contract.
|
|
4
|
+
|
|
5
|
+
Try running some of the following tasks:
|
|
6
|
+
|
|
7
|
+
```shell
|
|
8
|
+
npx hardhat help
|
|
9
|
+
npx hardhat test
|
|
10
|
+
REPORT_GAS=true npx hardhat test
|
|
11
|
+
npx hardhat node
|
|
12
|
+
npx hardhat ignition deploy ./ignition/modules/Lock.ts
|
|
13
|
+
```
|
|
14
|
+
# gn-contract
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const rootAdressList = [
|
|
2
|
+
"0xbbf56FB6878F4f6665507495B059901a5124FDdE",
|
|
3
|
+
"0xa9968A081e9119ECb17e65b5B00504A770E7554D",
|
|
4
|
+
"0x4Ab1539b21B7d9aBB5a535467deD7bf155A30223",
|
|
5
|
+
"0xaF8014763e6c8919767125D235730b459FDbA364",
|
|
6
|
+
"0xfC6b100A7B23E2cB7952D8f5Ece1A36727532c4a",
|
|
7
|
+
"0xde668F1cd8C4F38127C4B43a9A711e6615a2A080",
|
|
8
|
+
"0xd9682cf0870cFaDc307baEDFD8A0d1F92Db1e187",
|
|
9
|
+
"0x0387376b07D3Ae19E56bfB4992208360c4F604f0",
|
|
10
|
+
"0xA6BcA768eDCEC76565918E93d257e981c14064c6",
|
|
11
|
+
"0xD554c09Ea646001A72B59f154D831258878e3ee9",
|
|
12
|
+
"0xc0A2C50E560eA064aA9d863A8A1005D553b23a67",
|
|
13
|
+
"0x9c963c63e5f8669fa07e85a8711e36C0D49544a2",
|
|
14
|
+
"0xB8f8C74C740fD806cA267EE2B8bB733AC36642E7",
|
|
15
|
+
"0x9ADeB9088d0D091f7C5dbf0bc9864ccd0aD9A2d4",
|
|
16
|
+
"0x65CA460b1398d1d335edA4186fa2213fBfe6B815",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export const feeReceiverAddress = "0xFdA829C6E8825437365E666cBE3A07311c7B4337";
|
|
20
|
+
export const feeReceiverAddress2 = "0x456af512778C41cDf342b0778C49A3578C0A6C7E";
|
|
21
|
+
export const reserveAddress = "0xa1BA34674C0920d3113f2DDBDe6b7e586403c88B";
|
|
22
|
+
export const genesisPayment = "0x883EbD6056653712EFebd2787489fCdd9e63AfC4";
|
|
@@ -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 CROWD 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("Crowd Strike", "CROWD") {
|
|
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,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 CUSDT 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("Crowd United State Dollar", "CUSDT") {
|
|
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,499 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.17;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
|
|
5
|
+
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
|
|
6
|
+
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol";
|
|
7
|
+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
8
|
+
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
|
|
9
|
+
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
|
|
10
|
+
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
11
|
+
import "./CROWD.sol";
|
|
12
|
+
import "./Network.sol";
|
|
13
|
+
import "./lib/ValhallaPool.sol";
|
|
14
|
+
import "./lib/NFTHelpers.sol";
|
|
15
|
+
import "./NFTGenesis.sol";
|
|
16
|
+
|
|
17
|
+
contract NFT is
|
|
18
|
+
ValhallaPool,
|
|
19
|
+
Initializable,
|
|
20
|
+
OwnableUpgradeable,
|
|
21
|
+
ERC721Upgradeable,
|
|
22
|
+
ERC721EnumerableUpgradeable,
|
|
23
|
+
UUPSUpgradeable
|
|
24
|
+
{
|
|
25
|
+
using CountersUpgradeable for CountersUpgradeable.Counter;
|
|
26
|
+
using StringsUpgradeable for uint256;
|
|
27
|
+
using NFTHelpers for *;
|
|
28
|
+
|
|
29
|
+
uint256 private randNonce;
|
|
30
|
+
|
|
31
|
+
mapping(uint => OwnedToken) public ownedTokenMap;
|
|
32
|
+
mapping(uint => Card) public cardMap;
|
|
33
|
+
mapping(address => uint) public totalValueMap;
|
|
34
|
+
mapping(address => uint) public rewardMap;
|
|
35
|
+
mapping(address => uint) public referralRewardMap;
|
|
36
|
+
mapping(address => uint) public farmMatchingRewardMap;
|
|
37
|
+
mapping(address => uint) public rankRewardClaimedAtMap;
|
|
38
|
+
CROWD public gnetERC20;
|
|
39
|
+
Network public valhalla;
|
|
40
|
+
|
|
41
|
+
CountersUpgradeable.Counter private _tokenIdCounter;
|
|
42
|
+
CountersUpgradeable.Counter private _cardIdCounter;
|
|
43
|
+
|
|
44
|
+
NFTGenesis public nftGenesis;
|
|
45
|
+
|
|
46
|
+
// events
|
|
47
|
+
event Buy(address indexed _from, uint indexed _tokenId);
|
|
48
|
+
event Farm(uint indexed _tokenId, uint _value);
|
|
49
|
+
event ClaimReward(address indexed _from, uint value);
|
|
50
|
+
event ClaimRankReward(address indexed _from, uint value);
|
|
51
|
+
event DirectReferralReward(
|
|
52
|
+
address indexed referrer,
|
|
53
|
+
address indexed buyer,
|
|
54
|
+
uint value
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
58
|
+
constructor() {
|
|
59
|
+
_disableInitializers();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function initialize(CROWD _gnetERC20, Network _valhalla) public initializer {
|
|
63
|
+
// this is not a real name, please check this contract before deploy
|
|
64
|
+
__Ownable_init();
|
|
65
|
+
__ERC721_init("CrowdStrikeNFT", "CROWDNFT");
|
|
66
|
+
__ERC721Enumerable_init();
|
|
67
|
+
__UUPSUpgradeable_init();
|
|
68
|
+
|
|
69
|
+
gnetERC20 = _gnetERC20;
|
|
70
|
+
valhalla = _valhalla;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* initiate 6 card on deployment
|
|
74
|
+
*/
|
|
75
|
+
uint[6] memory initialCardPriceList = [
|
|
76
|
+
uint(5000),
|
|
77
|
+
uint(25000),
|
|
78
|
+
uint(100000),
|
|
79
|
+
uint(500000),
|
|
80
|
+
uint(2500000),
|
|
81
|
+
uint(10000000)
|
|
82
|
+
];
|
|
83
|
+
for (uint i = 0; i < initialCardPriceList.length; i++) {
|
|
84
|
+
uint _cardId = _cardIdCounter.current();
|
|
85
|
+
Card storage _card = cardMap[_cardId];
|
|
86
|
+
_card.price = initialCardPriceList[_cardId] * 10 ** gnetERC20.decimals();
|
|
87
|
+
_card.halfingPercentage = 100;
|
|
88
|
+
_card.isMintable = true;
|
|
89
|
+
_cardIdCounter.increment();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function _authorizeUpgrade(
|
|
94
|
+
address newImplementation
|
|
95
|
+
) internal override onlyOwner {}
|
|
96
|
+
|
|
97
|
+
// The following functions are overrides required by Solidity.
|
|
98
|
+
|
|
99
|
+
function _beforeTokenTransfer(
|
|
100
|
+
address from,
|
|
101
|
+
address to,
|
|
102
|
+
uint256 tokenId,
|
|
103
|
+
uint256 batchSize
|
|
104
|
+
) internal override(ERC721Upgradeable, ERC721EnumerableUpgradeable) {
|
|
105
|
+
super._beforeTokenTransfer(from, to, tokenId, batchSize);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function supportsInterface(
|
|
109
|
+
bytes4 interfaceId
|
|
110
|
+
)
|
|
111
|
+
public
|
|
112
|
+
view
|
|
113
|
+
override(ERC721Upgradeable, ERC721EnumerableUpgradeable)
|
|
114
|
+
returns (bool)
|
|
115
|
+
{
|
|
116
|
+
return super.supportsInterface(interfaceId);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function _random(uint256 modulus) private returns (uint256) {
|
|
120
|
+
randNonce++;
|
|
121
|
+
return
|
|
122
|
+
uint256(
|
|
123
|
+
keccak256(abi.encodePacked(block.timestamp, msg.sender, randNonce))
|
|
124
|
+
) % modulus;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function tokenURI(
|
|
128
|
+
uint256 tokenId
|
|
129
|
+
) public view override returns (string memory) {
|
|
130
|
+
_requireMinted(tokenId);
|
|
131
|
+
|
|
132
|
+
string memory baseURI = _baseURI();
|
|
133
|
+
OwnedToken memory ownedToken = ownedTokenMap[tokenId];
|
|
134
|
+
uint cardId = ownedToken.cardId;
|
|
135
|
+
return
|
|
136
|
+
bytes(baseURI).length > 0
|
|
137
|
+
? string(abi.encodePacked(baseURI, cardId.toString()))
|
|
138
|
+
: "";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function _baseURI() internal pure override returns (string memory) {
|
|
142
|
+
return "https://crowdstrike.club/api/image/";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* calculate the probability of farm percentage
|
|
147
|
+
*/
|
|
148
|
+
function _getRandomFarmPercentage() private returns (uint256) {
|
|
149
|
+
uint256 rand = _random(1000);
|
|
150
|
+
return NFTHelpers.getRandomFarmPercentage(rand);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* calculate reward per seconds base on its own percentage
|
|
155
|
+
*/
|
|
156
|
+
function getFarmValue(uint tokenId) public view returns (uint256) {
|
|
157
|
+
OwnedToken storage _tokenMetadata = ownedTokenMap[tokenId];
|
|
158
|
+
Card memory card = cardMap[_tokenMetadata.cardId];
|
|
159
|
+
return
|
|
160
|
+
NFTHelpers.calculateFarmValue(
|
|
161
|
+
_tokenMetadata.mintedAt,
|
|
162
|
+
_tokenMetadata.lastFarmedAt,
|
|
163
|
+
_tokenMetadata.percentage,
|
|
164
|
+
_tokenMetadata.mintingPrice,
|
|
165
|
+
card.halfingPercentage
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function buy(uint cardId) public notInBlacklist {
|
|
170
|
+
bool is_registered;
|
|
171
|
+
Rank rank;
|
|
172
|
+
address directReferrer;
|
|
173
|
+
(is_registered, , rank, directReferrer, , , , ) = valhalla.accountMap(
|
|
174
|
+
msg.sender
|
|
175
|
+
);
|
|
176
|
+
address feeReceiver = valhalla.feeReceiverAddress();
|
|
177
|
+
address feeReceiver2 = valhalla.feeReceiverAddress2();
|
|
178
|
+
bool isRankRewardClaimable = valhalla.isRankRewardClaimable();
|
|
179
|
+
Card storage _card = cardMap[cardId];
|
|
180
|
+
|
|
181
|
+
require(isRankRewardClaimable == false, "Market closed");
|
|
182
|
+
require(is_registered, "Registration required");
|
|
183
|
+
require(_card.price > 0, "Invalid card");
|
|
184
|
+
require(_card.isMintable, "Card is not mintable");
|
|
185
|
+
|
|
186
|
+
uint32[7] memory maxBuy = [
|
|
187
|
+
100_000,
|
|
188
|
+
200_000,
|
|
189
|
+
1000_000,
|
|
190
|
+
5_000_000,
|
|
191
|
+
20_000_000,
|
|
192
|
+
100_000_000,
|
|
193
|
+
500_000_000
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
for (uint i = 0; i < 7; i++) {
|
|
197
|
+
if (uint(rank) == i) {
|
|
198
|
+
require(
|
|
199
|
+
_card.price + totalValueMap[msg.sender] <=
|
|
200
|
+
maxBuy[i] * 10 ** gnetERC20.decimals(),
|
|
201
|
+
"Max Buy Error"
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
uint distributeGenesis = (_card.price * 5) / 100;
|
|
207
|
+
gnetERC20.transferFrom(
|
|
208
|
+
msg.sender,
|
|
209
|
+
address(this),
|
|
210
|
+
_card.price - distributeGenesis
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
_storeGlobalPool((_card.price * 17) / 100);
|
|
214
|
+
genesisPoolResolver(distributeGenesis);
|
|
215
|
+
uint tax = (_card.price * 20) / 100;
|
|
216
|
+
uint halfTax = tax / 2;
|
|
217
|
+
// rewardMap[feeReceiver] += halfTax;
|
|
218
|
+
// rewardMap[feeReceiver2] += halfTax;
|
|
219
|
+
gnetERC20.transfer(feeReceiver, halfTax);
|
|
220
|
+
gnetERC20.transfer(feeReceiver2, halfTax);
|
|
221
|
+
gnetERC20.burn((_card.price * 50) / 100);
|
|
222
|
+
|
|
223
|
+
if (directReferrer != address(0)) {
|
|
224
|
+
uint referralReward = (_card.price * 8) / 100;
|
|
225
|
+
rewardMap[directReferrer] += referralReward;
|
|
226
|
+
referralRewardMap[directReferrer] += referralReward;
|
|
227
|
+
emit DirectReferralReward(directReferrer, msg.sender, referralReward);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
uint256 tokenId = _tokenIdCounter.current();
|
|
231
|
+
OwnedToken storage _purchasedToken = ownedTokenMap[tokenId];
|
|
232
|
+
_purchasedToken.cardId = cardId;
|
|
233
|
+
_purchasedToken.mintingPrice = _card.price;
|
|
234
|
+
_purchasedToken.mintedAt = block.timestamp;
|
|
235
|
+
_purchasedToken.lastFarmedAt = block.timestamp;
|
|
236
|
+
_purchasedToken.percentage = _getRandomFarmPercentage();
|
|
237
|
+
|
|
238
|
+
_tokenIdCounter.increment();
|
|
239
|
+
_safeMint(msg.sender, tokenId);
|
|
240
|
+
emit Buy(msg.sender, tokenId);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function withdrawAllGenesisPool() public onlyOwner {
|
|
244
|
+
PoolType storage genesisPool = poolMap[GENESIS_POOL_KEY];
|
|
245
|
+
gnetERC20.transfer(msg.sender, genesisPool.claimable);
|
|
246
|
+
genesisPool.claimable = 0;
|
|
247
|
+
genesisPool.valueLeft = 0;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function _getReferrerFarmMatchingPercentage(
|
|
251
|
+
uint level,
|
|
252
|
+
address referrer
|
|
253
|
+
) private view returns (uint) {
|
|
254
|
+
Rank rank;
|
|
255
|
+
(, , rank, , , , , ) = valhalla.accountMap(referrer);
|
|
256
|
+
|
|
257
|
+
return
|
|
258
|
+
NFTHelpers.getReferrerMatchingPercentage(
|
|
259
|
+
level,
|
|
260
|
+
uint8(rank),
|
|
261
|
+
totalValueMap[referrer],
|
|
262
|
+
gnetERC20.decimals()
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function setNFTGenesis(NFTGenesis _nftGenesis) public onlyOwner {
|
|
267
|
+
nftGenesis = _nftGenesis;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function genesisPoolResolver(uint _genesisValue) private {
|
|
271
|
+
uint storedGenesisValue = 0;
|
|
272
|
+
uint amountNftTypes = nftGenesis.amountNftTypes();
|
|
273
|
+
address receiver = nftGenesis.receiverAddress();
|
|
274
|
+
|
|
275
|
+
for (uint256 i = 0; i < amountNftTypes; i++) {
|
|
276
|
+
(, uint genesisPercentage, uint totalMinted, uint maxMinted) = nftGenesis
|
|
277
|
+
.cardMap(i);
|
|
278
|
+
uint valueDistributed = ((_genesisValue * genesisPercentage) /
|
|
279
|
+
100 /
|
|
280
|
+
maxMinted) * totalMinted;
|
|
281
|
+
storedGenesisValue += valueDistributed;
|
|
282
|
+
if (valueDistributed == 0) continue;
|
|
283
|
+
nftGenesis.distributeGenesisRewards(i, valueDistributed);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
gnetERC20.transferFrom(msg.sender, address(nftGenesis), storedGenesisValue);
|
|
287
|
+
gnetERC20.transferFrom(
|
|
288
|
+
msg.sender,
|
|
289
|
+
receiver,
|
|
290
|
+
_genesisValue - storedGenesisValue
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function farm(uint tokenId) public notInBlacklist {
|
|
295
|
+
require(ownerOf(tokenId) == msg.sender, "caller is not owner");
|
|
296
|
+
require(ownedTokenMap[tokenId].isBlackListed == false, "token blacklisted");
|
|
297
|
+
uint reward = getFarmValue(tokenId);
|
|
298
|
+
require(reward > 0, "No reward to farm");
|
|
299
|
+
uint tax = (reward * 10) / 100;
|
|
300
|
+
uint halTax = tax / 2;
|
|
301
|
+
gnetERC20.mintForFarm(halTax, valhalla.feeReceiverAddress());
|
|
302
|
+
gnetERC20.mintForFarm(halTax, valhalla.feeReceiverAddress2());
|
|
303
|
+
gnetERC20.mintForFarm(reward - tax, msg.sender);
|
|
304
|
+
|
|
305
|
+
Rank rank;
|
|
306
|
+
address referrer;
|
|
307
|
+
(, , rank, referrer, , , , ) = valhalla.accountMap(msg.sender);
|
|
308
|
+
for (uint i = 1; i <= 100; i++) {
|
|
309
|
+
if (referrer == address(0)) break;
|
|
310
|
+
uint matchingPercentage = _getReferrerFarmMatchingPercentage(i, referrer);
|
|
311
|
+
if (matchingPercentage > 0) {
|
|
312
|
+
uint uplineReward = (reward * matchingPercentage) / 100;
|
|
313
|
+
gnetERC20.mintForFarm(uplineReward, address(this));
|
|
314
|
+
rewardMap[referrer] += uplineReward;
|
|
315
|
+
farmMatchingRewardMap[referrer] += uplineReward;
|
|
316
|
+
}
|
|
317
|
+
(, , rank, referrer, , , , ) = valhalla.accountMap(referrer);
|
|
318
|
+
}
|
|
319
|
+
ownedTokenMap[tokenId].lastFarmedAt = block.timestamp;
|
|
320
|
+
emit Farm(tokenId, reward);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function startClaimingRankReward() external {
|
|
324
|
+
require(msg.sender == address(valhalla), "Only valhalla can call");
|
|
325
|
+
PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
|
|
326
|
+
globalPool.valueLeft = globalPool.claimable;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function stopClaimingRankReward() external {
|
|
330
|
+
require(msg.sender == address(valhalla), "Only valhalla can call");
|
|
331
|
+
PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
|
|
332
|
+
globalPool.claimable = globalPool.valueLeft;
|
|
333
|
+
globalPool.valueLeft = 0;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function getMyRankReward(address _accountAddress) public view returns (uint) {
|
|
337
|
+
Rank rank;
|
|
338
|
+
(, , rank, , , , , ) = valhalla.accountMap(_accountAddress);
|
|
339
|
+
PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
|
|
340
|
+
bool isRankRewardClaimable = valhalla.isRankRewardClaimable();
|
|
341
|
+
if (globalPool.valueLeft == 0) return 0;
|
|
342
|
+
uint rankRewardClaimableAt = valhalla.rankRewardClaimableAt();
|
|
343
|
+
if (isRankRewardClaimable == false) return 0;
|
|
344
|
+
if (rankRewardClaimedAtMap[_accountAddress] >= rankRewardClaimableAt)
|
|
345
|
+
return 0;
|
|
346
|
+
if (rank == Rank.NoRank) return 0;
|
|
347
|
+
uint commonRankDistribution = 0;
|
|
348
|
+
uint rareRankDistribution = 0;
|
|
349
|
+
uint superRareRankDistribution = 0;
|
|
350
|
+
uint epicRankDistribution = 0;
|
|
351
|
+
uint legendRankDistribution = 0;
|
|
352
|
+
uint superLegendRankDistribution = 0;
|
|
353
|
+
(
|
|
354
|
+
commonRankDistribution,
|
|
355
|
+
rareRankDistribution,
|
|
356
|
+
superRareRankDistribution,
|
|
357
|
+
epicRankDistribution,
|
|
358
|
+
legendRankDistribution,
|
|
359
|
+
superLegendRankDistribution
|
|
360
|
+
) = valhalla.rankDistribution();
|
|
361
|
+
uint distribution = 0;
|
|
362
|
+
uint base = 0;
|
|
363
|
+
if (rank == Rank.Common) {
|
|
364
|
+
distribution = commonRankDistribution;
|
|
365
|
+
base = (globalPool.claimable * 3) / 100;
|
|
366
|
+
}
|
|
367
|
+
if (rank == Rank.Rare) {
|
|
368
|
+
distribution = rareRankDistribution;
|
|
369
|
+
base = (globalPool.claimable * 7) / 100;
|
|
370
|
+
}
|
|
371
|
+
if (rank == Rank.SuperRare) {
|
|
372
|
+
distribution = superRareRankDistribution;
|
|
373
|
+
base = (globalPool.claimable * 12) / 100;
|
|
374
|
+
}
|
|
375
|
+
if (rank == Rank.Epic) {
|
|
376
|
+
distribution = epicRankDistribution;
|
|
377
|
+
base = (globalPool.claimable * 18) / 100;
|
|
378
|
+
}
|
|
379
|
+
if (rank == Rank.Legend) {
|
|
380
|
+
distribution = legendRankDistribution;
|
|
381
|
+
base = (globalPool.claimable * 26) / 100;
|
|
382
|
+
}
|
|
383
|
+
if (rank == Rank.SuperLegend) {
|
|
384
|
+
distribution = superLegendRankDistribution;
|
|
385
|
+
base = (globalPool.claimable * 34) / 100;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return base / distribution;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function claimRankReward() public notInBlacklist {
|
|
392
|
+
Rank rank;
|
|
393
|
+
(, , rank, , , , , ) = valhalla.accountMap(msg.sender);
|
|
394
|
+
PoolType storage globalPool = poolMap[GLOBAL_POOL_KEY];
|
|
395
|
+
uint myReward = getMyRankReward(msg.sender);
|
|
396
|
+
uint nftValue = totalValueMap[msg.sender];
|
|
397
|
+
|
|
398
|
+
uint32[7] memory eligValue = [
|
|
399
|
+
0,
|
|
400
|
+
50_000,
|
|
401
|
+
200_000,
|
|
402
|
+
1_000_000,
|
|
403
|
+
5_000_000,
|
|
404
|
+
25_000_000,
|
|
405
|
+
100_000_000
|
|
406
|
+
];
|
|
407
|
+
|
|
408
|
+
require(myReward > 0, "No Reward can be claimed");
|
|
409
|
+
|
|
410
|
+
for (uint i = 0; i < 7; i++) {
|
|
411
|
+
if (uint(rank) == i && rank != Rank.NoRank) {
|
|
412
|
+
require(
|
|
413
|
+
nftValue >= eligValue[i] * 10 ** gnetERC20.decimals(),
|
|
414
|
+
"Not Eligible"
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
uint tax = (myReward * 10) / 100;
|
|
420
|
+
uint halfTax = tax / 2;
|
|
421
|
+
gnetERC20.transfer(valhalla.feeReceiverAddress(), halfTax);
|
|
422
|
+
gnetERC20.transfer(valhalla.feeReceiverAddress2(), halfTax);
|
|
423
|
+
gnetERC20.transfer(msg.sender, myReward - tax);
|
|
424
|
+
rankRewardClaimedAtMap[msg.sender] = block.timestamp;
|
|
425
|
+
globalPool.valueLeft -= myReward;
|
|
426
|
+
emit ClaimRankReward(msg.sender, myReward);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function claimReward() public notInBlacklist {
|
|
430
|
+
uint _reward = rewardMap[msg.sender];
|
|
431
|
+
address feeReceiver = valhalla.feeReceiverAddress();
|
|
432
|
+
address feeReceiver2 = valhalla.feeReceiverAddress2();
|
|
433
|
+
require(_reward > 0, "No reward to be claimed");
|
|
434
|
+
// apply 10% tax
|
|
435
|
+
uint tax = (_reward * 10) / 100;
|
|
436
|
+
uint halfTax = tax / 2;
|
|
437
|
+
gnetERC20.transfer(feeReceiver, halfTax);
|
|
438
|
+
gnetERC20.transfer(feeReceiver2, halfTax);
|
|
439
|
+
gnetERC20.transfer(msg.sender, _reward - tax);
|
|
440
|
+
rewardMap[msg.sender] = 0;
|
|
441
|
+
referralRewardMap[msg.sender] = 0; // TAMBAH INI
|
|
442
|
+
farmMatchingRewardMap[msg.sender] = 0;
|
|
443
|
+
|
|
444
|
+
emit ClaimReward(msg.sender, _reward - tax);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function blacklistToken(uint tokenId) public onlyAdmin {
|
|
448
|
+
OwnedToken storage token = ownedTokenMap[tokenId];
|
|
449
|
+
token.isBlackListed = true;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function _afterTokenTransfer(
|
|
453
|
+
address from,
|
|
454
|
+
address to,
|
|
455
|
+
uint256 tokenId,
|
|
456
|
+
uint256 batchSize
|
|
457
|
+
) internal virtual override {
|
|
458
|
+
super._afterTokenTransfer(from, to, tokenId, batchSize);
|
|
459
|
+
uint256 price = ownedTokenMap[tokenId].mintingPrice;
|
|
460
|
+
if (from == address(0)) {
|
|
461
|
+
totalValueMap[to] += price;
|
|
462
|
+
} else if (to == address(0)) {
|
|
463
|
+
totalValueMap[from] -= price;
|
|
464
|
+
} else {
|
|
465
|
+
totalValueMap[from] -= price;
|
|
466
|
+
totalValueMap[to] += price;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
modifier onlyAdmin() {
|
|
471
|
+
require(
|
|
472
|
+
valhalla.hasRole(valhalla.DEFAULT_ADMIN_ROLE(), msg.sender),
|
|
473
|
+
"Only Admin can perform action"
|
|
474
|
+
);
|
|
475
|
+
_;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
modifier onlyStaff() {
|
|
479
|
+
require(
|
|
480
|
+
valhalla.hasRole(valhalla.DEFAULT_ADMIN_ROLE(), msg.sender) ||
|
|
481
|
+
valhalla.hasRole(valhalla.STAFF_ROLE(), msg.sender),
|
|
482
|
+
"Only Admin can perform action"
|
|
483
|
+
);
|
|
484
|
+
_;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
modifier notInBlacklist() {
|
|
488
|
+
require(
|
|
489
|
+
valhalla.blacklistedAddressMap(msg.sender) != true,
|
|
490
|
+
"Address blacklisted"
|
|
491
|
+
);
|
|
492
|
+
_;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
modifier onlyGenesis() {
|
|
496
|
+
require(msg.sender == address(nftGenesis), "Transaction Prohibited");
|
|
497
|
+
_;
|
|
498
|
+
}
|
|
499
|
+
}
|