@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.
- package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/Controller.json +19 -0
- package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IGoodDollar.json +13 -0
- package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
- package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
- package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.json +2 -2
- package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
- package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.json +2 -2
- package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
- package/artifacts/contracts/governance/GReputation.sol/GReputation.json +41 -2
- package/artifacts/contracts/governance/GovarnanceStaking.sol/GovernanceStaking.dbg.json +1 -1
- package/artifacts/contracts/governance/GovarnanceStaking.sol/GovernanceStaking.json +2 -2
- package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
- package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
- package/artifacts/contracts/governance/Reputation.sol/Reputation.json +2 -2
- package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
- package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.json +2 -2
- package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.json +2 -2
- package/artifacts/contracts/mocks/AaveUSDMockOracle.sol/AaveUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/BatUSDMockOracle.sol/BatUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/CompUsdMockOracle.sol/CompUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/DaiEthPriceMockOracle.sol/DaiEthPriceMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.json +2 -2
- package/artifacts/contracts/mocks/EthUSDMockOracle.sol/EthUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/GasPriceMockOracle.sol/GasPriceMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.json +4 -4
- package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.json +37 -11
- package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.json +2 -2
- package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.json +2 -2
- package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
- package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.json +2 -2
- package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
- package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.json +2 -2
- package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.json +2 -2
- package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.json +2 -2
- package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
- package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
- package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.json +2 -2
- package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
- package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.json +2 -2
- package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
- package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
- package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.json +2 -2
- package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
- package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.json +2 -2
- package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.json +2 -2
- package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
- package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.json +37 -11
- package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
- package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.json +2 -2
- package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
- package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.json +3 -3
- package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.json +4 -4
- package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
- package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.json +4 -4
- package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.json +6 -6
- package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
- package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.json +2 -2
- package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
- package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
- package/artifacts/contracts/utils/DAOContract.sol/DAOContract.json +2 -2
- package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
- package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.json +2 -2
- package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
- package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
- package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
- package/artifacts/contracts/utils/NameService.sol/NameService.json +2 -2
- package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.json +12 -2
- package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.json +2 -2
- package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
- package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.json +2 -2
- package/contracts/DAOStackInterfaces.sol +2 -0
- package/contracts/Interfaces.sol +2 -0
- package/contracts/governance/CompoundVotingMachine.sol +1 -1
- package/contracts/governance/GReputation.sol +70 -40
- package/contracts/staking/GoodFundManager.sol +41 -40
- package/contracts/utils/ProtocolUpgrade.sol +56 -5
- package/contracts/utils/ProtocolUpgradeFuse.sol +28 -6
- package/package.json +3 -2
- package/releases/deployment.json +1 -1
- package/releases/olddao.json +1 -1
- package/scripts/governance/README.md +70 -0
- package/scripts/governance/airdropCalculation.ts +264 -70
- package/scripts/upgradeToV2/upgradeToV2.ts +132 -124
- package/test/governance/GReputation.test.ts +145 -86
- package/test/localOldDaoDeploy.ts +5 -0
- package/test/staking/DifferentStakingTokens.test.ts +11 -10
- package/test/staking/SimpleDAIStaking.test.ts +37 -40
- package/test/staking/StakingRewards.test.ts +57 -65
- package/test/staking/SwapHelper.test.ts +17 -21
- package/test/staking/UsdcAaveStaking.test.ts +12 -12
- package/test/utils/ProtocolUpgrade.test.ts +70 -6
- 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
|
|
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
|
|
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
|
|
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
|
-
|
|
142
|
+
fuseProvider
|
|
137
143
|
);
|
|
138
144
|
const ubinew = new ethers.Contract(
|
|
139
145
|
"0xD7aC544F8A570C4d8764c3AAbCF6870CBD960D0D",
|
|
140
146
|
["event UBIClaimed(address indexed from, uint amount)"],
|
|
141
|
-
|
|
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
|
|
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
|
|
663
|
+
(await gdNonArchive.provider.getCode(b[0]).catch(e => "0x")) ===
|
|
664
|
+
"0x"
|
|
564
665
|
);
|
|
565
|
-
const cleanBalance = await
|
|
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
|
-
|
|
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
|
-
|
|
700
|
+
toFetch = toFetch.concat(foundBalances);
|
|
701
|
+
// await fetchBalances(foundBalances);
|
|
600
702
|
}
|
|
601
|
-
console.log("fetched:", {
|
|
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
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
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
|
-
|
|
675
|
-
|
|
676
|
-
|
|
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
|
|
679
|
-
.
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
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
|
-
|
|
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] =
|
|
740
|
-
"
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
fs.writeFileSync("
|
|
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[
|
|
747
|
-
|
|
748
|
-
.then(r =>
|
|
749
|
-
|
|
750
|
-
|
|
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[
|
|
753
|
-
|
|
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
|
-
|
|
756
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
873
|
-
|
|
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
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
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
|
+
};
|