From 9ddafc0b1ce55f97562f35fa8f016d701b595fdd Mon Sep 17 00:00:00 2001 From: Marco Tabasco Date: Mon, 24 Jun 2024 17:57:38 +0200 Subject: [PATCH] added custom test --- test/helpers/contract-helpers.ts | 4 +- test/operators/whitelist.ts | 84 +++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/test/helpers/contract-helpers.ts b/test/helpers/contract-helpers.ts index cae0fa7d..2a68ec5d 100644 --- a/test/helpers/contract-helpers.ts +++ b/test/helpers/contract-helpers.ts @@ -170,6 +170,7 @@ export const registerOperators = async function ( fee: BigInt, gasGroups: GasGroup[] = [GasGroup.REGISTER_OPERATOR], ) { + const newOperatorIds = []; const targetOperatorId = lastOperatorId + numberOfOperators; for (let i = lastOperatorId; i < lastOperatorId + numberOfOperators && i < mockedOperators.length; i++) { const operator = mockedOperators[i]; @@ -185,9 +186,10 @@ export const registerOperators = async function ( const event = eventsByName.OperatorAdded[0]; operator.id = Number(event.args.operatorId); mockedOperators[i] = operator; + newOperatorIds.push(operator.id); } lastOperatorId = targetOperatorId; - return lastOperatorId; + return newOperatorIds; }; export const coldRegisterValidator = async function () { diff --git a/test/operators/whitelist.ts b/test/operators/whitelist.ts index 5a06c663..7d7ff410 100644 --- a/test/operators/whitelist.ts +++ b/test/operators/whitelist.ts @@ -8,8 +8,10 @@ import { trackGas, GasGroup } from '../helpers/gas-usage'; import { ethers } from 'hardhat'; import { expect } from 'chai'; +import { mine } from '@nomicfoundation/hardhat-network-helpers'; + // Declare globals -let ssvNetwork: any, ssvViews: any, mockWhitelistingContract: any, mockWhitelistingContractAddress: any; +let ssvNetwork: any, ssvViews: any, ssvToken: any, mockWhitelistingContract: any, mockWhitelistingContractAddress: any; const OPERATOR_IDS_10 = Array.from({ length: 10 }, (_, i) => i + 1); describe('Whitelisting Operator Tests', () => { @@ -18,6 +20,7 @@ describe('Whitelisting Operator Tests', () => { const metadata = await initializeContract(); ssvNetwork = metadata.ssvNetwork; ssvViews = metadata.ssvNetworkViews; + ssvToken = metadata.ssvToken; mockWhitelistingContract = await hre.viem.deployContract('MockWhitelistingContract', [[]], { client: owners[0].client, @@ -967,4 +970,83 @@ describe('Whitelisting Operator Tests', () => { [], ); }); + + it('Custom test: Operators balances sync', async () => { + // owners[2] -> operators' owner + // owners[3] -> whitelisted address for all 4 operators + + // create 4 operators with a fee + const operatorIds = await registerOperators(2, 4, CONFIG.minimalOperatorFee); + + // set operators private + ssvNetwork.write.setOperatorsPrivateUnchecked([operatorIds], { + account: owners[2].account, + }); + + // whitelist owners[3] address for all operators + await ssvNetwork.write.setOperatorsWhitelists([operatorIds, [owners[3].account.address]], { + account: owners[2].account, + }); + + // owners[3] registers a validator + const minDepositAmount = (BigInt(CONFIG.minimalBlocksBeforeLiquidation) + 2n) * CONFIG.minimalOperatorFee * 4n; + await ssvToken.write.approve([ssvNetwork.address, minDepositAmount], { account: owners[3].account }); + const { eventsByName } = await trackGas( + ssvNetwork.write.registerValidator( + [ + DataGenerator.publicKey(1), + operatorIds, + await DataGenerator.shares(2, 1, operatorIds), + minDepositAmount, + { + validatorCount: 0, + networkFeeIndex: 0, + index: 0, + balance: 0n, + active: true, + }, + ], + { account: owners[3].account }, + ), + ); + + const firstCluster = eventsByName.ValidatorAdded[0].args; + + // liquidate the cluster + await mine(CONFIG.minimalBlocksBeforeLiquidation); + const liquidatedCluster = await trackGas( + ssvNetwork.write.liquidate([firstCluster.owner, firstCluster.operatorIds, firstCluster.cluster]), + ); + const updatedCluster = liquidatedCluster.eventsByName.ClusterLiquidated[0].args; + + // withdraw all operators' earnings + for (let i = 0; i < operatorIds.length; i++) { + await ssvNetwork.write.withdrawAllOperatorEarnings([operatorIds[i]], { + account: owners[2].account, + }); + } + + // de-whitelist owners[3] address for all operators + await ssvNetwork.write.removeOperatorsWhitelists([operatorIds, [owners[3].account.address]], { + account: owners[2].account, + }); + + // check operators' balance is 0 after few blocks + await mine(1000); + for (let i = 0; i < operatorIds.length; i++) { + expect(await ssvViews.read.getOperatorEarnings([operatorIds[i]])).to.equal(0); + } + + // reactivate the cluster + await ssvToken.write.approve([ssvNetwork.address, minDepositAmount], { account: owners[3].account }); + await ssvNetwork.write.reactivate([updatedCluster.operatorIds, minDepositAmount, updatedCluster.cluster], { + account: owners[3].account, + }); + + // all operators have have the right balance + await mine(100); + for (let i = 0; i < operatorIds.length; i++) { + expect(await ssvViews.read.getOperatorEarnings([operatorIds[i]])).to.equal(CONFIG.minimalOperatorFee * 100n); + } + }); });