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,399 @@
1
+ import { expect } from "chai";
2
+ import { fromBn, toBn } from "evm-bn";
3
+ import { initialize, getState, getAccounts } from "./lib/initializer";
4
+ import { BigNumber } from "ethers";
5
+
6
+ const cardsRegisteredProps = [
7
+ {
8
+ price: 5000,
9
+ percentage: 40,
10
+ maxMinted: 2000,
11
+ },
12
+ {
13
+ price: 2000,
14
+ percentage: 20,
15
+ maxMinted: 1500,
16
+ },
17
+ ];
18
+
19
+ describe("Valhalla NFT Genesis", function () {
20
+ before(async () => {
21
+ await initialize();
22
+ });
23
+
24
+ it("Register NFT Variants", async () => {
25
+ const { nftGenesis, usdt } = getState();
26
+
27
+ // Use sequential loop to guarantee order (ID 0, ID 1)
28
+ for (const c of cardsRegisteredProps) {
29
+ await (
30
+ await nftGenesis.addNft(c.price, c.percentage, c.maxMinted)
31
+ ).wait();
32
+ }
33
+
34
+ const cardsRegisteredAmount = await nftGenesis.amountNftTypes();
35
+ expect(cardsRegisteredAmount).to.eq(2);
36
+
37
+ const decimals = await usdt.decimals(); // Should be 18
38
+
39
+ // Verify Card 0
40
+ const card0 = await nftGenesis.cardMap(0);
41
+ expect(card0.price).to.eq(
42
+ toBn(String(cardsRegisteredProps[0].price), decimals),
43
+ );
44
+ expect(card0.genesisPercentage).to.eq(cardsRegisteredProps[0].percentage);
45
+ expect(card0.maxMinted).to.eq(cardsRegisteredProps[0].maxMinted);
46
+
47
+ // Verify Card 1
48
+ const card1 = await nftGenesis.cardMap(1);
49
+ expect(card1.price).to.eq(
50
+ toBn(String(cardsRegisteredProps[1].price), decimals),
51
+ );
52
+ expect(card1.genesisPercentage).to.eq(cardsRegisteredProps[1].percentage);
53
+ expect(card1.maxMinted).to.eq(cardsRegisteredProps[1].maxMinted);
54
+ });
55
+
56
+ it("should be able to purchase nft Genesis", async () => {
57
+ const { usdt, nftGenesis } = getState();
58
+ const [admin, buyer] = await getAccounts(0, 2);
59
+ const price = toBn("5000", 18);
60
+
61
+ await usdt.connect(admin).transfer(buyer.address, price);
62
+
63
+ const balanceBefore = await usdt.balanceOf(buyer.address);
64
+ const nftBefore = await nftGenesis.balanceOf(buyer.address);
65
+
66
+ const approveTx = await usdt
67
+ .connect(buyer)
68
+ .approve(nftGenesis.address, price);
69
+ await approveTx.wait();
70
+
71
+ const tx = await nftGenesis.connect(buyer).buyMultipleNFT(0, 1);
72
+ await tx.wait();
73
+
74
+ const nftAfter = await nftGenesis.balanceOf(buyer.address);
75
+ const balanceAfter = await usdt.balanceOf(buyer.address);
76
+ const tokenId = await nftGenesis.tokenOfOwnerByIndex(buyer.address, 0);
77
+ const uri = await nftGenesis.tokenURI(tokenId);
78
+ const getMintedNFT = await nftGenesis.nftGenesis(buyer.address, 0);
79
+
80
+ // URI check
81
+ expect(uri).to.eq("https://globalnetwork.finance/api/image/genesis/0");
82
+
83
+ // Balance checks using BigNumber
84
+ expect(getMintedNFT.ownedNfts).to.eq(1);
85
+ expect(nftAfter.sub(nftBefore)).to.eq(1);
86
+
87
+ // Check USDT balance deduction
88
+ expect(balanceBefore.sub(balanceAfter)).to.eq(price);
89
+ });
90
+
91
+ it("should be able to purchase multiple nft Genesis", async () => {
92
+ const { usdt, nftGenesis } = getState();
93
+ const [admin, _, buyer] = await getAccounts(0, 3);
94
+ const amount = 3;
95
+ const pricePerUnit = toBn("5000", 18);
96
+ const totalPrice = pricePerUnit.mul(amount);
97
+
98
+ await usdt.connect(admin).transfer(buyer.address, totalPrice);
99
+
100
+ const balanceBefore = await usdt.balanceOf(buyer.address);
101
+ const nftBefore = await nftGenesis.balanceOf(buyer.address);
102
+
103
+ const approveTx = await usdt
104
+ .connect(buyer)
105
+ .approve(nftGenesis.address, totalPrice);
106
+ await approveTx.wait();
107
+
108
+ const tx = await nftGenesis.connect(buyer).buyMultipleNFT(0, amount);
109
+ await tx.wait();
110
+
111
+ const nftAfter = await nftGenesis.balanceOf(buyer.address);
112
+ const balanceAfter = await usdt.balanceOf(buyer.address);
113
+ const getMintedNFT = await nftGenesis.nftGenesis(buyer.address, 0);
114
+
115
+ expect(getMintedNFT.ownedNfts).to.eq(amount);
116
+ expect(nftAfter.sub(nftBefore)).to.eq(amount);
117
+ expect(balanceBefore.sub(balanceAfter)).to.eq(totalPrice);
118
+ });
119
+
120
+ it("make sure able to purchase nft", async () => {
121
+ // This purchases a Regular NFT (to trigger Genesis Pool distribution)
122
+ const { nft, crowd } = getState();
123
+ const [account] = await getAccounts(0);
124
+ const nftPrice = toBn("5000", 18);
125
+
126
+ // Need to approve enough for the purchase
127
+ const approveTx = await crowd
128
+ .connect(account)
129
+ .approve(nft.address, toBn("10000", 18));
130
+ await approveTx.wait();
131
+
132
+ const tx = await nft.connect(account).buy(0);
133
+ const receipt = await tx.wait();
134
+ expect(receipt.status).to.eq(1);
135
+ });
136
+
137
+ it("should be able to check current nft genesis rewards and have correct rewards", async () => {
138
+ const { nftGenesis } = getState();
139
+
140
+ // Logic:
141
+ // Regular NFT Price = 5000
142
+ // Genesis Pool Allocation = 5% of 5000 = 250
143
+ // Type 0 (Price 5000) Allocation = 40% of 250 = 100
144
+ // Reward Per Unit = 100 / MaxMinted(2000) = 0.05
145
+
146
+ const ONE_UNIT = toBn("1", 18);
147
+ const nftPrice = toBn("5000", 18);
148
+
149
+ const genesisAllocation = nftPrice.mul(5).div(100); // 250
150
+ const type0Allocation = genesisAllocation.mul(40).div(100); // 100
151
+ const rewardPerUnit = type0Allocation.div(2000); // 0.05
152
+
153
+ const [buyer, buyer2] = await getAccounts(1, 2);
154
+
155
+ // buyer has 1 NFT (bought in first test)
156
+ const rewards = await nftGenesis
157
+ .connect(buyer)
158
+ .myNftRewards(0, buyer.address);
159
+
160
+ // buyer2 has 3 NFTs (bought in second test)
161
+ const rewards2 = await nftGenesis
162
+ .connect(buyer2)
163
+ .myNftRewards(0, buyer2.address);
164
+
165
+ // Debug logs if needed
166
+ // console.log("Reward Per Unit:", fromBn(rewardPerUnit, 18));
167
+ // console.log("Buyer 1 Reward:", fromBn(rewards, 18));
168
+
169
+ expect(rewards).to.eq(rewardPerUnit);
170
+ expect(rewards2).to.eq(rewardPerUnit.mul(3));
171
+ });
172
+
173
+ it("should have correct value sended to receiverAddress", async () => {
174
+ const { crowd, nftGenesis } = getState();
175
+
176
+ // Logic:
177
+ // Total Type 0 allocation per Regular NFT sale = 100 tokens.
178
+ // Distributed = RewardPerUnit * TotalMinted
179
+ // Total Minted so far: 1 (buyer) + 3 (buyer2) = 4 units.
180
+ // Distributed = 0.05 * 4 = 0.2 tokens.
181
+ // Sent to Receiver (Undistributed) = 100 - 0.2 = 99.8 tokens.
182
+
183
+ const nftPrice = toBn("5000", 18);
184
+ const genesisAllocation = nftPrice.mul(5).div(100); // 250
185
+ const type0Allocation = genesisAllocation.mul(40).div(100); // 100
186
+ const rewardPerUnit = type0Allocation.div(2000); // 0.05
187
+
188
+ const totalMinted = 4;
189
+ const distributed = rewardPerUnit.mul(totalMinted);
190
+ // Correct logic: Receiver gets the rest of the GLOBAL genesis allocation
191
+ const expectedReceiverAndount = genesisAllocation.sub(distributed);
192
+
193
+ const receiverAddress = await nftGenesis.receiverAddress();
194
+ const balanceReceiver = await crowd.balanceOf(receiverAddress);
195
+
196
+ expect(balanceReceiver).to.eq(expectedReceiverAndount);
197
+ });
198
+
199
+ it("should have correct value genesisPool", async () => {
200
+ const { nftGenesis, crowd } = getState();
201
+ // Genesis Pool (contract balance) should hold the DISTRIBUTED amount that hasn't been claimed yet.
202
+ // i.e., 0.2 tokens.
203
+
204
+ const nftPrice = toBn("5000", 18);
205
+ const genesisAllocation = nftPrice.mul(5).div(100); // 250
206
+ const type0Allocation = genesisAllocation.mul(40).div(100); // 100
207
+ const rewardPerUnit = type0Allocation.div(2000); // 0.05
208
+ const totalMinted = 4;
209
+ const expectedPoolBalance = rewardPerUnit.mul(totalMinted);
210
+
211
+ const balance = await crowd.balanceOf(nftGenesis.address);
212
+ expect(balance).to.eq(expectedPoolBalance);
213
+ });
214
+
215
+ it("should be able to claim genesis rewards and have correct amount", async () => {
216
+ const { nftGenesis, crowd } = getState();
217
+ const [_, buyer, buyer2] = await getAccounts(0, 3); // buyer=idx 1, buyer2=idx 2
218
+
219
+ // buyer2 claims first (owns 3 NFTs, reward 0.15)
220
+ const balanceBefore2 = await crowd.balanceOf(buyer2.address);
221
+ await (await nftGenesis.connect(buyer2).claimRewards(0)).wait();
222
+ const balanceAfter2 = await crowd.balanceOf(buyer2.address);
223
+
224
+ // Expected reward for 3 units = 0.05 * 3 = 0.15
225
+ const expectedReward2 = toBn("0.15", 18); // 0.05 * 3
226
+ expect(balanceAfter2.sub(balanceBefore2)).to.eq(expectedReward2);
227
+
228
+ // buyer claims next (owns 1 NFT, reward 0.05)
229
+ const balanceBefore1 = await crowd.balanceOf(buyer.address);
230
+ await (await nftGenesis.connect(buyer).claimRewards(0)).wait();
231
+ const balanceAfter1 = await crowd.balanceOf(buyer.address);
232
+
233
+ const expectedReward1 = toBn("0.05", 18);
234
+ expect(balanceAfter1.sub(balanceBefore1)).to.eq(expectedReward1);
235
+
236
+ // Pool should be empty now for this distribution
237
+ const genesisPoolAfter = await nftGenesis.nftGenesisPool();
238
+ // Note: genesisPool tracks total value, but contract balance tracks unclaimed.
239
+ // nftGenesisPool variable in contract tracks *available* rewards?
240
+ // Let's check logic: claimRewards reduces nftGenesisPool.
241
+ // So it should be close to 0 (or exactly 0 if only this type exist).
242
+ // Actually there might be dust or other types if any.
243
+ // But since we only distributed to Type 0 and claimed all, it should be 0.
244
+
245
+ expect(genesisPoolAfter).to.eq(0);
246
+ });
247
+
248
+ it("prepare calculation for next test cases", async () => {
249
+ const { nft, crowd } = getState();
250
+ const accounts = await getAccounts(0, 6);
251
+ // Accounts 3, 4, 5
252
+
253
+ const transferAmount = toBn("25000", 18); // 25k (enough for Card #1)
254
+ const smallAmount = toBn("5000", 18); // 5k (Card #0)
255
+
256
+ // Setup balances
257
+ await (
258
+ await crowd
259
+ .connect(accounts[0])
260
+ .transfer(accounts[3].address, transferAmount)
261
+ ).wait();
262
+ await (
263
+ await crowd
264
+ .connect(accounts[0])
265
+ .transfer(accounts[4].address, smallAmount)
266
+ ).wait();
267
+ await (
268
+ await crowd
269
+ .connect(accounts[0])
270
+ .transfer(accounts[5].address, transferAmount)
271
+ ).wait();
272
+
273
+ // Approvals
274
+ await (
275
+ await crowd.connect(accounts[3]).approve(nft.address, transferAmount)
276
+ ).wait();
277
+ await (
278
+ await crowd.connect(accounts[4]).approve(nft.address, smallAmount)
279
+ ).wait();
280
+ await (
281
+ await crowd.connect(accounts[5]).approve(nft.address, transferAmount)
282
+ ).wait();
283
+
284
+ // Buy NFTs to generate more rewards
285
+ // Card #1 sales generate 5% to Genesis Pool too.
286
+ // Price 25000 -> 5% = 1250.
287
+ // Type 0 allocation (40%) = 500.
288
+ // Reward per unit = 500 / 2000 = 0.25.
289
+
290
+ await (await nft.connect(accounts[3]).buy(1)).wait(); // +0.25 reward per unit
291
+ await (await nft.connect(accounts[4]).buy(0)).wait(); // +0.05 reward per unit
292
+ await (await nft.connect(accounts[5]).buy(1)).wait(); // +0.25 reward per unit
293
+
294
+ // Total new reward per unit = 0.25 + 0.05 + 0.25 = 0.55
295
+ });
296
+
297
+ it("should be able to claim rewards automatically when already have a genesis nft and then buy another", async () => {
298
+ const { crowd, nftGenesis, usdt } = getState();
299
+ const [admin, _, buyer] = await getAccounts(0, 3); // buyer2 (idx 2)
300
+
301
+ // buyer2 currently owns 3 NFTs.
302
+ // Previous rewards were claimed.
303
+ // New rewards generated in "prepare calculation" step: 0.55 per unit.
304
+ // Total pending reward = 0.55 * 3 = 1.65.
305
+
306
+ const pendingRewards = await nftGenesis
307
+ .connect(buyer)
308
+ .myNftRewards(0, buyer.address);
309
+ // Verify pending expectation
310
+ const expectedPending = toBn("0.55", 18).mul(3);
311
+
312
+ // Allow small rounding diff if any, but with integer math usually exact
313
+ expect(pendingRewards).to.eq(expectedPending);
314
+
315
+ const balanceCROWDBefore = await crowd.balanceOf(buyer.address);
316
+
317
+ // Buy 3 more Genesis NFTs
318
+ const pricePerUnit = toBn("5000", 18);
319
+ const cost = pricePerUnit.mul(3);
320
+
321
+ await usdt.connect(admin).transfer(buyer.address, cost);
322
+ await (await usdt.connect(buyer).approve(nftGenesis.address, cost)).wait();
323
+
324
+ // This buy action should trigger auto-claim of the 1.65 CROWD rewards
325
+ await (await nftGenesis.connect(buyer).buyMultipleNFT(0, 3)).wait();
326
+
327
+ const balanceCROWDAfter = await crowd.balanceOf(buyer.address);
328
+
329
+ // Check if rewards were received
330
+ expect(balanceCROWDAfter.sub(balanceCROWDBefore)).to.eq(expectedPending);
331
+
332
+ // New rewards should be 0 immediately after buy (for the old execution point)
333
+ // But wait, the marker updates only when distributed.
334
+ // The claimed amount is reset.
335
+ const newPending = await nftGenesis
336
+ .connect(buyer)
337
+ .myNftRewards(0, buyer.address);
338
+ expect(newPending).to.eq(0);
339
+ });
340
+
341
+ it("should be able to buy different variant nft", async () => {
342
+ const { usdt, nftGenesis } = getState();
343
+ const [admin, buyer] = await getAccounts(0, 2); // reuse buyer (idx 1)
344
+
345
+ // Buy Type 1 (Price 2000)
346
+ const price = toBn("2000", 18);
347
+
348
+ await usdt.connect(admin).transfer(buyer.address, price);
349
+ await (await usdt.connect(buyer).approve(nftGenesis.address, price)).wait();
350
+
351
+ const nftBefore = await nftGenesis.balanceOf(buyer.address);
352
+
353
+ await (await nftGenesis.connect(buyer).buyMultipleNFT(1, 1)).wait();
354
+
355
+ const nftAfter = await nftGenesis.balanceOf(buyer.address);
356
+ expect(nftAfter.sub(nftBefore)).to.eq(1);
357
+
358
+ // Check ownership of Type 1
359
+ const cardInfo = await nftGenesis.nftGenesis(buyer.address, 1);
360
+ expect(cardInfo.ownedNfts).to.eq(1);
361
+
362
+ // URI Check for Type 1
363
+ // buyer had 1 type 0. bought 1 type 1. Total 2. Index 1?
364
+ // tokenOfOwnerByIndex might return in order.
365
+ // Let's find the token with cardId 1.
366
+ // This part is tricky without knowing exact token ID logic, but usually append.
367
+ // We can just trust cardInfo verification above.
368
+ });
369
+
370
+ it("should be able to transfer NFT", async () => {
371
+ const { nftGenesis, crowd } = getState();
372
+ const [owner, receiver] = await getAccounts(2, 2); // owner=buyer2(idx2), receiver=idx3
373
+
374
+ // Owner (buyer2) has 3 (initial) + 3 (new) = 6 NFTs of Type 0.
375
+ // Receiver (idx3) has 0 NFTs.
376
+
377
+ const ownerCardBefore = await nftGenesis.nftGenesis(owner.address, 0);
378
+ const receiverCardBefore = await nftGenesis.nftGenesis(receiver.address, 0);
379
+
380
+ // console.log("Owner NFTs:", ownerCardBefore.ownedNfts.toString());
381
+
382
+ // Transfer 1 NFT from Owner to Receiver via token ID
383
+ const tokenId = await nftGenesis.tokenOfOwnerByIndex(owner.address, 0); // Get first token
384
+
385
+ await (
386
+ await nftGenesis
387
+ .connect(owner)
388
+ .transferFrom(owner.address, receiver.address, tokenId)
389
+ ).wait();
390
+
391
+ const ownerCardAfter = await nftGenesis.nftGenesis(owner.address, 0);
392
+ const receiverCardAfter = await nftGenesis.nftGenesis(receiver.address, 0);
393
+
394
+ expect(ownerCardAfter.ownedNfts).to.eq(ownerCardBefore.ownedNfts.sub(1));
395
+ expect(receiverCardAfter.ownedNfts).to.eq(
396
+ receiverCardBefore.ownedNfts.add(1),
397
+ );
398
+ });
399
+ });
@@ -0,0 +1,210 @@
1
+ import { expect } from "chai";
2
+ import { fromBn, toBn } from "evm-bn";
3
+ import { initialize, getState, getAccounts } from "./lib/initializer";
4
+
5
+ describe("Valhalla NFT Purchase", function () {
6
+ before(async () => {
7
+ await initialize();
8
+ });
9
+
10
+ it("make sure able to purchase nft", async () => {
11
+ const { nft, crowd } = getState();
12
+ const [account] = await getAccounts(0);
13
+ // Approve full NFT price - contract handles all transfers including genesis pool
14
+ const approveTx = await crowd
15
+ .connect(account)
16
+ .approve(nft.address, toBn("10000", 18));
17
+ await approveTx.wait();
18
+
19
+ const tx = await nft.connect(account).buy(0);
20
+ const receipt = await tx.wait();
21
+ expect(receipt.status).to.eq(1);
22
+ });
23
+
24
+ it("should fail to purchase nft if not registered", async () => {
25
+ const { nft, crowd } = getState();
26
+ const [unregisteredUser] = await getAccounts(50, 1); // Use new account
27
+
28
+ // Transfer token to unregistered user
29
+ const [admin] = await getAccounts(0);
30
+ await crowd
31
+ .connect(admin)
32
+ .transfer(unregisteredUser.address, toBn("10000", 18));
33
+
34
+ // Approve
35
+ await crowd
36
+ .connect(unregisteredUser)
37
+ .approve(nft.address, toBn("10000", 18));
38
+
39
+ // Expect revert
40
+ await expect(nft.connect(unregisteredUser).buy(0)).to.be.revertedWith(
41
+ "Registration required",
42
+ );
43
+ });
44
+
45
+ it("make sure total supply is correct", async () => {
46
+ const { nft } = getState();
47
+ const totalSupply = await nft.totalSupply();
48
+ expect(totalSupply.toNumber()).to.eq(1);
49
+ });
50
+
51
+ it("make sure global pool is correct (17%)", async () => {
52
+ const { nft } = getState();
53
+ const globalPool = await nft.getGlobalPool();
54
+ const calculation = toBn(String((5000 * 17) / 100), 18);
55
+ const isAccurate = calculation.eq(globalPool.claimable);
56
+ expect(isAccurate).to.eq(true);
57
+ });
58
+
59
+ it("make sure fee receiver reward is correct (20%)", async () => {
60
+ const { valhalla, crowd } = getState();
61
+ const feeReceiverAddress = await valhalla.feeReceiverAddress();
62
+ const feeReceiverAddress2 = await valhalla.feeReceiverAddress2();
63
+ const balanceFee = await crowd.balanceOf(feeReceiverAddress);
64
+ const balanceFee2 = await crowd.balanceOf(feeReceiverAddress2);
65
+
66
+ // Fee receiver should get 20% total (10% each)
67
+ const rewardCalc = toBn(String((5000 * 20) / 100), 18);
68
+ const halfFeeReward = rewardCalc.div(2);
69
+
70
+ expect(halfFeeReward).to.eq(balanceFee);
71
+ expect(halfFeeReward).to.eq(balanceFee2);
72
+ });
73
+
74
+ it("make sure 50% is burned", async () => {
75
+ const { crowd } = getState();
76
+ const totalSupply = await crowd.totalSupply();
77
+
78
+ // Initial supply is 1,000,000,000 CROWD
79
+ // After buying NFT for 5000 CROWD, 50% (2500 CROWD) should be burned
80
+ const initialSupply = toBn("1000000000", 18);
81
+ const burnedAmount = toBn(String((5000 * 50) / 100), 18);
82
+ const expectedSupply = initialSupply.sub(burnedAmount);
83
+
84
+ expect(totalSupply).to.eq(expectedSupply);
85
+ });
86
+
87
+ it("make sure direct referral gets 8% reward", async () => {
88
+ const { nft, crowd, valhalla, usdt, nftGenesis } = getState();
89
+ const [admin] = await getAccounts(0, 1);
90
+ const [referrer, buyer] = await getAccounts(15, 2);
91
+
92
+ // Register referrer first (referrer needs to be registered)
93
+ const transferUsdtToReferrerTx = await usdt
94
+ .connect(admin)
95
+ .transfer(referrer.address, toBn("100", 18));
96
+ await transferUsdtToReferrerTx.wait();
97
+
98
+ const approveUsdtReferrerTx = await usdt
99
+ .connect(referrer)
100
+ .approve(valhalla.address, toBn("100", 18));
101
+ await approveUsdtReferrerTx.wait();
102
+
103
+ const registerReferrerTx = await valhalla
104
+ .connect(referrer)
105
+ .register(admin.address);
106
+ await registerReferrerTx.wait();
107
+
108
+ // Transfer USDT for registration fee
109
+ const transferUsdtTx = await usdt
110
+ .connect(admin)
111
+ .transfer(buyer.address, toBn("100", 18));
112
+ await transferUsdtTx.wait();
113
+
114
+ // Approve USDT for registration
115
+ const approveUsdtTx = await usdt
116
+ .connect(buyer)
117
+ .approve(valhalla.address, toBn("100", 18));
118
+ await approveUsdtTx.wait();
119
+
120
+ // Transfer CROWD to buyer for NFT purchase
121
+ const transferTx = await crowd
122
+ .connect(admin)
123
+ .transfer(buyer.address, toBn("10000", 18));
124
+ await transferTx.wait();
125
+
126
+ // Register buyer with referrer as direct referral
127
+ const registerTx = await valhalla.connect(buyer).register(referrer.address);
128
+ await registerTx.wait();
129
+
130
+ // Get referrer's reward before purchase
131
+ const rewardBefore = await nft.rewardMap(referrer.address);
132
+
133
+ // Buyer approves and purchases NFT (full amount for genesis pool transfer)
134
+ const approveTx = await crowd
135
+ .connect(buyer)
136
+ .approve(nft.address, toBn("10000", 18));
137
+ await approveTx.wait();
138
+
139
+ const approveGenesisTx = await crowd
140
+ .connect(buyer)
141
+ .approve(nftGenesis.address, toBn("10000", 18));
142
+ await approveGenesisTx.wait();
143
+
144
+ const buyTx = await nft.connect(buyer).buy(0);
145
+ await buyTx.wait();
146
+
147
+ // Get referrer's reward after purchase
148
+ const rewardAfter = await nft.rewardMap(referrer.address);
149
+ const rewardReceived = rewardAfter.sub(rewardBefore);
150
+
151
+ // Direct referral should get 8% of NFT price
152
+ const expectedReward = toBn(String((5000 * 8) / 100), 18);
153
+ expect(rewardReceived).to.eq(expectedReward);
154
+ });
155
+
156
+ it("make sure genesis pool receives 5%", async () => {
157
+ const { nft, crowd, nftGenesis, valhalla, usdt } = getState();
158
+ const [admin] = await getAccounts(0, 1);
159
+ const [referrer] = await getAccounts(14, 1);
160
+ const [buyer] = await getAccounts(20, 1);
161
+
162
+ // Transfer USDT for registration fee
163
+ const transferUsdtTx = await usdt
164
+ .connect(admin)
165
+ .transfer(buyer.address, toBn("100", 18));
166
+ await transferUsdtTx.wait();
167
+
168
+ // Approve USDT for registration
169
+ const approveUsdtTx = await usdt
170
+ .connect(buyer)
171
+ .approve(valhalla.address, toBn("100", 18));
172
+ await approveUsdtTx.wait();
173
+
174
+ // Register buyer first
175
+ const registerTx = await valhalla.connect(buyer).register(referrer.address);
176
+ await registerTx.wait();
177
+
178
+ // Transfer CROWD to buyer
179
+ const transferTx = await crowd
180
+ .connect(admin)
181
+ .transfer(buyer.address, toBn("10000", 18));
182
+ await transferTx.wait();
183
+
184
+ // Get genesis pool balance before purchase
185
+ const genesisAddress = await nftGenesis.receiverAddress();
186
+ const genesisBalanceBefore = await crowd.balanceOf(genesisAddress);
187
+
188
+ // Buyer approves and purchases NFT (full amount for genesis pool transfer)
189
+ const approveTx = await crowd
190
+ .connect(buyer)
191
+ .approve(nft.address, toBn("10000", 18));
192
+ await approveTx.wait();
193
+
194
+ const approveGenesisTx = await crowd
195
+ .connect(buyer)
196
+ .approve(nftGenesis.address, toBn("10000", 18));
197
+ await approveGenesisTx.wait();
198
+
199
+ const buyTx = await nft.connect(buyer).buy(0);
200
+ await buyTx.wait();
201
+
202
+ // Get genesis pool balance after purchase
203
+ const genesisBalanceAfter = await crowd.balanceOf(genesisAddress);
204
+ const genesisReceived = genesisBalanceAfter.sub(genesisBalanceBefore);
205
+
206
+ // Genesis pool should receive 5% of NFT price
207
+ const expectedGenesisAmount = toBn(String((5000 * 5) / 100), 18);
208
+ expect(genesisReceived).to.eq(expectedGenesisAmount);
209
+ });
210
+ });