@gooddollar/goodprotocol 1.0.17 → 1.0.18-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/hardhat.config.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
airdrop as gdxAirdrop,
|
|
19
19
|
airdropRecover as gdxAirdropRecover
|
|
20
20
|
} from "./scripts/gdx/gdxAirdropCalculation";
|
|
21
|
+
import { sumStakersGdRewards } from "./scripts/staking/stakersGdRewardsCalculation";
|
|
21
22
|
import { verify } from "./scripts/verify";
|
|
22
23
|
import { ethers } from "ethers";
|
|
23
24
|
config();
|
|
@@ -223,8 +224,6 @@ task("gdxAirdrop", "Calculates airdrop data")
|
|
|
223
224
|
|
|
224
225
|
task("gdxAirdropRecover", "Calculates new airdrop data for recovery")
|
|
225
226
|
.addParam("action", "addition/tree")
|
|
226
|
-
.addOptionalPositionalParam("address", "proof for address")
|
|
227
|
-
.addOptionalParam("ethsnapshotblock", "eth block for calculate")
|
|
228
227
|
.setAction(async (taskArgs, hre) => {
|
|
229
228
|
const actions = gdxAirdropRecover(hre.ethers);
|
|
230
229
|
switch (taskArgs.action) {
|
|
@@ -243,3 +242,10 @@ task("verifyjson", "verify contracts on etherscan").setAction(
|
|
|
243
242
|
}
|
|
244
243
|
);
|
|
245
244
|
export default hhconfig;
|
|
245
|
+
|
|
246
|
+
task("sumStakersGdRewards", "Sums the GoodDollar reward for each staker")
|
|
247
|
+
.setAction(async (taskArgs, hre) => {
|
|
248
|
+
const actions = sumStakersGdRewards(hre.ethers);
|
|
249
|
+
return actions.getStakersGdRewards();
|
|
250
|
+
}
|
|
251
|
+
);
|
package/package.json
CHANGED
package/releases/deployment.json
CHANGED
|
@@ -463,6 +463,7 @@
|
|
|
463
463
|
"StakersDistribution": "0x5766cf4b2fdb09d986eb1783d276013c224e28c8",
|
|
464
464
|
"GoodFundManager": "0x0c6c80d2061afa35e160f3799411d83bdeea0a5a",
|
|
465
465
|
"GReputation": "0x603b8c0f110e037b51a381cbcacabb8d6c6e4543",
|
|
466
|
+
"CompoundVotingMachine": "0x57ee6ceff51cb30ecb1245934a882c500fbec1e9",
|
|
466
467
|
"ProtocolUpgradeRecover": "0x6f1b4dFDd7156FC5752541Ef35EDF57B48E74475",
|
|
467
468
|
"network": "production-mainnet",
|
|
468
469
|
"networkId": 1,
|
|
@@ -502,8 +503,7 @@
|
|
|
502
503
|
"0x3ff2d8eb2573819a9ef7167d2ba6fd6d31b17f4f",
|
|
503
504
|
6944
|
|
504
505
|
]
|
|
505
|
-
]
|
|
506
|
-
"CompoundVotingMachine": "0xc2Ff55b896e3c42f9e1c2f7467C51b93F1C23dFD"
|
|
506
|
+
]
|
|
507
507
|
},
|
|
508
508
|
"production": {
|
|
509
509
|
"NameService": "0xec6dcE387B1616a0c44fF2E4fA9E90E53Cf14eb0",
|
|
@@ -25,9 +25,9 @@ const quantile = (sorted, q) => {
|
|
|
25
25
|
const quantileBN = (sorted, q) => {
|
|
26
26
|
const pos = (sorted.length - 1) * q;
|
|
27
27
|
const base = Math.floor(pos);
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
let sum = BigNumber.from("0");
|
|
30
|
-
for (let i = 0; i < base; i++)
|
|
30
|
+
for (let i = 0; i < base; i++)
|
|
31
31
|
sum = BigNumber.from(sum).add(BigNumber.from(sorted[i]));
|
|
32
32
|
|
|
33
33
|
return sum.toString();
|
|
@@ -212,35 +212,54 @@ export const airdrop = (ethers: typeof Ethers, ethSnapshotBlock) => {
|
|
|
212
212
|
};
|
|
213
213
|
|
|
214
214
|
export const airdropRecover = (ethers: typeof Ethers) => {
|
|
215
|
-
|
|
216
215
|
const ZERO = ethers.BigNumber.from("0");
|
|
217
216
|
|
|
218
|
-
const getHoldersInformation = async (
|
|
217
|
+
const getHoldersInformation = async (
|
|
218
|
+
newAddresses = {},
|
|
219
|
+
newIsContracts = {}
|
|
220
|
+
) => {
|
|
219
221
|
const provider = new ethers.providers.InfuraProvider();
|
|
220
222
|
|
|
221
|
-
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
|
|
223
|
+
let newReserve = await ethers.getContractAt(
|
|
224
|
+
"GoodReserveCDai",
|
|
225
|
+
"0x6C35677206ae7FF1bf753877649cF57cC30D1c42"
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
let recoveredReserve = await ethers.getContractAt(
|
|
229
|
+
"GoodReserveCDai",
|
|
230
|
+
"0xa150a825d425B36329D8294eeF8bD0fE68f8F6E0"
|
|
231
|
+
);
|
|
225
232
|
|
|
226
|
-
let
|
|
227
|
-
|
|
233
|
+
// let exchangeHelper = await ethers.getContractAt(
|
|
234
|
+
// eventsABI,
|
|
235
|
+
// "0x0a8c6bB832801454F6CC21761D0A293Caa003296"
|
|
236
|
+
// );
|
|
228
237
|
|
|
229
|
-
exchangeHelper = exchangeHelper.connect(provider);
|
|
238
|
+
// exchangeHelper = exchangeHelper.connect(provider);
|
|
230
239
|
newReserve = newReserve.connect(provider);
|
|
231
240
|
|
|
232
241
|
const step = 100000;
|
|
233
242
|
const START_BLOCK = 13683748; // Reserve was created
|
|
234
|
-
const END_BLOCK = 14296271;
|
|
243
|
+
// const END_BLOCK = 14296271; // Following reserve created
|
|
244
|
+
const END_BLOCK = await ethers.provider.getBlockNumber();
|
|
235
245
|
const blocks = range(START_BLOCK, END_BLOCK, step);
|
|
236
246
|
|
|
237
|
-
const reserveTokenPurchasedFilter = newReserve.filters.
|
|
238
|
-
|
|
247
|
+
const reserveTokenPurchasedFilter = newReserve.filters.Transfer(
|
|
248
|
+
ethers.constants.AddressZero
|
|
249
|
+
);
|
|
250
|
+
const reserveTokenSoldFilter = newReserve.filters.Transfer(
|
|
251
|
+
undefined,
|
|
252
|
+
ethers.constants.AddressZero
|
|
253
|
+
);
|
|
239
254
|
|
|
240
|
-
const exchangeHelperTokenPurchasedFilter = exchangeHelper.filters.TokenPurchased();
|
|
241
|
-
const exchangeHelperTokenSoldFilter = exchangeHelper.filters.TokenSold();
|
|
255
|
+
// const exchangeHelperTokenPurchasedFilter = exchangeHelper.filters.TokenPurchased();
|
|
256
|
+
// const exchangeHelperTokenSoldFilter = exchangeHelper.filters.TokenSold();
|
|
242
257
|
|
|
243
|
-
const populateListOfAddressesAndBalances = async (
|
|
258
|
+
const populateListOfAddressesAndBalances = async (
|
|
259
|
+
contractInstance,
|
|
260
|
+
purchaseFilter,
|
|
261
|
+
soldFilter
|
|
262
|
+
) => {
|
|
244
263
|
for (let blockChunk of chunk(blocks, 10)) {
|
|
245
264
|
// Get the filter (the second null could be omitted)
|
|
246
265
|
const processedChunks = blockChunk.map(async bc => {
|
|
@@ -256,7 +275,7 @@ export const airdropRecover = (ethers: typeof Ethers) => {
|
|
|
256
275
|
);
|
|
257
276
|
});
|
|
258
277
|
|
|
259
|
-
// console.log({purchaseEvents});
|
|
278
|
+
// console.log({ purchaseEvents });
|
|
260
279
|
|
|
261
280
|
const soldEvents = await contractInstance
|
|
262
281
|
.queryFilter(soldFilter, bc, Math.min(bc + step - 1, END_BLOCK))
|
|
@@ -276,28 +295,27 @@ export const airdropRecover = (ethers: typeof Ethers) => {
|
|
|
276
295
|
// );
|
|
277
296
|
|
|
278
297
|
const isContract = async (log, role) => {
|
|
279
|
-
const possibleCodeStateOfAddress = await contractInstance.provider
|
|
298
|
+
const possibleCodeStateOfAddress = await contractInstance.provider
|
|
299
|
+
.getCode(log.args[role])
|
|
280
300
|
.catch(e => "0x");
|
|
281
301
|
return possibleCodeStateOfAddress !== "0x";
|
|
282
302
|
};
|
|
283
303
|
|
|
284
304
|
// Print out all the values:
|
|
285
305
|
const purchasedEventsMapped = purchaseEvents.map(async log => {
|
|
286
|
-
let balance = newAddresses[log.args.
|
|
287
|
-
// console.log(
|
|
306
|
+
let balance = newAddresses[log.args.to] || ZERO;
|
|
307
|
+
// console.log(log.blockNumber);
|
|
288
308
|
// console.log(`actualReturn: ${log.args.actualReturn.toString()}`);
|
|
289
|
-
newAddresses[log.args.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
);
|
|
309
|
+
newAddresses[log.args.to] =
|
|
310
|
+
log.blockNumber === 14358516 //airdrop reimburse
|
|
311
|
+
? balance.sub(log.args.value)
|
|
312
|
+
: balance.add(log.args.value);
|
|
313
|
+
newIsContracts[log.args.to] = await isContract(log, "to");
|
|
294
314
|
});
|
|
295
315
|
const soldEventsMapped = soldEvents.map(async log => {
|
|
296
|
-
let balance = newAddresses[log.args.
|
|
297
|
-
newAddresses[log.args.
|
|
298
|
-
newIsContracts[log.args.
|
|
299
|
-
log, "caller"
|
|
300
|
-
);
|
|
316
|
+
let balance = newAddresses[log.args.from] || ZERO;
|
|
317
|
+
newAddresses[log.args.from] = balance.sub(log.args.value);
|
|
318
|
+
newIsContracts[log.args.from] = await isContract(log, "from");
|
|
301
319
|
});
|
|
302
320
|
|
|
303
321
|
await Promise.all([...purchasedEventsMapped, ...soldEventsMapped]);
|
|
@@ -306,8 +324,17 @@ export const airdropRecover = (ethers: typeof Ethers) => {
|
|
|
306
324
|
}
|
|
307
325
|
};
|
|
308
326
|
|
|
309
|
-
await populateListOfAddressesAndBalances(
|
|
310
|
-
|
|
327
|
+
await populateListOfAddressesAndBalances(
|
|
328
|
+
newReserve,
|
|
329
|
+
reserveTokenPurchasedFilter,
|
|
330
|
+
reserveTokenSoldFilter
|
|
331
|
+
);
|
|
332
|
+
await populateListOfAddressesAndBalances(
|
|
333
|
+
recoveredReserve,
|
|
334
|
+
reserveTokenPurchasedFilter,
|
|
335
|
+
reserveTokenSoldFilter
|
|
336
|
+
);
|
|
337
|
+
// await populateListOfAddressesAndBalances(exchangeHelper, exchangeHelperTokenPurchasedFilter, exchangeHelperTokenSoldFilter);
|
|
311
338
|
|
|
312
339
|
// console.log({ newAddresses, newIsContracts });
|
|
313
340
|
return { newAddresses, newIsContracts };
|
|
@@ -317,25 +344,30 @@ export const airdropRecover = (ethers: typeof Ethers) => {
|
|
|
317
344
|
const { addressesCombined } = JSON.parse(
|
|
318
345
|
fs.readFileSync("airdrop/buyBalancesCombined.json").toString()
|
|
319
346
|
);
|
|
320
|
-
|
|
321
|
-
let toTree: Array<[string, BigNumber]> = Object.entries(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
);
|
|
326
|
-
|
|
347
|
+
|
|
348
|
+
let toTree: Array<[string, BigNumber]> = Object.entries(
|
|
349
|
+
addressesCombined
|
|
350
|
+
).map(([addr, gdx]) => {
|
|
351
|
+
return [addr, gdx as BigNumber];
|
|
352
|
+
});
|
|
353
|
+
|
|
327
354
|
// console.log(`Before sorting`);
|
|
328
|
-
// toTree.forEach((a,_) => { console.log(`${a[0].toString()}:${ethers.BigNumber.from(a[1]).toString()}\n`)});
|
|
329
|
-
|
|
330
|
-
toTree.sort((a, b) => BigNumber.from(b[1]).gt(a[1]) ? 0 : -1
|
|
355
|
+
// toTree.forEach((a,_) => { console.log(`${a[0].toString()}:${ethers.BigNumber.from(a[1]).toString()}\n`)});
|
|
356
|
+
|
|
357
|
+
toTree.sort((a, b) => (BigNumber.from(b[1]).gt(a[1]) ? 0 : -1));
|
|
331
358
|
|
|
332
359
|
// console.log(`After sorting`);
|
|
333
|
-
// toTree.forEach((a,_) => { console.log(`${a[0].toString()}:${ethers.BigNumber.from(a[1]).toString()}\n`)});
|
|
334
|
-
|
|
360
|
+
// toTree.forEach((a,_) => { console.log(`${a[0].toString()}:${ethers.BigNumber.from(a[1]).toString()}\n`)});
|
|
361
|
+
|
|
335
362
|
let totalGDX = ZERO;
|
|
336
|
-
toTree.forEach((a,_) => totalGDX = totalGDX.add(a[1]))
|
|
363
|
+
toTree.forEach((a, _) => (totalGDX = totalGDX.add(a[1])));
|
|
337
364
|
console.log({
|
|
338
|
-
toTree: toTree.forEach((a,_) =>
|
|
365
|
+
toTree: toTree.forEach((a, _) =>
|
|
366
|
+
console.log({
|
|
367
|
+
address: a[0].toString(),
|
|
368
|
+
balance: BigNumber.from(a[1]).toString()
|
|
369
|
+
})
|
|
370
|
+
),
|
|
339
371
|
numberOfAccounts: toTree.length,
|
|
340
372
|
TotalGDX: totalGDX.toString()
|
|
341
373
|
});
|
|
@@ -385,38 +417,63 @@ export const airdropRecover = (ethers: typeof Ethers) => {
|
|
|
385
417
|
const gdxAirdropData = JSON.parse(
|
|
386
418
|
fs.readFileSync("airdrop/gdxairdrop.json").toString()
|
|
387
419
|
);
|
|
388
|
-
const addressesCombined = {}
|
|
420
|
+
const addressesCombined = {};
|
|
389
421
|
for (const [address, balance] of Object.entries(gdxAirdropData.treeData)) {
|
|
390
|
-
addressesCombined[address] = BigNumber.from(balance[
|
|
422
|
+
addressesCombined[address] = BigNumber.from(balance["gdx"]).toString();
|
|
391
423
|
}
|
|
392
424
|
|
|
393
425
|
// get new holders info and turn into array
|
|
394
|
-
const { newAddresses
|
|
395
|
-
|
|
396
|
-
let newAddressesArray: Array<[string, BigNumber]> = Object.entries(newAddresses).map(
|
|
397
|
-
([addr, gdx]) => {
|
|
398
|
-
return [addr, gdx as BigNumber];
|
|
399
|
-
}
|
|
400
|
-
);
|
|
426
|
+
const { newAddresses } = await getHoldersInformation();
|
|
401
427
|
|
|
428
|
+
let newAddressesArray: Array<[string, BigNumber]> = Object.entries(
|
|
429
|
+
newAddresses
|
|
430
|
+
).map(([addr, gdx]) => {
|
|
431
|
+
return [addr, gdx as BigNumber];
|
|
432
|
+
});
|
|
402
433
|
|
|
403
|
-
// Unite previous airdrop with current information
|
|
434
|
+
// Unite previous airdrop with current information
|
|
404
435
|
for (const newAddressEntry of newAddressesArray) {
|
|
405
436
|
const address = newAddressEntry[0];
|
|
406
437
|
const addition = newAddressEntry[1];
|
|
407
|
-
|
|
408
|
-
if (addition<=ZERO)
|
|
409
|
-
continue;
|
|
438
|
+
|
|
439
|
+
if (addition <= ZERO) continue;
|
|
410
440
|
|
|
411
441
|
// console.log({address})
|
|
412
442
|
// console.log({before: BigNumber.from(addressesCombined[address] || "0").toString() })
|
|
413
443
|
// console.log({addition: addition.toString()})
|
|
414
|
-
addressesCombined[address] = ethers.BigNumber.from(
|
|
444
|
+
addressesCombined[address] = ethers.BigNumber.from(
|
|
445
|
+
addressesCombined[address] || 0
|
|
446
|
+
)
|
|
447
|
+
.add(addition.toString())
|
|
448
|
+
.toString();
|
|
415
449
|
// console.log({total: addressesCombined[address].toString()})
|
|
416
450
|
// console.log(`\n`);
|
|
417
451
|
}
|
|
418
|
-
|
|
419
|
-
|
|
452
|
+
|
|
453
|
+
let newReserve = await ethers.getContractAt(
|
|
454
|
+
"GoodReserveCDai",
|
|
455
|
+
"0xa150a825d425B36329D8294eeF8bD0fE68f8F6E0"
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
const ps = Object.entries(addressesCombined).map(async ([addr, amount]) => {
|
|
459
|
+
console.log(addr, amount);
|
|
460
|
+
const balance = await newReserve.balanceOf(addr);
|
|
461
|
+
const diff = balance.sub(amount);
|
|
462
|
+
if (diff.lt(0)) {
|
|
463
|
+
console.log({
|
|
464
|
+
addr,
|
|
465
|
+
balance: balance.toString(),
|
|
466
|
+
amount,
|
|
467
|
+
diff: diff.toString()
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
await Promise.all(ps);
|
|
473
|
+
fs.writeFileSync(
|
|
474
|
+
"airdrop/buyBalancesCombined.json",
|
|
475
|
+
JSON.stringify({ addressesCombined })
|
|
476
|
+
);
|
|
420
477
|
};
|
|
421
478
|
|
|
422
479
|
return { buildMerkleTree, addCalculationsToPreviousData };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { range, chunk } from "lodash";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import stakingContracts from "../../releases/deployment.json";
|
|
4
|
+
import { ethers as Ethers } from "hardhat";
|
|
5
|
+
import { BigNumber } from "ethereum-waffle/node_modules/ethers";
|
|
6
|
+
|
|
7
|
+
const ZERO = BigNumber.from("0");
|
|
8
|
+
|
|
9
|
+
export const sumStakersGdRewards = (ethers: typeof Ethers) => {
|
|
10
|
+
|
|
11
|
+
const getStakersGdRewards = async (stakersToGdRewards = {}) => {
|
|
12
|
+
const provider = new ethers.providers.InfuraProvider();
|
|
13
|
+
|
|
14
|
+
let goodFundManager = await ethers.getContractAt("GoodFundManager",stakingContracts["production-mainnet-bug"].GoodFundManager);
|
|
15
|
+
goodFundManager = goodFundManager.connect(provider);
|
|
16
|
+
const filter = goodFundManager.filters.StakingRewardMinted();
|
|
17
|
+
|
|
18
|
+
const step = 100000;
|
|
19
|
+
const ETH_START_BLOCK = 14291923;
|
|
20
|
+
const ETH_END_BLOCK = await provider.getBlockNumber();
|
|
21
|
+
const blocks = range(ETH_START_BLOCK, ETH_END_BLOCK, step);
|
|
22
|
+
|
|
23
|
+
for (let blockChunk of chunk(blocks, 10)) {
|
|
24
|
+
const processedChunks = blockChunk.map(async bc => {
|
|
25
|
+
const stakingRewardsEvents = await goodFundManager
|
|
26
|
+
.queryFilter(filter, bc, Math.min(bc + step - 1, ETH_END_BLOCK))
|
|
27
|
+
.catch(e => {
|
|
28
|
+
console.log("block transfer logs failed retrying...", bc);
|
|
29
|
+
return goodFundManager.queryFilter(
|
|
30
|
+
filter, bc, Math.min(bc + step - 1, ETH_END_BLOCK));
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const stakingRewardsEventsMapped = stakingRewardsEvents.map(async log => {
|
|
34
|
+
const initBalance = stakersToGdRewards[log.args.staker] || ZERO;
|
|
35
|
+
stakersToGdRewards[log.args.staker] = initBalance.add(log.args.gdReward);
|
|
36
|
+
// console.log(`TransactionHash:\t${log.transactionHash}`);
|
|
37
|
+
// console.log(`Staking contract:\t${log.args.stakingContract}`);
|
|
38
|
+
// console.log(`Previous Balance:\t${initBalance.toString()} for address ${log.args.staker}`);
|
|
39
|
+
// console.log(`Addition:\t\t${log.args.gdReward.toString()} for address ${log.args.staker}`);
|
|
40
|
+
// console.log(`New Balance:\t\t${stakersToGdRewards[log.args.staker].toString()} for address ${log.args.staker}\n`);
|
|
41
|
+
});
|
|
42
|
+
await Promise.all([...stakingRewardsEventsMapped]);
|
|
43
|
+
});
|
|
44
|
+
await Promise.all(processedChunks);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(`All stakers minted rewards:\n`);
|
|
48
|
+
Object.entries(stakersToGdRewards).forEach(a => { console.log(`${a[0].toString()}:${BigNumber.from(a[1]).toString()}\n`)});
|
|
49
|
+
// fs.writeFileSync("scripts/staking/stakersToGdRewards.json", JSON.stringify(stakersToGdRewards))
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return { getStakersGdRewards};
|
|
53
|
+
}
|