Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0cc7083
Add v1 nxm data and scripts
rackstar Aug 16, 2024
c63f784
Add v1 nxm push estimate gas script
rackstar Aug 20, 2024
48de15b
Add v1 NXM amounts calculation
rackstar Aug 20, 2024
3734cd7
Update v1 nxm scripts
rackstar Sep 2, 2024
d07a0e3
Rename v1 nxm data json files
rackstar Sep 3, 2024
bf2e9a2
Add v1 nxm push script
rackstar Sep 3, 2024
00a190b
Add v1-nxm-coordinator script
rackstar Sep 4, 2024
3e882d2
Update v1 nxm scripts
rackstar Sep 4, 2024
1e16d00
Update .eslintrc ecmaVersion to 2021
rackstar Sep 4, 2024
41622b8
Drop unneccesary data files
rackstar Sep 4, 2024
44cbbb8
Update output file name
rackstar Sep 4, 2024
22c18ac
Add docs, logs and clean up
rackstar Sep 4, 2024
93df65c
Rename file
rackstar Sep 4, 2024
e43c434
Add logs for failed memberIds
rackstar Sep 4, 2024
49f34e8
Fix linting issues + clean up
rackstar Sep 4, 2024
88eaab3
Rename file and remove unused file
rackstar Sep 4, 2024
277a439
Move functions to v1-nxm-push-utils
rackstar Sep 4, 2024
33f8912
Code clean up
rackstar Sep 4, 2024
ff518b2
Code clean up
rackstar Sep 5, 2024
10c112f
Remove v1-nxm-total in favour of v1-nxm-accounting
rackstar Sep 5, 2024
b79f841
Add failed members logs
rackstar Sep 5, 2024
1d7c460
Add tx.wait after sending txs
rackstar Sep 5, 2024
187f218
Move processing member logging after gas fee validation
rackstar Sep 6, 2024
e464a35
Set explicit gasFees
rackstar Sep 6, 2024
df5e67e
Push staking rewards first
rackstar Sep 6, 2024
a45e80e
Set pushV1StakingStake manual gasLimit
rackstar Sep 6, 2024
bd93484
Clean up v1 nxm push scripts
rackstar Sep 6, 2024
622401c
Clean up v1-nxm-accounting script
rackstar Sep 6, 2024
d5aa374
Drop redundant dotenv config
rackstar Sep 6, 2024
cd7295d
Add manual gasLimit from previous estimate
rackstar Sep 6, 2024
065c51e
Fix nxm accounting
rackstar Sep 6, 2024
42e5941
Fixes
rackstar Sep 6, 2024
3207a6d
Send tx synchronously to avoid having same nonce
rackstar Sep 6, 2024
ad17a34
Add manual / auto nonce feature
rackstar Sep 6, 2024
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
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"ignorePatterns": ["node_modules/", "artifacts", "coverage", "!.solcover.js", "deployments/dist"],
"parserOptions": {
"ecmaVersion": 2020
"ecmaVersion": 2021
},
"rules": {
"comma-dangle": ["warn", "always-multiline"],
Expand Down
72 changes: 72 additions & 0 deletions scripts/v1-nxm/v1-cla-locked.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const { inspect } = require('node:util');
const fs = require('node:fs');

const { Sema } = require('async-sema');
const { ethers } = require('hardhat');

const { getContract } = require('./v1-nxm-push-utils');

const OUTPUT_FILE = 'v1-cla-locked-amount.json';
const ROLE_MEMBER = 2;

async function getMemberCLA(memberId, claReason, mr, tc) {
process.stdout.write(`\rProcessing memberId ${memberId}`);

const [member, active] = await mr.memberAtIndex(ROLE_MEMBER, memberId);

if (!active) {
return { member, amount: '0' };
}

const amount = await tc.tokensLocked(member, claReason);

return { member, amount: amount.toString() };
}

const main = async () => {
const v1ClaimAssessment = [];

const mr = getContract('MemberRoles');
const tc = getContract('TokenController');

const claReason = ethers.utils.formatBytes32String('CLA');
const memberCount = (await mr.membersLength(ROLE_MEMBER)).toNumber();
const membersSemaphore = new Sema(100, { capacity: memberCount });

console.log('Fetching V1 Pooled Staking stake / rewards for all members...');
const failedMemberIds = [];

const memberPromises = Array.from({ length: memberCount }).map(async (_, memberId) => {
await membersSemaphore.acquire();

try {
const result = await getMemberCLA(memberId, claReason, mr, tc);
if (result.amount !== '0') {
v1ClaimAssessment.push(result);
}
} catch (e) {
console.error(`Error processing memberId ${memberId}: ${e.message}`);
failedMemberIds.push(memberId);
}

membersSemaphore.release();
});

await Promise.all(memberPromises);

console.log(`Found ${v1ClaimAssessment.length} members with locked v1 NXM for CLA`);
console.log(`Failed members: ${inspect(failedMemberIds, { depth: null })}`);

console.log(`Writing output to ${OUTPUT_FILE}...`);
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(v1ClaimAssessment, null, 2), 'utf8');
console.log('Done.');
};

if (require.main === module) {
main()
.then(() => process.exit(0))
.catch(e => {
console.log('Unhandled error encountered: ', e.stack);
process.exit(1);
});
}
103 changes: 103 additions & 0 deletions scripts/v1-nxm/v1-cn-locked.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
const { inspect } = require('node:util');
const fs = require('node:fs');

const { Sema } = require('async-sema');
const { ethers } = require('hardhat');

const { getContract } = require('./v1-nxm-push-utils');

const { BigNumber } = ethers;

const OUTPUT_FILE = 'v1-cn-locked-amount.json';
const ROLE_MEMBER = 2;

async function getMemberCN(memberId, mr, tc) {
try {
const [member, active] = await mr.memberAtIndex(ROLE_MEMBER, memberId);

if (!active) {
return { member, amount: '0' };
}

const { coverIds, lockReasons, withdrawableAmount } = await tc.getWithdrawableCoverNotes(member);
const memberLockReasons = await tc.getLockReasons(member);

const lockReasonIndexCover = {};
let coverIndex = 0;
for (const lockReason of lockReasons) {
const lockReasonIndex = memberLockReasons.indexOf(lockReason);
lockReasonIndexCover[lockReasonIndex] = BigNumber.from(coverIds[coverIndex++]).toString();
}

const sortedIndexes = Object.keys(lockReasonIndexCover).sort((a, b) => a - b);
const sortedCoverIds = [];
for (const index of sortedIndexes) {
sortedCoverIds.push(lockReasonIndexCover[index]);
}

return {
member,
coverIds: sortedCoverIds,
lockReasonIndexes: sortedIndexes,
amount: withdrawableAmount.toString(),
};
} catch (error) {
console.error(`Error processing memberId ${memberId}: ${error.message}`);
return { member: 'unknown', amount: '0', error: error.message };
}
}

const main = async () => {
const tc = getContract('TokenController');
const mr = getContract('MemberRoles');

const memberCount = (await mr.membersLength(ROLE_MEMBER)).toNumber();
const membersSemaphore = new Sema(100, { capacity: memberCount });
const memberLockedCN = [];
const failedMemberIds = [];

console.log('Fetching locked CN amounts for all members...');

const memberPromises = Array.from({ length: memberCount }).map(async (_, memberId) => {
await membersSemaphore.acquire();

try {
process.stdout.write(`\rProcessing memberId ${memberId}`);
const lockedCN = await getMemberCN(memberId, mr, tc);

if (lockedCN.amount !== '0') {
memberLockedCN.push(lockedCN);
}
if (lockedCN.error) {
console.error(`\nError event for memberId ${memberId}: ${lockedCN.error}`);
failedMemberIds.push(memberId);
}
} catch (e) {
console.error(`\nError event for memberId ${memberId}: ${e.message}`);
failedMemberIds.push(memberId);
} finally {
membersSemaphore.release();
}
});

await Promise.all(memberPromises);

console.log(`\nFound ${memberLockedCN.length} members with locked v1 NXM for CN`);
console.log(`Failed members: ${inspect(failedMemberIds, { depth: null })}`);

console.log(`Writing output to ${OUTPUT_FILE}...`);
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(memberLockedCN, null, 2), 'utf8');
console.log('Done.');
};

if (require.main === module) {
const provider = new ethers.providers.JsonRpcProvider(process.env.TEST_ENV_FORK);
main(provider)
.then(() => process.exit(0))
.catch(e => {
console.log('Unhandled error encountered: ', e.stack);
process.exit(1);
});
}

module.exports = main;
86 changes: 86 additions & 0 deletions scripts/v1-nxm/v1-nxm-accounting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const deployments = require('@nexusmutual/deployments');
const { ethers } = require('hardhat');

const { getContract } = require('./v1-nxm-push-utils');

async function logPoolBalances() {
const tokenController = getContract('TokenController');
const nxm = getContract('NXMToken');
const stakingPoolFactory = getContract('StakingPoolFactory');

let totalDeposits = ethers.BigNumber.from(0);
let totalRewards = ethers.BigNumber.from(0);

const stakingPoolCount = await stakingPoolFactory.stakingPoolCount();

for (let poolId = 1; poolId <= stakingPoolCount.toNumber(); poolId++) {
const { rewards, deposits } = await tokenController.stakingPoolNXMBalances(poolId);
const depositsNXM = ethers.utils.formatEther(deposits);
const rewardsNXM = ethers.utils.formatEther(rewards);

console.log(`Pool ${poolId}: Deposits: ${depositsNXM} NXM, Rewards: ${rewardsNXM} NXM`);

totalDeposits = totalDeposits.add(deposits);
totalRewards = totalRewards.add(rewards);
}

const cnData = require('../../v1-cn-locked-amount.json');
const claData = require('../../v1-cla-locked-amount.json');
const cnBalance = cnData.reduce((acc, data) => acc.add(data.amount), ethers.BigNumber.from(0));
const claBalance = claData.reduce((acc, data) => acc.add(data.amount), ethers.BigNumber.from(0));

const totalDepositsNXM = ethers.utils.formatEther(totalDeposits);
const totalRewardsNXM = ethers.utils.formatEther(totalRewards);
const totalCnBalanceNXM = ethers.utils.formatEther(cnBalance);
const totalClaBalanceNXM = ethers.utils.formatEther(claBalance);

console.log(`Total Deposits: ${totalDepositsNXM} NXM`);
console.log(`Total Rewards: ${totalRewardsNXM} NXM`);
console.log(`CN Balance: ${totalCnBalanceNXM} NXM`);
console.log(`CLA Balance: ${totalClaBalanceNXM} NXM`);

const totalPoolBalance = totalDeposits.add(totalRewards).add(cnBalance).add(claBalance);
console.log(`EXPECTED Total Pool Balance: ${ethers.utils.formatEther(totalPoolBalance)} NXM`);

const tokenControllerBalance = await nxm.balanceOf(deployments.addresses.TokenController);
console.log(`ACTUAL Token Controller Balance: ${ethers.utils.formatEther(tokenControllerBalance)} NXM`);

const difference = tokenControllerBalance.sub(totalPoolBalance);
const differenceNXM = ethers.utils.formatEther(difference);

console.log(`Difference: ${differenceNXM} NXM`);
}

/* Get total v1 NXM amounts that is owed to members */
const getAmounts = (label, usersAndAmounts) => {
const totalAmountNxm = usersAndAmounts.reduce((acc, data) => acc.add(data.amount), ethers.BigNumber.from(0));
const totalNxm = ethers.utils.formatEther(totalAmountNxm);
console.log(`${label} ${totalNxm} NXM`);
return totalNxm;
};

async function legacyPooledStakingAccounting() {
const nxm = getContract('NXMToken');

const psBal = await nxm.balanceOf(deployments.addresses.LegacyPooledStaking);
const psBalNxm = ethers.utils.formatEther(psBal);

const stakeData = require('../../v1-pooled-staking-stake.json');
const rewardsData = require('../../v1-pooled-staking-rewards.json');
const v1NxmStake = getAmounts('Stake', stakeData);
const v1NxmRewards = getAmounts('Rewards', rewardsData);
console.log(`LegacyPooledStaking ${psBalNxm} NXM`);

console.log(`LegacyPooledStaking Difference ${psBalNxm - v1NxmRewards - v1NxmStake} NXM`);
}

if (require.main === module) {
legacyPooledStakingAccounting()
.then(() => console.log('\n--------------------\n'))
.then(() => logPoolBalances())
.then(() => process.exit(0))
.catch(e => {
console.log('Unhandled error encountered: ', e.stack);
process.exit(1);
});
}
Loading
Loading