@gooddollar/goodprotocol
Version:
GoodDollar Protocol
99 lines (90 loc) • 3.59 kB
text/typescript
import { countBy, chunk, difference, flatten, sortBy } from "lodash";
import fs from "fs";
import { network, ethers, upgrades } from "hardhat";
import { Contract, Provider, setMulticallAddress } from "ethers-multicall";
import Identity from "../../artifacts/contracts/Interfaces.sol/IIdentity.json";
setMulticallAddress(122, "0x3CE6158b7278Bf6792e014FA7B4f3c6c46fe9410");
const CLAIM_START_BLOCK = 17896430;
const fuseProvider = new ethers.providers.JsonRpcBatchProvider(
"https://explorer-node.fuse.io/"
// "https://rpc.fuse.io"
);
const ethcallProvider = new Provider(fuseProvider, 122);
const GD_FUSE = "0x495d133b938596c9984d462f007b676bdc57ecec";
const IDENTITY_FUSE = "0xFa8d865A962ca8456dF331D78806152d3aC5B84F";
let gd = new ethers.Contract(
GD_FUSE,
[
"event Transfer(address indexed from, address indexed to, uint amount)",
"function balanceOf(address) view returns(uint256)"
],
fuseProvider
);
const gdMulti = new Contract(GD_FUSE, [
"event Transfer(address indexed from, address indexed to, uint amount)",
"function balanceOf(address) view returns(uint256)"
]);
const hasBalanceToRefund = async wallets => {
const chunks = chunk(wallets, 1000);
let balances = {};
for (let batch of chunks) {
const calls = batch.map(a => gdMulti.balanceOf(a));
const result = await ethcallProvider.all(calls);
console.log("batch:", batch.length, calls.length, result.length);
batch.forEach((d, i) => (balances[d] = result[i]));
}
console.log("got balances for:", Object.entries(balances).length);
const hasBalance = countBy(balances, v => v >= 9622260);
const noBalance = Object.entries(balances).filter(([k, v]) => v < 9622260);
console.log({ hasBalance });
return noBalance.map(_ => _[0]);
};
const hasRefunded = async wallets => {
const curBlock = (await gd.provider.getBlockNumber()) - 1;
console.log({ curBlock });
let toBlock = CLAIM_START_BLOCK + 50000;
let refunded = [];
let startBlock = CLAIM_START_BLOCK;
while (startBlock <= curBlock) {
const events = await gd.queryFilter(
gd.filters.Transfer(undefined, "0xd253A5203817225e9768C05E5996d642fb96bA86"),
startBlock,
toBlock
);
const accounts = events.filter(e => e.args.amount >= 9622260).map(_ => _.args.from.toLowerCase());
refunded.push(...accounts);
console.log("has refunded:", {
startBlock,
toBlock,
accounts: accounts.length
});
toBlock = Math.min(curBlock, toBlock + 50000);
startBlock += 50000;
}
return refunded;
};
const whereIsTheMoney = async noBalance => {
let targets = [];
for (let batch of chunk(noBalance, 100)) {
const tos = await Promise.all(
batch.map(async a => {
const e = await gd.queryFilter(gd.filters.Transfer(a), CLAIM_START_BLOCK);
const tos = e.filter(_ => _.args.amount > 1000000).map(_ => _.args.to);
return tos;
})
);
targets.push(...flatten(tos));
}
const targetCounter = countBy(targets, _ => _);
console.log("transfer targets:", sortBy(Object.entries(targetCounter), "1").reverse());
};
const main = async () => {
const wallets = JSON.parse(fs.readFileSync("torefund.json").toString()).map(_ => _.toLowerCase());
console.log("Total Claimed:", wallets.length);
const refunded = await hasRefunded(wallets);
const notRefunded = difference(wallets, refunded);
console.log("refunded:", refunded.length, "not refunded:", notRefunded.length);
const noBalanceToRefund = await hasBalanceToRefund(notRefunded);
await whereIsTheMoney(noBalanceToRefund);
};
main().catch(e => console.log(e));