Skip to content

Instantly share code, notes, and snippets.

@sembrestels
Created July 21, 2021 09:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sembrestels/e2639bfa07ab2425857678504355d1f1 to your computer and use it in GitHub Desktop.
Save sembrestels/e2639bfa07ab2425857678504355d1f1 to your computer and use it in GitHub Desktop.
Distribution of CSTK+IH voting power during pre-hatch IH distribution discussion
import { BigNumber } from "ethers";
import { ethers } from "hardhat";
import { MiniMeToken } from "../typechain";
import fetch from "node-fetch";
const cstkAddr = '0xc4fbE68522ba81a28879763C3eE33e08b13c499E'
const ihAddr = '0xDF2C3C8764a92Eb43d2eEA0A4C2d77c2306b0835'
const block = 16868082
const PPM = 1000000
const TOKENHOLDERS_LENGTH = 250
export const getContributors = async (tokenAddress: string): Promise<string[]> => {
return fetch(`https://blockscout.com/xdai/mainnet/api?module=token&action=getTokenHolders&contractaddress=${tokenAddress}&offset=${TOKENHOLDERS_LENGTH}`)
.then(res => res.json())
.then(res => res.result.map(({ address }) => address))
};
async function main(): Promise<void> {
const cstkHolders = await getContributors(cstkAddr)
const ihHolders = await getContributors(ihAddr)
const holders = [...new Set([...cstkHolders, ...ihHolders])]
const cstk = await ethers.getContractAt("MiniMeToken", cstkAddr) as MiniMeToken
const ih = await ethers.getContractAt("MiniMeToken", ihAddr) as MiniMeToken
const cstkBalances = await Promise.all(cstkHolders.map(cstkHolder => cstk.balanceOfAt(cstkHolder, block)))
const ihBalances = await Promise.all(ihHolders.map(ihHolder => ih.balanceOfAt(ihHolder, block)))
const cstkSupply = await cstk.totalSupplyAt(block)
const ihSupply = await ih.totalSupplyAt(block)
const cstkDist = holders.map(holder => {
const cstkBalance = cstkBalances[cstkHolders.indexOf(holder)] || BigNumber.from(0)
return cstkBalance.mul(PPM).div(cstkSupply).toNumber() / PPM
}).sort()
const ihDist = holders.map(holder => {
const ihBalance = ihBalances[ihHolders.indexOf(holder)] || BigNumber.from(0)
return ihBalance.mul(PPM).div(ihSupply).toNumber() / PPM
}).sort()
const holderDist = holders.map(holder => {
const cstkBalance = cstkBalances[cstkHolders.indexOf(holder)] || BigNumber.from(0)
const ihBalance = ihBalances[ihHolders.indexOf(holder)] || BigNumber.from(0)
return cstkBalance.mul(PPM).div(cstkSupply).add(ihBalance.mul(PPM).div(ihSupply)).div(2).toNumber() / PPM
}).sort()
const cstkTop10 = cstkDist.slice(-10).reverse()
const ihTop10 = ihDist.slice(-10).reverse()
const holderTop10 = holderDist.slice(-10).reverse()
console.log('CSTK Top 10 voting power: ', cstkTop10.reduce((a, b) => a + b, 0)) // 0.38605900000000004
console.log('IH Top 10 voting power: ', ihTop10.reduce((a, b) => a + b, 0)) // 0.36001900000000003
console.log('CSTK+IH Top 10 voting power', holderTop10.reduce((a, b) => a + b, 0)) // 0.30367999999999995
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment