Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed web3 from extract-staking-balances #1335

Merged
merged 3 commits into from
Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Loading default deployment for network
Using ProxyiETH address of 0xA9859874e1743A32409f75bB11549892138BBA1E
StakingRewardsiETH
Using StakingRewardsiETH address of 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d
Loading rewards for synth iETH on network mainnet
Staking rewards StakingRewardsiETH deployed at block 11781285
iETH current price is 774
Exchange fee of sUSD is 0.003
Querying all transfers into the staking contract to find candidate stakers.

Staking Contract: 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d
Synth: 0xA9859874e1743A32409f75bB11549892138BBA1E
Starting Block: 11781285 (853677 blocks ago at 2021/1/3 5:0:31 UTC)

138 candidate holders found. Querying their balances.

|██████████████████████████████████████████████████| - 138 / 138 (100%)

9 active stakers found.

Computing owed sUSD balances for accounts using parameters:
Price: 774
Exchange Fee: 0.3%

10.791025799025218434 staked in total.
8327.197206540182510709 total sUSD owed.

Saving results to owedBalances.csv...
27 changes: 27 additions & 0 deletions output_new.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Loading default deployment for network
Using ProxyiETH address of 0xA9859874e1743A32409f75bB11549892138BBA1E
Using StakingRewardsiETH address of 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d
Loading rewards for synth iETH on network mainnet
Staking rewards StakingRewardsiETH deployed at block 11781285
iETH current price is 774.0
Exchange fee of sUSD is 0.003
Querying all transfers into the staking contract to find candidate stakers.

Staking Contract: 0x3f27c540ADaE3a9E8c875C61e3B970b559d7F65d
Synth: 0xA9859874e1743A32409f75bB11549892138BBA1E
Starting Block: 11781285 (855481 blocks ago at 2021/1/3 5:0:31 UTC)

138 candidate holders found. Querying their balances.

|██████████████████████████████████████████████████| - 138 / 138 (100%)

9 active stakers found.

Computing owed sUSD balances for accounts using parameters:
Price: 774.0
Exchange Fee: 0.3%

10.791025799025218434 staked in total.
8327.197206540182510709 total sUSD owed.

Saving results to owedBalances.csv...
98 changes: 57 additions & 41 deletions publish/src/commands/extract-staking-balances.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const BN = require('bn.js');
const Web3 = require('web3');
const ethers = require('ethers');
const uniq = require('lodash.uniq');
const { toBN, fromWei, toWei } = require('web3-utils');
const {
wrap,
toBytes32,
Expand All @@ -29,7 +27,12 @@ async function extractStakingBalances({ network = DEFAULTS.network, deploymentPa
ensureDeploymentPath(deploymentPath);

// We're just using the ERC20 members `balanceOf` and `Transfer`, so any ERC20 contract will do.
const { getSource, getTarget, getVersions } = wrap({ network, deploymentPath, fs, path });
const { getSource, getTarget, getVersions } = wrap({
network,
deploymentPath,
fs,
path,
});

const { abi: snxABI } = getSource({ contract: 'Synthetix' });

Expand Down Expand Up @@ -82,50 +85,52 @@ async function extractStakingBalances({ network = DEFAULTS.network, deploymentPa
yellow(deploymentBlock)
);

const web3 = new Web3(new Web3.providers.HttpProvider(providerUrl));
const provider = new ethers.providers.JsonRpcProvider(providerUrl);

const ExchangeRates = new web3.eth.Contract(
const ExchangeRates = new ethers.Contract(
getTarget({ contract: 'ExchangeRates' }).address,
getSource({ contract: 'ExchangeRates' }).abi,
getTarget({ contract: 'ExchangeRates' }).address
provider
);

// The price at which the inverse synth was frozen, to compute how much users are owed after purging
const frozenPrice = await ExchangeRates.methods.rateForCurrency(toBytes32(synth)).call();
const frozenPrice = await ExchangeRates.rateForCurrency(toBytes32(synth));

console.log(`${synth} current price is `, yellow(web3.utils.fromWei(frozenPrice)));
console.log(`${synth} current price is `, yellow(ethers.utils.formatEther(frozenPrice)));

const isFrozen = await ExchangeRates.methods.rateIsFrozen(toBytes32(synth)).call();
const isFrozen = await ExchangeRates.rateIsFrozen(toBytes32(synth));

if (!isFrozen) {
throw new Error(`Error: ${synth} not frozen`);
}

const SystemSettings = new web3.eth.Contract(
const SystemSettings = new ethers.Contract(
getTarget({ contract: 'SystemSettings' }).address,
getSource({ contract: 'SystemSettings' }).abi,
getTarget({ contract: 'SystemSettings' }).address
provider
);

// The exchange fee incurred when users are purged into sUSD
const exchangeFee = await SystemSettings.methods.exchangeFeeRate(toBytes32('sUSD')).call();
const exchangeFee = await SystemSettings.exchangeFeeRate(toBytes32('sUSD'));

console.log(gray(`Exchange fee of sUSD is`), yellow(web3.utils.fromWei(exchangeFee)));
console.log(gray(`Exchange fee of sUSD is`), yellow(ethers.utils.formatEther(exchangeFee)));

/** *********** --------------------- *********** **/

// Fixed point multiplication utilities
function multiplyDecimal(x, y) {
const xBN = BN.isBN(x) ? x : toBN(x);
const yBN = BN.isBN(y) ? y : toBN(y);
const xBN = ethers.BigNumber.isBigNumber(x) ? x : ethers.BigNumber.from(x);
const yBN = ethers.BigNumber.isBigNumber(y) ? y : ethers.BigNumber.from(y);

const unit = toBN(toWei('1'));
const unit = ethers.utils.parseEther('1');
return xBN.mul(yBN).div(unit);
}

// Retrieves a user's staking balance from the staking contract
async function getStakingBalance(stakingContract, account) {
return {
address: account,
balance: await stakingContract.methods.balanceOf(account).call(),
balance: await stakingContract.balanceOf(account),
};
}

Expand All @@ -149,11 +154,11 @@ async function extractStakingBalances({ network = DEFAULTS.network, deploymentPa

// Looks for all transfers into the staking contract
async function fetchStakedBalances() {
const iSynth = new web3.eth.Contract(snxABI, iSynthAddress);
const stakingContract = new web3.eth.Contract(snxABI, stakingAddress);
const iSynth = new ethers.Contract(iSynthAddress, snxABI, provider);
const stakingContract = new ethers.Contract(stakingAddress, snxABI, provider);

const currentBlock = await web3.eth.getBlockNumber();
const deploymentBlockDetails = await web3.eth.getBlock(deploymentBlock);
const currentBlock = await provider.getBlockNumber();
const deploymentBlockDetails = await provider.getBlock(deploymentBlock);

console.log(`Querying all transfers into the staking contract to find candidate stakers.\n`);
console.log(` Staking Contract: ${stakingAddress}`);
Expand All @@ -163,14 +168,18 @@ async function extractStakingBalances({ network = DEFAULTS.network, deploymentPa
deploymentBlock} blocks ago at ${formatDate(deploymentBlockDetails.timestamp * 1000)})\n`
);

const transferEvents = await iSynth.getPastEvents('Transfer', {
filter: {
to: stakingAddress,
const transferEvents = await iSynth.queryFilter(
{
topics: [
ethers.utils.id('Transfer(address,address,uint256)'),
null,
ethers.utils.hexZeroPad(stakingAddress, 32),
],
},
fromBlock: deploymentBlock - 1,
});
deploymentBlock - 1
);

const candidates = uniq(transferEvents.map(e => e.returnValues.from));
const candidates = uniq(transferEvents.map(e => e.args.from));

const nonzero = [];

Expand All @@ -196,27 +205,34 @@ async function extractStakingBalances({ network = DEFAULTS.network, deploymentPa
// Computes the balances owed to each account
function computeOwedBalances(balances) {
console.log(`\nComputing owed sUSD balances for accounts using parameters:`);
console.log(` Price: ${fromWei(frozenPrice)}`);
console.log(` Exchange Fee: ${fromWei(multiplyDecimal(exchangeFee, toWei('100')))}%`);

const feeMultiplier = toBN(toWei('1')).sub(toBN(exchangeFee));
console.log(` Price: ${ethers.utils.formatEther(frozenPrice)}`);
console.log(
` Exchange Fee: ${ethers.utils.formatEther(
multiplyDecimal(exchangeFee, ethers.utils.parseEther('100'))
)}%`
);

const feeMultiplier = ethers.utils.parseEther('1').sub(exchangeFee);
const result = balances.map(b => {
const owed = multiplyDecimal(multiplyDecimal(toBN(b.balance), frozenPrice), feeMultiplier);
const owed = multiplyDecimal(multiplyDecimal(b.balance, frozenPrice), feeMultiplier);

return {
address: b.address,
balance: b.balance,
owed: owed.toString(),
readableBalance: fromWei(b.balance),
readableOwed: fromWei(owed),
readableBalance: ethers.utils.formatEther(b.balance),
readableOwed: ethers.utils.formatEther(owed),
};
});

const totalStaked = result.reduce((total, curr) => total.add(toBN(curr.balance)), toBN(0));
const totalOwed = result.reduce((total, curr) => total.add(toBN(curr.owed)), toBN(0));
const totalStaked = result.reduce(
(total, curr) => total.add(curr.balance),
ethers.constants.Zero
);
const totalOwed = result.reduce((total, curr) => total.add(curr.owed), ethers.constants.Zero);

console.log(`\n${fromWei(totalStaked)} staked in total.`);
console.log(`${fromWei(totalOwed)} total sUSD owed.\n`);
console.log(`\n${ethers.utils.formatEther(totalStaked, 'ether')} staked in total.`);
console.log(`${ethers.utils.formatEther(totalOwed, 'ether')} total sUSD owed.\n`);
return result;
}

Expand All @@ -228,8 +244,8 @@ async function extractStakingBalances({ network = DEFAULTS.network, deploymentPa
csvString = csvString.concat(line);
}

csvString = csvString.concat(`\nPrice,${fromWei(frozenPrice)}\n`);
csvString = csvString.concat(`Exchange Fee,${fromWei(exchangeFee)}\n`);
csvString = csvString.concat(`\nPrice,${ethers.utils.formatEther(frozenPrice)}\n`);
csvString = csvString.concat(`Exchange Fee,${ethers.utils.formatEther(exchangeFee)}\n`);

console.log(`Saving results to ${owedFile}...`);
fs.writeFileSync(owedFile, csvString);
Expand Down