@gooddollar/goodprotocol 1.0.0-beta.23 → 1.0.0-beta.31

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.
Files changed (140) hide show
  1. package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
  2. package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
  3. package/artifacts/contracts/DAOStackInterfaces.sol/Controller.json +19 -0
  4. package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
  5. package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
  6. package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
  7. package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
  8. package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
  9. package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
  10. package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
  11. package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
  12. package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
  13. package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
  14. package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
  15. package/artifacts/contracts/Interfaces.sol/IGoodDollar.json +13 -0
  16. package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
  17. package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
  18. package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
  19. package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
  20. package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
  21. package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
  22. package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
  23. package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
  24. package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
  25. package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
  26. package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
  27. package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
  28. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
  29. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.json +2 -2
  30. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
  31. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.json +2 -2
  32. package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
  33. package/artifacts/contracts/governance/GReputation.sol/GReputation.json +41 -2
  34. package/artifacts/contracts/governance/GovarnanceStaking.sol/GovernanceStaking.dbg.json +1 -1
  35. package/artifacts/contracts/governance/GovarnanceStaking.sol/GovernanceStaking.json +2 -2
  36. package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
  37. package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
  38. package/artifacts/contracts/governance/Reputation.sol/Reputation.json +2 -2
  39. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
  40. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.json +2 -2
  41. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
  42. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.json +2 -2
  43. package/artifacts/contracts/mocks/AaveUSDMockOracle.sol/AaveUSDMockOracle.dbg.json +1 -1
  44. package/artifacts/contracts/mocks/BatUSDMockOracle.sol/BatUSDMockOracle.dbg.json +1 -1
  45. package/artifacts/contracts/mocks/CompUsdMockOracle.sol/CompUSDMockOracle.dbg.json +1 -1
  46. package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
  47. package/artifacts/contracts/mocks/DaiEthPriceMockOracle.sol/DaiEthPriceMockOracle.dbg.json +1 -1
  48. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
  49. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.json +2 -2
  50. package/artifacts/contracts/mocks/EthUSDMockOracle.sol/EthUSDMockOracle.dbg.json +1 -1
  51. package/artifacts/contracts/mocks/GasPriceMockOracle.sol/GasPriceMockOracle.dbg.json +1 -1
  52. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
  53. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.json +4 -4
  54. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
  55. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.json +37 -11
  56. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
  57. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.json +2 -2
  58. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
  59. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.json +2 -2
  60. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
  61. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.json +2 -2
  62. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
  63. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.json +2 -2
  64. package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
  65. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
  66. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.json +2 -2
  67. package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
  68. package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
  69. package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
  70. package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
  71. package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
  72. package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
  73. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
  74. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.json +2 -2
  75. package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
  76. package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
  77. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
  78. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.json +2 -2
  79. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
  80. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.json +2 -2
  81. package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
  82. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
  83. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.json +2 -2
  84. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
  85. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.json +2 -2
  86. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
  87. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.json +2 -2
  88. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
  89. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.json +37 -11
  90. package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
  91. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
  92. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.json +2 -2
  93. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
  94. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.json +3 -3
  95. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
  96. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.json +4 -4
  97. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
  98. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.json +4 -4
  99. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
  100. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.json +6 -6
  101. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
  102. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.json +2 -2
  103. package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
  104. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
  105. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.json +2 -2
  106. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
  107. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.json +2 -2
  108. package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
  109. package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
  110. package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
  111. package/artifacts/contracts/utils/NameService.sol/NameService.json +2 -2
  112. package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
  113. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
  114. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.json +12 -2
  115. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
  116. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.json +2 -2
  117. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
  118. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.json +2 -2
  119. package/contracts/DAOStackInterfaces.sol +2 -0
  120. package/contracts/Interfaces.sol +2 -0
  121. package/contracts/governance/CompoundVotingMachine.sol +1 -1
  122. package/contracts/governance/GReputation.sol +70 -40
  123. package/contracts/staking/GoodFundManager.sol +41 -40
  124. package/contracts/utils/ProtocolUpgrade.sol +56 -5
  125. package/contracts/utils/ProtocolUpgradeFuse.sol +28 -6
  126. package/package.json +3 -2
  127. package/releases/deployment.json +1 -1
  128. package/releases/olddao.json +1 -1
  129. package/scripts/governance/README.md +70 -0
  130. package/scripts/governance/airdropCalculation.ts +264 -70
  131. package/scripts/upgradeToV2/upgradeToV2.ts +132 -124
  132. package/test/governance/GReputation.test.ts +145 -86
  133. package/test/localOldDaoDeploy.ts +5 -0
  134. package/test/staking/DifferentStakingTokens.test.ts +11 -10
  135. package/test/staking/SimpleDAIStaking.test.ts +37 -40
  136. package/test/staking/StakingRewards.test.ts +57 -65
  137. package/test/staking/SwapHelper.test.ts +17 -21
  138. package/test/staking/UsdcAaveStaking.test.ts +12 -12
  139. package/test/utils/ProtocolUpgrade.test.ts +70 -6
  140. package/yarn.lock +12 -5
@@ -1,6 +1,9 @@
1
1
  import { get, range, chunk, flatten, mergeWith, sortBy, uniq } from "lodash";
2
2
  import fs from "fs";
3
- import MerkleTree from "merkle-tree-solidity";
3
+ import MerkleTree, {
4
+ checkProof,
5
+ checkProofOrdered
6
+ } from "merkle-tree-solidity";
4
7
  import coreContracts from "@gooddollar/goodcontracts/releases/deployment.json";
5
8
  import stakingContracts from "@gooddollar/goodcontracts/stakingModel/releases/deployment.json";
6
9
  import upgradablesContracts from "@gooddollar/goodcontracts/upgradables/releases/deployment.json";
@@ -8,7 +11,8 @@ import SimpleDAIStaking from "@gooddollar/goodcontracts/stakingModel/build/contr
8
11
  import { ethers as Ethers } from "hardhat";
9
12
  import fetch from "node-fetch";
10
13
  import { request, gql } from "graphql-request";
11
- import PromiseQueue from "promise-queue";
14
+ import { Retrier } from "@jsier/retrier";
15
+ import PromisePool from "async-promise-pool";
12
16
 
13
17
  const GD_FUSE = "0x495d133b938596c9984d462f007b676bdc57ecec";
14
18
  const GD_MAINNET = "0x67c5870b4a41d4ebef24d2456547a03f1f3e094b";
@@ -66,8 +70,6 @@ flatten(
66
70
  .filter(x => typeof x === "string" && x.startsWith("0x"))
67
71
  .map(addr => (systemContracts[addr.toLowerCase()] = true));
68
72
 
69
- const step = 500;
70
-
71
73
  const isSystemContract = addr => systemContracts[addr.toLowerCase()] === true;
72
74
 
73
75
  const updateBalance = (balance, update) => {
@@ -92,7 +94,11 @@ export const airdrop = (
92
94
  ethplorer_key,
93
95
  etherscan_key
94
96
  ) => {
95
- const fuseArchiveProvider = new ethers.providers.JsonRpcProvider(
97
+ const fuseProvider = new ethers.providers.JsonRpcProvider(
98
+ "https://rpc.fuse.io"
99
+ );
100
+
101
+ const fuseArchiveProvider = new ethers.providers.JsonRpcBatchProvider(
96
102
  "https://explorer-node.fuse.io/"
97
103
  );
98
104
 
@@ -133,12 +139,12 @@ export const airdrop = (
133
139
  const ubi = new ethers.Contract(
134
140
  "0xAACbaaB8571cbECEB46ba85B5981efDB8928545e",
135
141
  ["event UBIClaimed(address indexed from, uint amount)"],
136
- fuseArchiveProvider
142
+ fuseProvider
137
143
  );
138
144
  const ubinew = new ethers.Contract(
139
145
  "0xD7aC544F8A570C4d8764c3AAbCF6870CBD960D0D",
140
146
  ["event UBIClaimed(address indexed from, uint amount)"],
141
- fuseArchiveProvider
147
+ fuseProvider
142
148
  );
143
149
  const usdcgdYieldFarming = new ethers.Contract(
144
150
  "0x04Ee5DE43332aF99eeC2D40de19962AA1cC583EC",
@@ -161,7 +167,7 @@ export const airdrop = (
161
167
  const events = await staking.queryFilter(
162
168
  staking.filters.DAIStaked(),
163
169
  10575628, //block contract was created,
164
- ETH_SNAPSHOT_BLOCK
170
+ Math.max(ETH_SNAPSHOT_BLOCK, 10575628)
165
171
  );
166
172
 
167
173
  const nowBlock = ETH_SNAPSHOT_BLOCK; //await staking.provider.getBlockNumber();
@@ -178,7 +184,7 @@ export const airdrop = (
178
184
  const daiDonationEvents = await dai.queryFilter(
179
185
  dai.filters.Transfer(null, "0x93FB057EeC37aBc11D955d1C09e6A0d218F35CfF"),
180
186
  11512056, //donation staking contract creation block,
181
- ETH_SNAPSHOT_BLOCK
187
+ Math.max(ETH_SNAPSHOT_BLOCK, 11512056)
182
188
  );
183
189
 
184
190
  const daiDonationsToAggregate = daiDonationEvents
@@ -195,11 +201,13 @@ export const airdrop = (
195
201
  "homestead",
196
202
  etherscan_key
197
203
  );
204
+
205
+ //use etherscan to read past eth transfers to the donation contract
198
206
  let historyPromises = (
199
207
  await provider.getHistory(
200
208
  "0x93FB057EeC37aBc11D955d1C09e6A0d218F35CfF",
201
209
  11512056,
202
- ETH_SNAPSHOT_BLOCK
210
+ Math.max(ETH_SNAPSHOT_BLOCK, 11512056)
203
211
  )
204
212
  )
205
213
  .filter(_ => _.value.gt(ethers.constants.Zero))
@@ -243,7 +251,7 @@ export const airdrop = (
243
251
  const withdrawevents = await staking.queryFilter(
244
252
  staking.filters.DAIStakeWithdraw(),
245
253
  10575628,
246
- ETH_SNAPSHOT_BLOCK
254
+ Math.max(ETH_SNAPSHOT_BLOCK, 10575628)
247
255
  );
248
256
  withdrawevents.forEach(
249
257
  _ =>
@@ -494,16 +502,17 @@ export const airdrop = (
494
502
  const staked = await usdcgdYieldFarming.queryFilter(
495
503
  usdcgdYieldFarming.filters.Staked(),
496
504
  10560021,
497
- FUSE_SNAPSHOT_BLOCK
505
+ Math.max(FUSE_SNAPSHOT_BLOCK, 10560021)
498
506
  );
499
- const [totalStaked, ,] = await usdcgdYieldFarming.interestData({
500
- blockTag: FUSE_SNAPSHOT_BLOCK
501
- });
502
507
 
503
508
  const farmers = {};
504
509
  const yieldFarmingRep =
505
510
  addresses[usdcgdYieldFarming.address.toLowerCase()]?.balance || 0;
506
511
  if (yieldFarmingRep > 0) {
512
+ const [totalStaked, ,] = await usdcgdYieldFarming.interestData({
513
+ blockTag: FUSE_SNAPSHOT_BLOCK
514
+ });
515
+
507
516
  await Promise.all(
508
517
  staked.map(async e => {
509
518
  const [balance] = await usdcgdYieldFarming.getStakerData(
@@ -544,12 +553,103 @@ export const airdrop = (
544
553
  return addresses;
545
554
  };
546
555
 
556
+ const getFuseHolders = async (addresses: Balances = {}) => {
557
+ const toFetch = {};
558
+
559
+ const step = 1000;
560
+ const gdNonArchive = gd.connect(fuseProvider);
561
+
562
+ const latestBlock = FUSE_SNAPSHOT_BLOCK; //await ubiContract.provider.getBlockNumber();
563
+ const blocks = range(6400000, latestBlock, step);
564
+ const filter = gdNonArchive.filters.Transfer();
565
+
566
+ const pool = new PromisePool({ concurrency: 50 });
567
+
568
+ blocks.forEach(bc => {
569
+ pool.add(async () => {
570
+ const options = { limit: 20, delay: 2000 };
571
+ const retrier = new Retrier(options);
572
+ // Query the filter (the latest could be omitted)
573
+ const logs = await retrier.resolve(attempt => {
574
+ console.log("fetching block transfer logs", { attempt, bc });
575
+
576
+ return gdNonArchive.queryFilter(
577
+ filter,
578
+ bc,
579
+ Math.min(bc + step - 1, latestBlock)
580
+ );
581
+ });
582
+
583
+ logs.forEach(l => (toFetch[l.args.to.toLowerCase()] = true));
584
+ console.log("found Transfer logs in block:", { bc }, logs.length);
585
+ });
586
+ });
587
+
588
+ await pool.all();
589
+
590
+ // for (let blockChunk of chunk(blocks, 30)) {
591
+ // // Get the filter (the second null could be omitted)
592
+ // const ps = blockChunk.map(async bc => {
593
+ // const options = { limit: 10, delay: 2000 };
594
+ // const retrier = new Retrier(options);
595
+ // // Query the filter (the latest could be omitted)
596
+ // const logs = await retrier.resolve(attempt => {
597
+ // console.log("fetching block transfer logs", { attempt, bc });
598
+ // return gdNonArchive.queryFilter(
599
+ // filter,
600
+ // bc,
601
+ // Math.min(bc + step - 1, latestBlock)
602
+ // );
603
+ // });
604
+
605
+ // logs.forEach(l => (toFetch[l.args.to.toLowerCase()] = true));
606
+ // console.log("found Transfer logs in block:", { bc }, logs.length);
607
+ // });
608
+ // await Promise.all(ps);
609
+ // }
610
+ const addrs = Object.keys(toFetch);
611
+ console.log("found G$ holders, fetching balacnes...:", addrs.length);
612
+ // Print out all the values:
613
+ let fetched = 0;
614
+ const balancesPool = new PromisePool({ concurrency: 10 });
615
+
616
+ for (let addrChunk of chunk(addrs, 50)) {
617
+ balancesPool.add(async () => {
618
+ const ps = addrChunk.map(async uAddress => {
619
+ const curBalance = get(addresses, `${uAddress}.balance`, 0);
620
+ const isNotContract = get(
621
+ addresses,
622
+ `${uAddress}.isNotContract`,
623
+ (await gdNonArchive.provider.getCode(uAddress).catch(e => "0x")) ===
624
+ "0x"
625
+ );
626
+ const balance = await gd
627
+ .balanceOf(uAddress)
628
+ .then(_ => _.toNumber(), { blockTag: FUSE_SNAPSHOT_BLOCK });
629
+ const claims = get(uAddress, "claims", 0) + 1;
630
+ addresses[uAddress] = updateBalance(addresses[uAddress], {
631
+ balance: curBalance + balance,
632
+ isNotContract
633
+ });
634
+ });
635
+ await Promise.all(ps);
636
+ fetched += addrChunk.length;
637
+ console.log("fetched fuse balances:", fetched);
638
+ });
639
+ }
640
+ await balancesPool.all();
641
+ return addresses;
642
+ };
643
+
547
644
  const getBlockScoutHolders = async (addresses: Balances = {}) => {
548
645
  let initialUrl = `https://explorer.fuse.io/tokens/${gd.address}/token-holders?type=JSON`;
549
- const queue = new PromiseQueue(30);
646
+ const pool = new PromisePool({ concurrency: 30 });
647
+ const gdNonArchive = gd.connect(fuseProvider);
648
+
550
649
  let analyzedPages = 0;
551
650
  let analyzedBalances = 0;
552
651
  let failedAccounts = [];
652
+ let toFetch = [];
553
653
 
554
654
  const fetchBalances = async foundBalances => {
555
655
  const ps = foundBalances
@@ -560,9 +660,10 @@ export const airdrop = (
560
660
  const isNotContract = get(
561
661
  addresses,
562
662
  `${uAddress}.isNotContract`,
563
- (await gd.provider.getCode(b[0]).catch(e => "0x")) === "0x"
663
+ (await gdNonArchive.provider.getCode(b[0]).catch(e => "0x")) ===
664
+ "0x"
564
665
  );
565
- const cleanBalance = await gd
666
+ const cleanBalance = await gdNonArchive
566
667
  .balanceOf(uAddress, { blockTag: FUSE_SNAPSHOT_BLOCK })
567
668
  .catch(e =>
568
669
  gd.balanceOf(uAddress, {
@@ -587,7 +688,7 @@ export const airdrop = (
587
688
  let [, path] = next_page_path.match(/\?(.*$)/);
588
689
  const params = path + "&type=JSON";
589
690
  let nextUrl = `https://explorer.fuse.io/tokens/${gd.address}/token-holders?${params}`;
590
- queue.add(() => analyzeUrl(nextUrl));
691
+ pool.add(() => analyzeUrl(nextUrl));
591
692
  }
592
693
 
593
694
  if (items && items.length) {
@@ -596,23 +697,32 @@ export const airdrop = (
596
697
  );
597
698
  analyzedPages++;
598
699
  analyzedBalances += foundBalances.length;
599
- await fetchBalances(foundBalances);
700
+ toFetch = toFetch.concat(foundBalances);
701
+ // await fetchBalances(foundBalances);
600
702
  }
601
- console.log("fetched:", { url, next_page_path });
602
- };
603
-
604
- queue.add(() => analyzeUrl(initialUrl));
605
- while (true) {
606
- console.log("waiting for queue:", queue.pendingPromises, {
607
- queued: queue.queue.length,
703
+ console.log("fetched blockscout url:", {
704
+ url,
705
+ next_page_path,
608
706
  analyzedBalances,
609
707
  analyzedPages
610
708
  });
611
- if (queue.pendingPromises === 0) {
612
- break;
613
- }
614
- await new Promise(res => setTimeout(res, 5000));
709
+ };
710
+
711
+ pool.add(() => analyzeUrl(initialUrl));
712
+ await pool.all();
713
+
714
+ console.log("fetching fuse balances....", toFetch.length);
715
+ let fetched = 0;
716
+ const balancesPool = new PromisePool({ concurrency: 10 });
717
+
718
+ for (let addrChunk of chunk(toFetch, 50)) {
719
+ balancesPool.add(async () => {
720
+ await fetchBalances(addrChunk);
721
+ fetched += 500;
722
+ console.log("fetched fuse balances:", fetched);
723
+ });
615
724
  }
725
+ await balancesPool.all();
616
726
  console.log("refetching fuse balances failed:", failedAccounts.length);
617
727
  await fetchBalances(failedAccounts);
618
728
  };
@@ -668,23 +778,27 @@ export const airdrop = (
668
778
  balances: Balances = {},
669
779
  ubiContract = ubi
670
780
  ) => {
781
+ const pool = new PromisePool({ concurrency: 50 });
782
+ const step = 1000;
671
783
  const latestBlock = FUSE_SNAPSHOT_BLOCK; //await ubiContract.provider.getBlockNumber();
672
784
  const blocks = range(6400000, latestBlock, step);
673
785
  const filter = ubiContract.filters.UBIClaimed();
674
- for (let blockChunk of chunk(blocks, 10)) {
675
- // Get the filter (the second null could be omitted)
676
- const ps = blockChunk.map(async bc => {
786
+
787
+ blocks.forEach(bc => {
788
+ pool.add(async () => {
789
+ const options = { limit: 20, delay: 2000 };
790
+ const retrier = new Retrier(options);
677
791
  // Query the filter (the latest could be omitted)
678
- const logs = await ubiContract
679
- .queryFilter(filter, bc, Math.min(bc + step - 1, latestBlock))
680
- .catch(e => {
681
- console.log("block ubiclaimed logs failed retrying...", bc);
682
- return ubiContract.queryFilter(
683
- filter,
684
- bc,
685
- Math.min(bc + step - 1, latestBlock)
686
- );
687
- });
792
+ const logs = await retrier.resolve(attempt => {
793
+ console.log("fetching block ubiclaimed logs", { attempt, bc });
794
+
795
+ return ubiContract.queryFilter(
796
+ filter,
797
+ bc,
798
+ Math.min(bc + step - 1, latestBlock)
799
+ );
800
+ });
801
+
688
802
  console.log("found claim logs in block:", { bc }, logs.length);
689
803
  // Print out all the values:
690
804
  logs.map(log => {
@@ -695,8 +809,8 @@ export const airdrop = (
695
809
  });
696
810
  });
697
811
  });
698
- await Promise.all(ps);
699
- }
812
+ });
813
+ await pool.all();
700
814
  return balances;
701
815
  };
702
816
 
@@ -736,25 +850,50 @@ export const airdrop = (
736
850
  });
737
851
  const ps = [];
738
852
 
739
- ps[0] = getFuseSwapBalances(
740
- "https://graph.fuse.io/subgraphs/name/fuseio/fuseswap",
741
- GD_FUSE
742
- ).then(r => fs.writeFileSync("fuseswapBalances.json", JSON.stringify(r)));
743
- ps[1] = getUniswapBalances().then(r =>
744
- fs.writeFileSync("uniswapBalances.json", JSON.stringify(r))
853
+ ps[0] = _timer(
854
+ "getFuseSwapBalances",
855
+ getFuseSwapBalances(
856
+ "https://graph.fuse.io/subgraphs/name/fuseio/fuseswap",
857
+ GD_FUSE
858
+ ).then(r => fs.writeFileSync("fuseswapBalances.json", JSON.stringify(r)))
745
859
  );
746
- ps[2] = getClaimsPerAddress()
747
- .then(r => getClaimsPerAddress(r, ubinew))
748
- .then(r => fs.writeFileSync("claimBalances.json", JSON.stringify(r)));
749
- ps[3] = getEthPlorerHolders().then(r =>
750
- fs.writeFileSync("ethBalances.json", JSON.stringify(r))
860
+ ps[1] = _timer(
861
+ "getUniswapBalances",
862
+ getUniswapBalances().then(r =>
863
+ fs.writeFileSync("uniswapBalances.json", JSON.stringify(r))
864
+ )
865
+ );
866
+ ps[2] = _timer(
867
+ "getClaimsPerAddress",
868
+ getClaimsPerAddress()
869
+ .then(r => getClaimsPerAddress(r, ubinew))
870
+ .then(r => fs.writeFileSync("claimBalances.json", JSON.stringify(r)))
751
871
  );
752
- ps[4] = getBlockScoutHolders().then(r =>
753
- fs.writeFileSync("fuseBalances.json", JSON.stringify(r))
872
+ ps[3] = _timer(
873
+ "getEthPlorerHolders",
874
+ getEthPlorerHolders().then(r =>
875
+ fs.writeFileSync("ethBalances.json", JSON.stringify(r))
876
+ )
877
+ );
878
+ // ps[4] = _timer(
879
+ // "getBlockScoutHolders",
880
+ // getBlockScoutHolders().then(r =>
881
+ // fs.writeFileSync("fuseBalances.json", JSON.stringify(r))
882
+ // ));
883
+ ps[4] = _timer(
884
+ "getFuseHolders",
885
+ getFuseHolders().then(r =>
886
+ fs.writeFileSync("fuseBalances.json", JSON.stringify(r))
887
+ )
754
888
  );
755
- ps[5] = getStakersBalance().then(r =>
756
- fs.writeFileSync("stakersBalances.json", JSON.stringify(r))
889
+
890
+ ps[5] = _timer(
891
+ "getStakersBalance",
892
+ getStakersBalance().then(r =>
893
+ fs.writeFileSync("stakersBalances.json", JSON.stringify(r))
894
+ )
757
895
  );
896
+
758
897
  await Promise.all(ps);
759
898
  };
760
899
 
@@ -821,10 +960,11 @@ export const airdrop = (
821
960
 
822
961
  const sorted = toTree.map(_ => _[1]);
823
962
  fs.writeFileSync("reptree.json", JSON.stringify(toTree));
824
- console.log("Reputation Distribution\nFoundation: 33%");
963
+ console.log("Reputation Distribution");
825
964
  [0.001, 0.01, 0.1, 0.5].forEach(q =>
826
965
  console.log({
827
966
  precentile: q * 100 + "%",
967
+ addresses: (sorted.length * q).toFixed(0),
828
968
  rep:
829
969
  quantile(sorted, q) /
830
970
  (CLAIMER_REP_ALLOCATION +
@@ -834,6 +974,7 @@ export const airdrop = (
834
974
  );
835
975
 
836
976
  const treeData = {};
977
+
837
978
  const elements = toTree.map(e => {
838
979
  const repInWei = (e[1] * 1e18)
839
980
  .toLocaleString("fullwide", {
@@ -853,14 +994,44 @@ export const airdrop = (
853
994
  return Buffer.from(hash.slice(2), "hex");
854
995
  });
855
996
 
997
+ console.log("creating merkletree...", elements.length);
998
+ //NOTICE: we use a non sorted merkletree to save generation time, this requires also a different proof verification algorithm which
999
+ //is not in the default openzeppelin library
1000
+
856
1001
  const merkleTree = new MerkleTree(elements, true);
857
1002
  // get the merkle root
858
1003
  // returns 32 byte buffer
859
1004
  const merkleRoot = merkleTree.getRoot().toString("hex");
860
1005
  // generate merkle proof
861
1006
  // returns array of 32 byte buffers
1007
+
862
1008
  const proof = merkleTree.getProof(elements[0]).map(_ => _.toString("hex"));
863
- console.log({ merkleRoot, proof, sampleProofFor: toTree[50] });
1009
+ const validProof = checkProofOrdered(
1010
+ proof.map(_ => Buffer.from(_, "hex")),
1011
+ merkleTree.getRoot(),
1012
+ elements[0],
1013
+ 1
1014
+ );
1015
+
1016
+ const lastProof = merkleTree
1017
+ .getProof(elements[elements.length - 1])
1018
+ .map(_ => _.toString("hex"));
1019
+ const lastValidProof = checkProofOrdered(
1020
+ lastProof.map(_ => Buffer.from(_, "hex")),
1021
+ merkleTree.getRoot(),
1022
+ elements[elements.length - 1],
1023
+ elements.length
1024
+ );
1025
+
1026
+ console.log({
1027
+ merkleRoot,
1028
+ proof,
1029
+ validProof,
1030
+ lastProof,
1031
+ lastValidProof,
1032
+ proofFor: toTree[0],
1033
+ lastProofFor: toTree[toTree.length - 1]
1034
+ });
864
1035
  fs.writeFileSync("airdrop.json", JSON.stringify({ treeData, merkleRoot }));
865
1036
  };
866
1037
 
@@ -869,16 +1040,39 @@ export const airdrop = (
869
1040
  fs.readFileSync("airdrop.json").toString()
870
1041
  );
871
1042
 
872
- const elements = Object.entries(treeData as Tree).map(e =>
873
- Buffer.from(e[1].hash.slice(2), "hex")
874
- );
1043
+ let entries = Object.entries(treeData as Tree);
1044
+ let elements = entries.map(e => Buffer.from(e[1].hash.slice(2), "hex"));
875
1045
 
1046
+ console.log("creating merkletree...", elements.length);
876
1047
  const merkleTree = new MerkleTree(elements, true);
877
- const proof = merkleTree
878
- .getProof(Buffer.from(treeData[addr].hash.slice(2), "hex"))
879
- .map(_ => "0x" + _.toString("hex"));
880
- console.log({ proof, [addr]: treeData[addr] });
1048
+
1049
+ const calcMerkleRoot = merkleTree.getRoot().toString("hex");
1050
+ console.log("merkleroots:", {
1051
+ fromFile: merkleRoot,
1052
+ calculated: calcMerkleRoot
1053
+ });
1054
+
1055
+ const addrData = treeData[addr];
1056
+ const proofFor = Buffer.from(addrData.hash.slice(2), "hex");
1057
+
1058
+ const proof = merkleTree.getProof(proofFor);
1059
+ const proofIndex = entries.findIndex(_ => _[1].hash === addrData.hash) + 1;
1060
+
1061
+ console.log(
1062
+ "checkProof:",
1063
+ checkProofOrdered(proof, merkleTree.getRoot(), proofFor, proofIndex)
1064
+ );
1065
+ const hexProof = proof.map(_ => "0x" + _.toString("hex"));
1066
+ console.log({ proofIndex, proof: hexProof, [addr]: treeData[addr] });
881
1067
  };
882
1068
 
883
1069
  return { buildMerkleTree, collectAirdropData, getProof };
884
1070
  };
1071
+
1072
+ const _timer = async (name, promise) => {
1073
+ const start = Date.now();
1074
+ const res = await promise;
1075
+ const milis = Date.now() - start;
1076
+ console.log(`done task ${name} in ${milis / 1000} seconds`);
1077
+ return res;
1078
+ };