@gooddollar/goodprotocol 1.0.15 → 1.0.16

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 (115) 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/GlobalConstraintInterface.dbg.json +1 -1
  4. package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
  5. package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
  6. package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
  7. package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
  8. package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
  9. package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
  10. package/artifacts/contracts/Interfaces.sol/IAdminWallet.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/IGoodStaking.dbg.json +1 -1
  16. package/artifacts/contracts/Interfaces.sol/IHasRouter.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/GReputation.sol/GReputation.dbg.json +1 -1
  32. package/artifacts/contracts/governance/GReputation.sol/GReputation.json +3 -10
  33. package/artifacts/contracts/governance/GovernanceStaking.sol/GovernanceStaking.dbg.json +1 -1
  34. package/artifacts/contracts/governance/GovernanceStaking.sol/GovernanceStaking.json +41 -3
  35. package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
  36. package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
  37. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
  38. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.json +2 -2
  39. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
  40. package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
  41. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
  42. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
  43. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.json +2 -2
  44. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
  45. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
  46. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
  47. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
  48. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.json +2 -2
  49. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
  50. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.json +2 -2
  51. package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
  52. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
  53. package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
  54. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.dbg.json +1 -1
  55. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.dbg.json +1 -1
  56. package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
  57. package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
  58. package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
  59. package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
  60. package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
  61. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
  62. package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
  63. package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
  64. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
  65. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
  66. package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
  67. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
  68. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
  69. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.dbg.json +1 -1
  70. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
  71. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.json +2 -2
  72. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
  73. package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
  74. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.dbg.json +1 -1
  75. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
  76. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
  77. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.json +2 -2
  78. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
  79. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.json +2 -2
  80. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.dbg.json +1 -1
  81. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.json +2 -2
  82. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
  83. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.json +2 -2
  84. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
  85. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.json +2 -2
  86. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.dbg.json +1 -1
  87. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.json +2 -2
  88. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
  89. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.json +2 -2
  90. package/artifacts/contracts/unaudited-foundation/FuseFaucet.sol/FuseFaucet.dbg.json +1 -1
  91. package/artifacts/contracts/unaudited-foundation/InvitesV1.sol/InvitesV1.dbg.json +1 -1
  92. package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
  93. package/artifacts/contracts/utils/BulkProof.sol/BulkProof.dbg.json +4 -0
  94. package/artifacts/contracts/utils/BulkProof.sol/BulkProof.json +41 -0
  95. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
  96. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
  97. package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
  98. package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
  99. package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
  100. package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
  101. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
  102. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
  103. package/artifacts/contracts/utils/ProtocolUpgradeFuseRecover.sol/ProtocolUpgradeFuseRecover.dbg.json +1 -1
  104. package/artifacts/contracts/utils/ProtocolUpgradeRecover.sol/ProtocolUpgradeRecover.dbg.json +1 -1
  105. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
  106. package/contracts/governance/GReputation.sol +10 -31
  107. package/contracts/governance/GovernanceStaking.sol +15 -2
  108. package/contracts/utils/BulkProof.sol +45 -0
  109. package/hardhat.config.ts +41 -1
  110. package/package.json +1 -1
  111. package/releases/deployment.json +1 -1
  112. package/scripts/bulkProof.ts +207 -0
  113. package/scripts/gdx/gdxAirdropCalculation.ts +223 -0
  114. package/scripts/governance/airdropCalculationRecover.ts +406 -0
  115. package/test/governance/GReputation.test.ts +16 -3
@@ -0,0 +1,406 @@
1
+ import { get, range, chunk, flatten, mergeWith, sortBy, uniq } from "lodash";
2
+ import fs from "fs";
3
+ import MerkleTree, {
4
+ checkProof,
5
+ checkProofOrdered
6
+ } from "merkle-tree-solidity";
7
+ import coreContracts from "@gooddollar/goodcontracts/releases/deployment.json";
8
+ import stakingContracts from "@gooddollar/goodcontracts/stakingModel/releases/deployment.json";
9
+ import upgradablesContracts from "@gooddollar/goodcontracts/upgradables/releases/deployment.json";
10
+ import { ethers as Ethers } from "hardhat";
11
+ import { BigNumber } from "ethers";
12
+ type Balances = {
13
+ [key: string]: {
14
+ isNotContract: boolean;
15
+ balance: number;
16
+ claims: number;
17
+ stake: number;
18
+ gdRepShare: number;
19
+ claimRepShare: number;
20
+ stakeRepShare: number;
21
+ };
22
+ };
23
+
24
+ type Tree = {
25
+ [key: string]: {
26
+ hash: string;
27
+ rep: number;
28
+ };
29
+ };
30
+ const DefaultBalance = {
31
+ balance: 0,
32
+ claims: 0,
33
+ gdRepShare: 0,
34
+ claimRepShare: 0,
35
+ stake: 0,
36
+ stakeRepShare: 0,
37
+ isNotContract: true
38
+ };
39
+ const otherContracts = [
40
+ "0x8d441C2Ff54C015A1BE22ad88e5D42EFBEC6C7EF", //fuseswap
41
+ "0x0bf36731724f0baceb0748a9e71cd4883b69c533", //fuseswap usdc
42
+ "0x17b09b22823f00bb9b8ee2d4632e332cadc29458", //old bridge
43
+ "0xd5d11ee582c8931f336fbcd135e98cee4db8ccb0", //new bridge
44
+ "0xa56A281cD8BA5C083Af121193B2AaCCaAAC9850a", //mainnet uniswap
45
+ "0x66c0f5449ba4ff4fba0b05716705a4176bbdb848", //defender automation
46
+ "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" //"uniswap DAI"
47
+ ];
48
+
49
+ const systemContracts = {};
50
+ const allContracts = flatten(
51
+ [coreContracts, stakingContracts, upgradablesContracts].map(_ =>
52
+ Object.values(_).map(_ => Object.values(_))
53
+ )
54
+ );
55
+ flatten(
56
+ [].concat(
57
+ ...[otherContracts, allContracts]
58
+ .map(Object.values)
59
+ .map(arr => arr.map(x => (typeof x === "object" ? Object.values(x) : x)))
60
+ )
61
+ )
62
+ .filter(x => typeof x === "string" && x.startsWith("0x"))
63
+ .map(addr => (systemContracts[addr.toLowerCase()] = true));
64
+
65
+ const isSystemContract = addr => systemContracts[addr.toLowerCase()] === true;
66
+
67
+ const updateBalance = (balance, update) => {
68
+ return Object.assign({}, DefaultBalance, balance, update);
69
+ };
70
+
71
+ const quantile = (sorted, q) => {
72
+ const pos = (sorted.length - 1) * q;
73
+ const base = Math.floor(pos);
74
+
75
+ let sum = 0;
76
+ for (let i = 0; i < base; i++) sum += sorted[i];
77
+
78
+ return sum;
79
+ };
80
+
81
+ export const airdrop = (
82
+ ethers: typeof Ethers,
83
+ ethplorer_key,
84
+ etherscan_key
85
+ ) => {
86
+ const fusePoktProvider = new ethers.providers.JsonRpcProvider({
87
+ url: "https://fuse-mainnet.gateway.pokt.network/v1/lb/60ee374fc6318362996a1fb0",
88
+ user: "",
89
+ password: "d57939c260bdf0a6f22550e2350b4312" //end point will be removed, so its ok to keep clear text password
90
+ });
91
+
92
+ const fuseProvider = new ethers.providers.JsonRpcProvider(
93
+ "https://rpc.fuse.io"
94
+ );
95
+
96
+ const fuseGDProvider = new ethers.providers.JsonRpcProvider(
97
+ "https://gooddollar-rpc.fuse.io"
98
+ );
99
+ const fuseArchiveProvider = new ethers.providers.JsonRpcBatchProvider(
100
+ "https://explorer-node.fuse.io/"
101
+ );
102
+
103
+ const poktArchiveProvider = new ethers.providers.JsonRpcProvider({
104
+ url: "https://eth-trace.gateway.pokt.network/v1/lb/6130bad2dc57c50036551041",
105
+ user: "",
106
+ password: "15439e4f4aeceb469b6b38e319f4f2a5" //end point will be removed, so its ok to keep clear text password
107
+ });
108
+
109
+ console.log({ systemContracts });
110
+
111
+ const LAST_BLOCK_ETH = 14296865;
112
+ const LAST_BLOCK_FUSE = 14296865;
113
+ const START_BLOCK_FUSE = 14149729;
114
+ const START_BLOCK_ETH = 13683492;
115
+
116
+ const collectAirdropData = async () => {
117
+ const goodMainnet = await ethers
118
+ .getContractAt(
119
+ "GReputation",
120
+ "0x3A9299BE789ac3730e4E4c49d6d2Ad1b8BC34DFf"
121
+ )
122
+ .then(_ => _.connect(new ethers.providers.InfuraProvider()));
123
+
124
+ const goodFuse = await ethers
125
+ .getContractAt(
126
+ "GReputation",
127
+ "0x3A9299BE789ac3730e4E4c49d6d2Ad1b8BC34DFf"
128
+ )
129
+ .then(_ => _.connect(fuseGDProvider));
130
+
131
+ console.log({
132
+ LAST_BLOCK_ETH,
133
+ LAST_BLOCK_FUSE
134
+ });
135
+ const calcGoodMints = async (runForFuse = true) => {
136
+ const step = 10000;
137
+ const START_BLOCK = runForFuse ? START_BLOCK_FUSE : START_BLOCK_ETH;
138
+
139
+ const good = runForFuse ? goodFuse : goodMainnet;
140
+ const LAST_BLOCK = await good.provider.getBlockNumber();
141
+ const blocks = range(START_BLOCK, LAST_BLOCK, step);
142
+ const allLogs = [];
143
+ for (let blockChunk of chunk(blocks, 10)) {
144
+ // Get the filter (the second null could be omitted)
145
+ const ps = blockChunk.map(async (bc: number) => {
146
+ const logs = await good
147
+ .queryFilter(
148
+ good.filters.Mint(),
149
+ bc,
150
+ Math.min(bc + step - 1, LAST_BLOCK)
151
+ )
152
+ .catch(e => {
153
+ console.log("block transfer logs failed retrying...", bc);
154
+ return good.queryFilter(
155
+ good.filters.Mint(),
156
+ bc,
157
+ Math.min(bc + step - 1, LAST_BLOCK)
158
+ );
159
+ });
160
+ const claimedLogs = await good
161
+ .queryFilter(
162
+ good.filters.StateHashProof(),
163
+ bc,
164
+ Math.min(bc + step - 1, LAST_BLOCK)
165
+ )
166
+ .catch(e => {
167
+ console.log("block transfer logs failed retrying...", bc);
168
+ return good.queryFilter(
169
+ good.filters.StateHashProof(),
170
+ bc,
171
+ Math.min(bc + step - 1, LAST_BLOCK)
172
+ );
173
+ });
174
+ console.log("found logs:", claimedLogs.length, logs.length, bc);
175
+ return logs.concat(claimedLogs);
176
+ });
177
+ let chunkLogs = flatten(await Promise.all(ps));
178
+ console.log("chunk logs: ", chunkLogs.length, { blockChunk });
179
+ allLogs.push(chunkLogs);
180
+ }
181
+ const logs = flatten(allLogs);
182
+
183
+ const balances: { [key: string]: BigNumber } = {};
184
+ const result = [];
185
+ if (runForFuse) {
186
+ logs.forEach(l => {
187
+ if (l.event === "Mint")
188
+ balances[l.args._to.toLowerCase()] = (
189
+ balances[l.args._to.toLowerCase()] || BigNumber.from("0")
190
+ ).add(l.args._amount);
191
+ else
192
+ balances[l.args.user.toLowerCase()] = (
193
+ balances[l.args.user.toLowerCase()] || BigNumber.from("0")
194
+ ).sub(l.args.repBalance);
195
+ });
196
+ Object.entries(balances).forEach(
197
+ ([k, v]) => {
198
+ if (v.gt(0)) result.push([k, v.toString()]);
199
+ }
200
+ // console.log(k, v.toString())
201
+ );
202
+ console.log(
203
+ "total balances found:",
204
+ Object.entries(balances).length,
205
+ "to update balances:",
206
+ result.length
207
+ );
208
+ fs.writeFileSync("airdrop/repRecoverFuse.json", JSON.stringify(result));
209
+ } else {
210
+ const mints = {};
211
+ const claims = {};
212
+ const result = {};
213
+ console.log("logs found:", logs.length);
214
+ let totalMints = ethers.constants.Zero;
215
+ logs.forEach(l => {
216
+ if (l.event === "Mint") {
217
+ mints[l.args._to.toLowerCase()] = (
218
+ mints[l.args._to.toLowerCase()] || BigNumber.from("0")
219
+ ).add(l.args._amount);
220
+ totalMints = totalMints.add(l.args._amount);
221
+ } else
222
+ claims[l.args.user.toLowerCase()] = l.args.repBalance.toString();
223
+ });
224
+ Object.entries(mints).forEach(
225
+ ([k, v]) =>
226
+ (result[k] = { claim: "0", ...result[k], mint: v.toString() })
227
+ );
228
+ Object.entries(claims).forEach(
229
+ ([k, v]) =>
230
+ (result[k] = { mint: "0", ...result[k], claim: v.toString() })
231
+ );
232
+ console.log({ result, totalMints: totalMints.toString() });
233
+ fs.writeFileSync(
234
+ "airdrop/repRecoverMainnet.json",
235
+ JSON.stringify(result)
236
+ );
237
+ }
238
+ };
239
+
240
+ await Promise.all([calcGoodMints(), calcGoodMints(false)]);
241
+ };
242
+
243
+ const buildMerkleTree = () => {
244
+ const { treeData } = JSON.parse(
245
+ fs.readFileSync("airdrop/airdrop.first.json").toString()
246
+ );
247
+ const fuseMints = JSON.parse(
248
+ fs.readFileSync("airdrop/repRecoverFuse.json").toString()
249
+ );
250
+
251
+ const mainnetMints = JSON.parse(
252
+ fs.readFileSync("airdrop/repRecoverMainnet.json").toString()
253
+ );
254
+
255
+ fuseMints.forEach(([addr, v]) => {
256
+ const rep = BigNumber.from(v);
257
+ const repInWei = BigNumber.from(
258
+ treeData[addr.toLowerCase()]?.rep || "0"
259
+ ).add(rep);
260
+ const hash = ethers.utils.keccak256(
261
+ ethers.utils.defaultAbiCoder.encode(
262
+ ["address", "uint256"],
263
+ [addr, repInWei.toString()]
264
+ )
265
+ );
266
+ treeData[addr.toLowerCase()] = {
267
+ ...treeData[addr.toLowerCase()],
268
+ rep: repInWei,
269
+ hash
270
+ };
271
+ });
272
+
273
+ const ethRestore = Object.entries(mainnetMints).map(
274
+ ([k, v]: [string, any]) => {
275
+ return [
276
+ k.toLowerCase(),
277
+ BigNumber.from(treeData[k.toLowerCase()]?.rep || "0").toString(),
278
+ v.mint
279
+ ];
280
+ }
281
+ );
282
+ fs.writeFileSync(
283
+ "airdrop/ethAirdropRecover.json",
284
+ JSON.stringify({
285
+ accounts: ethRestore.map(_ => _[0]),
286
+ stateValue: ethRestore.map(_ => _[1]),
287
+ mintValue: ethRestore.map(_ => _[2])
288
+ })
289
+ );
290
+ let toTree: Array<[string, BigNumber]> = Object.entries(treeData).map(
291
+ ([k, v]) => {
292
+ return [k, BigNumber.from((v as any).rep)];
293
+ }
294
+ );
295
+ toTree = toTree.sort((a, b) => (a[1].gte(b[1]) ? 1 : -1));
296
+ // console.log({ toTree });
297
+ // const topContracts = toTree.filter(_ => _[2] === true);
298
+ const totalReputationAirdrop = toTree
299
+ .reduce((c, a) => c.add(a[1]), BigNumber.from(0))
300
+ .toString();
301
+ console.log({
302
+ totalReputationAirdrop,
303
+ numberOfAccounts: toTree.length
304
+ });
305
+ // const sorted = toTree.map(_ => _[1]);
306
+ console.log(toTree.slice(0, 100).map(_ => [_[0], _[1].toString()]));
307
+ // fs.writeFileSync(`${folder}/reptree.json`, JSON.stringify(toTree));
308
+ // console.log("Reputation Distribution");
309
+ // [0.001, 0.01, 0.1, 0.5].forEach(q =>
310
+ // console.log({
311
+ // precentile: q * 100 + "%",
312
+ // addresses: (sorted.length * q).toFixed(0),
313
+ // rep:
314
+ // quantile(sorted, q) /
315
+ // (CLAIMER_REP_ALLOCATION +
316
+ // HOLDER_REP_ALLOCATION +
317
+ // STAKER_REP_ALLOCATION)
318
+ // })
319
+ // );
320
+ const elements = Object.values(treeData).map((e: any) =>
321
+ Buffer.from(e.hash.slice(2), "hex")
322
+ );
323
+ console.log("creating merkletree...", elements.length);
324
+ //NOTICE: we use a non sorted merkletree to save generation time, this requires also a different proof verification algorithm which
325
+ //is not in the default openzeppelin library
326
+ const merkleTree = new MerkleTree(elements, true);
327
+ // get the merkle root
328
+ // returns 32 byte buffer
329
+ const merkleRoot = merkleTree.getRoot().toString("hex");
330
+ // generate merkle proof
331
+ // returns array of 32 byte buffers
332
+ const proof = merkleTree.getProof(elements[0]).map(_ => _.toString("hex"));
333
+ const validProof = checkProofOrdered(
334
+ proof.map(_ => Buffer.from(_, "hex")),
335
+ merkleTree.getRoot(),
336
+ elements[0],
337
+ 1
338
+ );
339
+ const lastProof = merkleTree
340
+ .getProof(elements[elements.length - 1])
341
+ .map(_ => _.toString("hex"));
342
+ const lastValidProof = checkProofOrdered(
343
+ lastProof.map(_ => Buffer.from(_, "hex")),
344
+ merkleTree.getRoot(),
345
+ elements[elements.length - 1],
346
+ elements.length
347
+ );
348
+ console.log({
349
+ merkleRoot,
350
+ proof,
351
+ validProof,
352
+ lastProof,
353
+ lastValidProof,
354
+ proofFor: toTree[0],
355
+ lastProofFor: toTree[toTree.length - 1]
356
+ });
357
+ fs.writeFileSync(
358
+ `airdrop/airdrop.json`,
359
+ JSON.stringify({
360
+ treeData,
361
+ merkleRoot
362
+ })
363
+ );
364
+ };
365
+
366
+ const getProof = addr => {
367
+ const { treeData, merkleRoot } = JSON.parse(
368
+ fs.readFileSync("airdrop/airdrop.json").toString()
369
+ );
370
+
371
+ let entries = Object.entries(treeData as Tree);
372
+ let elements = entries.map(e => Buffer.from(e[1].hash.slice(2), "hex"));
373
+
374
+ console.log("creating merkletree...", elements.length);
375
+ const merkleTree = new MerkleTree(elements, true);
376
+
377
+ const calcMerkleRoot = merkleTree.getRoot().toString("hex");
378
+ console.log("merkleroots:", {
379
+ fromFile: merkleRoot,
380
+ calculated: calcMerkleRoot
381
+ });
382
+
383
+ const addrData = treeData[addr] || treeData[addr.toLowerCase()];
384
+ const proofFor = Buffer.from(addrData.hash.slice(2), "hex");
385
+
386
+ const proof = merkleTree.getProof(proofFor);
387
+ const proofIndex = entries.findIndex(_ => _[1].hash === addrData.hash) + 1;
388
+
389
+ console.log(
390
+ "checkProof:",
391
+ checkProofOrdered(proof, merkleTree.getRoot(), proofFor, proofIndex)
392
+ );
393
+ const hexProof = proof.map(_ => "0x" + _.toString("hex"));
394
+ console.log({ proofIndex, proof: hexProof, [addr]: addrData });
395
+ };
396
+
397
+ return { buildMerkleTree, collectAirdropData, getProof };
398
+ };
399
+
400
+ const _timer = async (name, promise) => {
401
+ const start = Date.now();
402
+ const res = await promise;
403
+ const milis = Date.now() - start;
404
+ console.log(`done task ${name} in ${milis / 1000} seconds`);
405
+ return res;
406
+ };
@@ -156,10 +156,10 @@ describe("GReputation", () => {
156
156
  expect(rootState[0]).to.be.equal("0x" + merkleRoot.toString("hex"));
157
157
  });
158
158
  it("rootState should not change totalsupply until proof", async () => {
159
- expect(await grep.totalSupply()).to.equal(0);
159
+ expect(await grep.totalSupply()).to.equal(100);
160
160
  });
161
161
 
162
- it("should update core balances after proof", async () => {
162
+ it("should update core balances and not change totalsupply after proof of rootState", async () => {
163
163
  await grep.proveBalanceOfAtBlockchain("rootState", rep1, 1, proof, 1);
164
164
 
165
165
  //root states changes the core balance
@@ -168,7 +168,7 @@ describe("GReputation", () => {
168
168
 
169
169
  const newVotes = await grep.getVotes(rep1);
170
170
  expect(newVotes.toNumber()).to.be.equal(1);
171
- expect(await grep.totalSupply()).to.equal(1);
171
+ expect(await grep.totalSupply()).to.equal(100); //total supply shouldnt change by proof
172
172
  });
173
173
  it("should not set rootState again", async () => {
174
174
  await setDAOAddress("GDAO_CLAIMERS", repOwner);
@@ -610,6 +610,10 @@ describe("GReputation", () => {
610
610
  });
611
611
 
612
612
  describe("real example of airdrop", async () => {
613
+ let startSupply = ethers.constants.Zero;
614
+ before(async () => {
615
+ startSupply = await grep.totalSupply();
616
+ });
613
617
  it("should set a new state hash", async () => {
614
618
  let encodedCall = grep.interface.encodeFunctionData(
615
619
  "setBlockchainStateHash",
@@ -621,6 +625,9 @@ describe("GReputation", () => {
621
625
  );
622
626
 
623
627
  expect(await avatarGenericCall(grep.address, encodedCall)).to.not.throw;
628
+ expect(await grep.totalSupply()).to.eq(
629
+ startSupply.add(ethers.utils.parseEther("96000000"))
630
+ );
624
631
  });
625
632
 
626
633
  it("should prove real proof", async () => {
@@ -658,6 +665,9 @@ describe("GReputation", () => {
658
665
  expect(
659
666
  await grep.getVotes("0xf79b804bae955ae4cd8e8b0331c4bc437104804f")
660
667
  ).to.be.eq(prevVotes.add(rep)); //add new blockchain rep
668
+ expect(await grep.totalSupply()).to.eq(
669
+ startSupply.add(ethers.utils.parseEther("96000000"))
670
+ );
661
671
  });
662
672
 
663
673
  it("should prove real proof of last index", async () => {
@@ -690,6 +700,9 @@ describe("GReputation", () => {
690
700
  expect(
691
701
  await grep.getVotes("0x68b064891efb77b87fe1e872205e795f75a72a6d")
692
702
  ).to.be.eq(prevVotes.add(rep)); //add new blockchain rep
703
+ expect(await grep.totalSupply()).to.eq(
704
+ startSupply.add(ethers.utils.parseEther("96000000"))
705
+ );
693
706
  });
694
707
 
695
708
  it("it should be able get votes at the specific block", async () => {