diff --git a/test-ts/account.test.ts b/test-ts/account.test.ts index 130261cc..b6dfdf06 100644 --- a/test-ts/account.test.ts +++ b/test-ts/account.test.ts @@ -17,18 +17,20 @@ import { LOCKED_GOLD_UNLOCKING_PERIOD, mineToNextEpoch, randomSigner, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, REGISTRY_ADDRESS, resetNetwork, timeTravel, } from "./utils"; +import { registerValidatorAndAddToGroupMembers, registerValidatorGroup } from "./utils-validators"; after(() => { hre.kit.stop(); }); describe("Account", () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let snapshotId: any; + let accountsInstance: AccountsWrapper; let lockedGold: LockedGoldWrapper; let election: ElectionWrapper; @@ -79,12 +81,6 @@ describe("Account", () => { await registerValidatorAndAddToGroupMembers(groups[i], validators[i], validatorWallet); } - accountsInstance = await hre.kit.contracts.getAccounts(); - lockedGold = await hre.kit.contracts.getLockedGold(); - election = await hre.kit.contracts.getElection(); - }); - - beforeEach(async () => { await hre.deployments.fixture("TestAccount"); owner = await hre.ethers.getNamedSigner("owner"); pauser = owner; @@ -92,6 +88,18 @@ describe("Account", () => { await account.connect(owner).setManager(manager.address); await account.connect(owner).setPauser(); governance = await hre.ethers.getContract("MockGovernance"); + + accountsInstance = await hre.kit.contracts.getAccounts(); + lockedGold = await hre.kit.contracts.getLockedGold(); + election = await hre.kit.contracts.getElection(); + }); + + beforeEach(async () => { + snapshotId = await hre.ethers.provider.send("evm_snapshot", []); + }); + + afterEach(async () => { + await hre.ethers.provider.send("evm_revert", [snapshotId]); }); it("should create an account on the core Accounts contract", async () => { diff --git a/test-ts/address-sorted-linked-list.test.ts b/test-ts/address-sorted-linked-list.test.ts index 567b769a..636635ec 100644 --- a/test-ts/address-sorted-linked-list.test.ts +++ b/test-ts/address-sorted-linked-list.test.ts @@ -12,6 +12,9 @@ after(() => { }); describe("AddressSortedLinkedList", () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let snapshotId: any; + let addressSortedLinkedList: MockAddressSortedLinkedList; let accounts: string[] = []; @@ -21,9 +24,7 @@ describe("AddressSortedLinkedList", () => { } catch (error) { console.error(error); } - }); - beforeEach(async () => { const Lib = await hre.ethers.getContractFactory("AddressSortedLinkedList"); const lib = await Lib.deploy(); await lib.deployed(); @@ -38,6 +39,14 @@ describe("AddressSortedLinkedList", () => { accounts = await hre.web3.eth.getAccounts(); }); + beforeEach(async () => { + snapshotId = await hre.ethers.provider.send("evm_snapshot", []); + }); + + afterEach(async () => { + await hre.ethers.provider.send("evm_revert", [snapshotId]); + }); + describe("#insert()", () => { let key: string; const numerator = 2; diff --git a/test-ts/default-strategy.test.ts b/test-ts/default-strategy.test.ts index 69c9097a..24601aaa 100644 --- a/test-ts/default-strategy.test.ts +++ b/test-ts/default-strategy.test.ts @@ -25,26 +25,28 @@ import { MockVote } from "../typechain-types/MockVote"; import { SpecificGroupStrategy } from "../typechain-types/SpecificGroupStrategy"; import { ADDRESS_ZERO, - deregisterValidatorGroup, - electGroup, - electMockValidatorGroupsAndUpdate, getDefaultGroups, getOrderedActiveGroups, getUnsortedGroups, mineToNextEpoch, prepareOverflow, randomSigner, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, REGISTRY_ADDRESS, - removeMembersFromGroup, resetNetwork, revokeElectionOnMockValidatorGroupsAndUpdate, updateGroupCeloBasedOnProtocolStCelo, - updateGroupSlashingMultiplier, updateMaxNumberOfGroups, } from "./utils"; import { OrderedGroup } from "./utils-interfaces"; +import { + deregisterValidatorGroup, + electGroup, + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, + removeMembersFromGroup, + updateGroupSlashingMultiplier, +} from "./utils-validators"; after(() => { hre.kit.stop(); diff --git a/test-ts/end-to-end-overflow.test.ts b/test-ts/end-to-end-overflow.test.ts index 7a63a36e..8c1cc7e6 100644 --- a/test-ts/end-to-end-overflow.test.ts +++ b/test-ts/end-to-end-overflow.test.ts @@ -15,17 +15,19 @@ import { MockGroupHealth } from "../typechain-types/MockGroupHealth"; import { SpecificGroupStrategy } from "../typechain-types/SpecificGroupStrategy"; import { activateAndVoteTest, - activateValidators, - electMockValidatorGroupsAndUpdate, prepareOverflow, randomSigner, rebalanceDefaultGroups, rebalanceGroups, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, resetNetwork, upgradeToMockGroupHealthE2E, } from "./utils"; +import { + activateValidators, + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, +} from "./utils-validators"; after(() => { hre.kit.stop(); @@ -131,7 +133,7 @@ describe("e2e overflow test", () => { await activateValidators( defaultStrategy, groupHealthContract as unknown as GroupHealth, - multisigOwner0.address, + multisigOwner0, activatedGroupAddresses ); }); diff --git a/test-ts/end-to-end-specific-group-strategy.test.ts b/test-ts/end-to-end-specific-group-strategy.test.ts index a4008b57..5011f7f9 100644 --- a/test-ts/end-to-end-specific-group-strategy.test.ts +++ b/test-ts/end-to-end-specific-group-strategy.test.ts @@ -15,9 +15,7 @@ import { SpecificGroupStrategy } from "../typechain-types/SpecificGroupStrategy" import { StakedCelo } from "../typechain-types/StakedCelo"; import { activateAndVoteTest, - activateValidators, distributeEpochRewards, - electMockValidatorGroupsAndUpdate, getGroupsOfAllStrategies, getRealVsExpectedCeloForGroups, LOCKED_GOLD_UNLOCKING_PERIOD, @@ -25,13 +23,17 @@ import { randomSigner, rebalanceDefaultGroups, rebalanceGroups, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, resetNetwork, revokeElectionOnMockValidatorGroupsAndUpdate, timeTravel, upgradeToMockGroupHealthE2E, } from "./utils"; +import { + activateValidators, + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, +} from "./utils-validators"; after(() => { hre.kit.stop(); @@ -154,7 +156,7 @@ describe("e2e specific group strategy voting", () => { await activateValidators( defaultStrategy, groupHealthContract as unknown as GroupHealth, - multisigOwner0.address, + multisigOwner0, activatedGroupAddresses ); }); diff --git a/test-ts/end-to-end-vote-proposal.test.ts b/test-ts/end-to-end-vote-proposal.test.ts index 8578dd3f..afffc49a 100644 --- a/test-ts/end-to-end-vote-proposal.test.ts +++ b/test-ts/end-to-end-vote-proposal.test.ts @@ -17,18 +17,20 @@ import { StakedCelo } from "../typechain-types/StakedCelo"; import { Vote } from "../typechain-types/Vote"; import { activateAndVoteTest, - activateValidators, distributeEpochRewards, - electMockValidatorGroupsAndUpdate, impersonateAccount, mineToNextEpoch, randomSigner, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, resetNetwork, timeTravel, upgradeToMockGroupHealthE2E, } from "./utils"; +import { + activateValidators, + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, +} from "./utils-validators"; after(() => { hre.kit.stop(); @@ -131,7 +133,7 @@ describe("e2e governance vote", () => { await activateValidators( defaultStrategyContract, groupHealthContract as unknown as GroupHealth, - multisigOwner0.address, + multisigOwner0, activatedGroupAddresses ); }); diff --git a/test-ts/end-to-end.test.ts b/test-ts/end-to-end.test.ts index 5eba07ea..ee6038ac 100644 --- a/test-ts/end-to-end.test.ts +++ b/test-ts/end-to-end.test.ts @@ -12,20 +12,22 @@ import { SpecificGroupStrategy } from "../typechain-types/SpecificGroupStrategy" import { StakedCelo } from "../typechain-types/StakedCelo"; import { activateAndVoteTest, - activateValidators, distributeEpochRewards, - electMockValidatorGroupsAndUpdate, LOCKED_GOLD_UNLOCKING_PERIOD, mineToNextEpoch, randomSigner, rebalanceDefaultGroups, rebalanceGroups, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, resetNetwork, timeTravel, upgradeToMockGroupHealthE2E, } from "./utils"; +import { + activateValidators, + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, +} from "./utils-validators"; after(() => { hre.kit.stop(); @@ -119,7 +121,7 @@ describe("e2e", () => { await activateValidators( defaultStrategyContract, groupHealthContract as unknown as GroupHealth, - multisigOwner0.address, + multisigOwner0, activatedGroupAddresses ); }); diff --git a/test-ts/group-health.test.ts b/test-ts/group-health.test.ts index 8b4e897c..b068468a 100644 --- a/test-ts/group-health.test.ts +++ b/test-ts/group-health.test.ts @@ -14,18 +14,20 @@ import { MockRegistry } from "../typechain-types/MockRegistry"; import { MockValidators } from "../typechain-types/MockValidators"; import { ADDRESS_ZERO, - deregisterValidatorGroup, - electMockValidatorGroupsAndUpdate, mineToNextEpoch, randomSigner, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, REGISTRY_ADDRESS, - removeMembersFromGroup, resetNetwork, revokeElectionOnMockValidatorGroupsAndUpdate, - updateGroupSlashingMultiplier, } from "./utils"; +import { + deregisterValidatorGroup, + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, + removeMembersFromGroup, + updateGroupSlashingMultiplier, +} from "./utils-validators"; after(() => { hre.kit.stop(); diff --git a/test-ts/manager.test.ts b/test-ts/manager.test.ts index 6b9d8b95..96b6122f 100644 --- a/test-ts/manager.test.ts +++ b/test-ts/manager.test.ts @@ -25,7 +25,6 @@ import { MockVote } from "../typechain-types/MockVote"; import { SpecificGroupStrategy } from "../typechain-types/SpecificGroupStrategy"; import { ADDRESS_ZERO, - electMockValidatorGroupsAndUpdate, getDefaultGroups, getImpersonatedSigner, getSpecificGroups, @@ -33,14 +32,17 @@ import { prepareOverflow, randomSigner, rebalanceDefaultGroups, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, REGISTRY_ADDRESS, resetNetwork, revokeElectionOnMockValidatorGroupsAndUpdate, updateGroupCeloBasedOnProtocolStCelo, - updateGroupSlashingMultiplier, } from "./utils"; +import { + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, + updateGroupSlashingMultiplier, +} from "./utils-validators"; const sum = (xs: BigNumber[]): BigNumber => xs.reduce((a, b) => a.add(b)); diff --git a/test-ts/multisig.test.ts b/test-ts/multisig.test.ts index 336e4170..a07d62ef 100644 --- a/test-ts/multisig.test.ts +++ b/test-ts/multisig.test.ts @@ -9,6 +9,10 @@ import { PausableTest } from "../typechain-types/PausableTest"; import { ProposalTester } from "../typechain-types/ProposalTester"; import { ADDRESS_ZERO, DAY, getImpersonatedSigner, randomSigner, timeTravel } from "./utils"; +after(() => { + hre.kit.stop(); +}); + /** * Invokes the multisig's submitProposal, waits for the confirmation event * and returns the generated proposalId. @@ -87,6 +91,9 @@ async function multiSigInitialize(owners: string[], requiredSignatures: number) } describe("MultiSig", () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let snapshotId: any; + let multiSig: MultiSig; let owner1: SignerWithAddress; let owner2: SignerWithAddress; @@ -100,7 +107,7 @@ describe("MultiSig", () => { const requiredSignatures = 2; const delay = 7 * DAY; - beforeEach(async () => { + before(async () => { await hre.deployments.fixture("TestMultiSig"); multiSig = await hre.ethers.getContract("MultiSig"); await hre.deployments.fixture("TestPausable"); @@ -120,6 +127,14 @@ describe("MultiSig", () => { owners = [owner1.address, owner2.address]; }); + beforeEach(async () => { + snapshotId = await hre.ethers.provider.send("evm_snapshot", []); + }); + + afterEach(async () => { + await hre.ethers.provider.send("evm_revert", [snapshotId]); + }); + describe("#constructor", () => { it("should have set the delay to 3 days", async () => { expect(await multiSig.minDelay()).to.deep.equal(3 * DAY); diff --git a/test-ts/pausable.test.ts b/test-ts/pausable.test.ts index 303d23fe..5efecf44 100644 --- a/test-ts/pausable.test.ts +++ b/test-ts/pausable.test.ts @@ -5,12 +5,19 @@ import hre from "hardhat"; import { PausableTest } from "../typechain-types/PausableTest"; import { ADDRESS_ZERO, randomSigner } from "./utils"; +after(() => { + hre.kit.stop(); +}); + describe("Pausable", () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let snapshotId: any; + let pausableTest: PausableTest; let pauser: SignerWithAddress; let nonPauser: SignerWithAddress; - beforeEach(async () => { + before(async () => { await hre.deployments.fixture("TestPausable"); pausableTest = await hre.ethers.getContract("PausableTest"); [pauser] = await randomSigner(parseUnits("100")); @@ -18,6 +25,14 @@ describe("Pausable", () => { await pausableTest.setPauser(pauser.address); }); + beforeEach(async () => { + snapshotId = await hre.ethers.provider.send("evm_snapshot", []); + }); + + afterEach(async () => { + await hre.ethers.provider.send("evm_revert", [snapshotId]); + }); + describe("#pause", () => { it("sets the contract to paused", async () => { await pausableTest.connect(pauser).pause(); diff --git a/test-ts/proxy-deploy.test.ts b/test-ts/proxy-deploy.test.ts index 72fbde45..c858363b 100644 --- a/test-ts/proxy-deploy.test.ts +++ b/test-ts/proxy-deploy.test.ts @@ -4,7 +4,8 @@ import { expect } from "chai"; import { Contract, ContractFactory } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import hre from "hardhat"; -import { randomAddress, randomSigner, submitAndExecuteProposal, waitForEvent } from "./utils"; +import { randomAddress, randomSigner } from "./utils"; +import { submitAndExecuteMultiSigProposal } from "./utils-multisig"; interface ProxyDeployTestData { contractName: string; @@ -103,11 +104,11 @@ describe("Contract deployed via proxy", () => { describe("when called by the owner", () => { it("can transfer ownership", async () => { - await submitAndExecuteProposal( - multisigOwner0.address, + await submitAndExecuteMultiSigProposal( [contract.address], ["0"], - [contract.interface.encodeFunctionData("transferOwnership", [newOwner.address])] + [contract.interface.encodeFunctionData("transferOwnership", [newOwner.address])], + multisigOwner0 ); expect(await contract.owner()).to.eq(newOwner.address); @@ -115,15 +116,16 @@ describe("Contract deployed via proxy", () => { it("can update the implementation", async () => { const newImplementation = (await contractFactory.deploy()).address; + const theProxy = await hre.ethers.getContract(`${test.contractName}_Proxy`); - await submitAndExecuteProposal( - multisigOwner0.address, - [contract.address], - ["0"], - [contract.interface.encodeFunctionData("upgradeTo", [newImplementation])] - ); - - await waitForEvent(contract, "Upgraded", newImplementation); + await expect( + submitAndExecuteMultiSigProposal( + [contract.address], + ["0"], + [contract.interface.encodeFunctionData("upgradeTo", [newImplementation])], + multisigOwner0 + ) + ).to.emit(theProxy, "Upgraded"); }); }); diff --git a/test-ts/rebased-staked-celo.test.ts b/test-ts/rebased-staked-celo.test.ts index 75a5a4bc..475e14be 100644 --- a/test-ts/rebased-staked-celo.test.ts +++ b/test-ts/rebased-staked-celo.test.ts @@ -8,7 +8,14 @@ import { MockStakedCelo } from "../typechain-types/MockStakedCelo"; import { RebasedStakedCelo } from "../typechain-types/RebasedStakedCelo"; import { ADDRESS_ZERO, randomSigner, resetNetwork } from "./utils"; +after(() => { + hre.kit.stop(); +}); + describe("RebasedStakedCelo", () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let snapshotId: any; + let rebasedStakedCelo: RebasedStakedCelo; let stakedCelo: MockStakedCelo; let account: MockAccount; @@ -21,9 +28,7 @@ describe("RebasedStakedCelo", () => { before(async () => { await resetNetwork(); - }); - beforeEach(async () => { await hre.deployments.fixture("TestRebasedStakedCelo"); rebasedStakedCelo = await hre.ethers.getContract("RebasedStakedCelo"); stakedCelo = await hre.ethers.getContract("MockStakedCelo"); @@ -38,6 +43,14 @@ describe("RebasedStakedCelo", () => { await rebasedStakedCelo.connect(owner).setPauser(); }); + beforeEach(async () => { + snapshotId = await hre.ethers.provider.send("evm_snapshot", []); + }); + + afterEach(async () => { + await hre.ethers.provider.send("evm_revert", [snapshotId]); + }); + describe("#initialize()", () => { it("should be named 'Rebased Staked CELO'", async () => { const tokenName = await rebasedStakedCelo.name(); diff --git a/test-ts/specific_group_strategy.test.ts b/test-ts/specific_group_strategy.test.ts index 805f5406..a5875413 100644 --- a/test-ts/specific_group_strategy.test.ts +++ b/test-ts/specific_group_strategy.test.ts @@ -20,20 +20,22 @@ import { MockVote } from "../typechain-types/MockVote"; import { SpecificGroupStrategy } from "../typechain-types/SpecificGroupStrategy"; import { ADDRESS_ZERO, - deregisterValidatorGroup, - electMockValidatorGroupsAndUpdate, getBlockedSpecificGroupStrategies, getDefaultGroups, getImpersonatedSigner, getSpecificGroups, prepareOverflow, randomSigner, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, resetNetwork, revokeElectionOnMockValidatorGroupsAndUpdate, updateGroupCeloBasedOnProtocolStCelo, } from "./utils"; +import { + deregisterValidatorGroup, + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, +} from "./utils-validators"; after(() => { hre.kit.stop(); diff --git a/test-ts/staked-celo.test.ts b/test-ts/staked-celo.test.ts index 8180a693..f0cd4f82 100644 --- a/test-ts/staked-celo.test.ts +++ b/test-ts/staked-celo.test.ts @@ -6,7 +6,14 @@ import { MockManager } from "../typechain-types/MockManager"; import { StakedCelo } from "../typechain-types/StakedCelo"; import { ADDRESS_ZERO, impersonateAccount, randomSigner, resetNetwork } from "./utils"; +after(() => { + hre.kit.stop(); +}); + describe("StakedCelo", () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let snapshotId: any; + let stakedCelo: StakedCelo; let managerContract: MockManager; @@ -23,9 +30,7 @@ describe("StakedCelo", () => { pauser = owner; [nonManager] = await randomSigner(parseUnits("100")); [anAccount] = await randomSigner(parseUnits("100")); - }); - beforeEach(async () => { await hre.deployments.fixture("TestStakedCelo"); stakedCelo = await hre.ethers.getContract("StakedCelo"); managerContract = await hre.ethers.getContract("MockManager"); @@ -44,6 +49,14 @@ describe("StakedCelo", () => { await stakedCelo.connect(owner).setPauser(); }); + beforeEach(async () => { + snapshotId = await hre.ethers.provider.send("evm_snapshot", []); + }); + + afterEach(async () => { + await hre.ethers.provider.send("evm_revert", [snapshotId]); + }); + describe("#mint()", () => { it("mints the specified amount of stCELO to an address", async () => { await stakedCelo.connect(manager).mint(anAccount.address, 100); diff --git a/test-ts/utils-interfaces.ts b/test-ts/utils-interfaces.ts index 86bb0c95..867cf009 100644 --- a/test-ts/utils-interfaces.ts +++ b/test-ts/utils-interfaces.ts @@ -1,12 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable no-unused-vars */ -import { - BaseContract, - BigNumber as EthersBigNumber, - CallOverrides, - ContractTransaction, - Overrides, -} from "ethers"; +import { BaseContract, BigNumber as EthersBigNumber, ContractTransaction, Overrides } from "ethers"; export interface RebalanceContract extends BaseContract { rebalance( @@ -23,27 +17,6 @@ export interface ExpectVsReal { diff: EthersBigNumber; } -export interface DefaultGroupContract extends BaseContract { - getNumberOfGroups(overrides?: CallOverrides): Promise; - getGroupsHead( - overrides?: CallOverrides - ): Promise<[string, string] & { head: string; previousAddress: string }>; - getGroupPreviousAndNext( - key: string, - overrides?: CallOverrides - ): Promise<[string, string] & { previousAddress: string; nextAddress: string }>; - activateGroup( - group: string, - lesser: string, - greater: string, - overrides?: Overrides & { from?: string | Promise } - ): Promise; - addActivatableGroup( - group: string, - overrides?: Overrides & { from?: string | Promise } - ): Promise; -} - export interface OrderedGroup { group: string; stCelo: string; diff --git a/test-ts/utils-multisig.ts b/test-ts/utils-multisig.ts new file mode 100644 index 00000000..417d4f81 --- /dev/null +++ b/test-ts/utils-multisig.ts @@ -0,0 +1,22 @@ +import { BigNumberish, ContractTransaction, Signer } from "ethers"; +import hre from "hardhat"; +import { ProposalConfirmedEvent } from "../typechain-types/MultiSig"; +import { timeTravel } from "./utils"; + +export async function submitAndExecuteMultiSigProposal( + destinations: string[], + values: BigNumberish[], + payloads: string[], + signer: Signer +): Promise { + const multiSig = await hre.ethers.getContract("MultiSig"); + const tx = await multiSig.connect(signer).submitProposal(destinations, values, payloads); + const receipt = await tx.wait(); + const event = receipt.events?.find( + (event: ProposalConfirmedEvent) => event.event === "ProposalConfirmed" + ); + // @ts-ignore - proposalId not a compiled member of event.args + const proposalId = event?.args.proposalId; + await timeTravel((await multiSig.delay()).toNumber()); + return multiSig.connect(signer).executeProposal(proposalId); +} diff --git a/test-ts/utils-validators.ts b/test-ts/utils-validators.ts new file mode 100644 index 00000000..fa1ec3b0 --- /dev/null +++ b/test-ts/utils-validators.ts @@ -0,0 +1,287 @@ +import { CeloTxReceipt } from "@celo/connect"; +import { stringToSolidityBytes } from "@celo/contractkit/lib/wrappers/BaseWrapper"; +import { ValidatorsWrapper } from "@celo/contractkit/lib/wrappers/Validators"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { default as BigNumber, default as BigNumberJs } from "bignumber.js"; +import { BigNumber as EthersBigNumber, Signer, Wallet } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import hre, { kit } from "hardhat"; +import { DefaultStrategy } from "../typechain-types/DefaultStrategy"; +import { GroupHealth } from "../typechain-types/GroupHealth"; +import { MockGroupHealth } from "../typechain-types/MockGroupHealth"; +import { MockLockedGold } from "../typechain-types/MockLockedGold"; +import { MockRegistry } from "../typechain-types/MockRegistry"; +import { MockValidators } from "../typechain-types/MockValidators"; +import { + ADDRESS_ZERO, + DAY, + impersonateAccount, + mineToNextEpoch, + MIN_VALIDATOR_LOCKED_CELO, + timeTravel, +} from "./utils"; +import { submitAndExecuteMultiSigProposal } from "./utils-multisig"; + +// Locks the required CELO and registers as a validator group. +export async function registerValidatorGroup(account: SignerWithAddress, members = 1) { + const accounts = await kit.contracts.getAccounts(); + const tx = accounts.createAccount(); + await tx.sendAndWaitForReceipt({ + from: account.address, + }); + + const lockedGold = await kit.contracts.getLockedGold(); + + // lock up the minimum of 10k per validator + await lockedGold.lock().sendAndWaitForReceipt({ + from: account.address, + value: EthersBigNumber.from(MIN_VALIDATOR_LOCKED_CELO).mul(members).toString(), + }); + + const validators = await kit.contracts.getValidators(); + + await ( + await validators.registerValidatorGroup(new BigNumber("0")) + ).sendAndWaitForReceipt({ + from: account.address, + }); +} + +// Locks the required CELO and registers as a validator in the group `groupAddress` +export async function registerValidatorAndAddToGroupMembers( + group: SignerWithAddress, + validator: SignerWithAddress, + validatorWallet: Wallet +) { + await registerValidatorAndOnlyAffiliateToGroup(group, validator, validatorWallet); + await addValidatorToGroupMembers(group, validator); +} + +export async function registerValidatorAndOnlyAffiliateToGroup( + group: SignerWithAddress, + validator: SignerWithAddress, + validatorWallet: Wallet +) { + const accounts = await kit.contracts.getAccounts(); + + await accounts.createAccount().sendAndWaitForReceipt({ + from: validator.address, + }); + + const lockedGold = await kit.contracts.getLockedGold(); + + // lock up the 10k minimum + await lockedGold.lock().sendAndWaitForReceipt({ + from: validator.address, + value: MIN_VALIDATOR_LOCKED_CELO, + }); + + const validators = await kit.contracts.getValidators(); + + // Validators.sol needs a 64 byte public key, the one stored in a Wallet is 65 + // bytes. The first byte is unnecessary, and we also want to strip the leading + // 0x, so we `.slice(4)`. + const publicKey = validatorWallet.publicKey.slice(4); + // A random 64 byte hex string. Taken from the monorepo. + const blsPublicKey = + "0x4fa3f67fc913878b068d1fa1cdddc54913d3bf988dbe5a36a20fa888f20d4894c408a6773f3d7bde11154f2a3076b700d345a42fd25a0e5e83f4db5586ac7979ac2053cd95d8f2efd3e959571ceccaa743e02cf4be3f5d7aaddb0b06fc9aff00"; + const blsPoP = + "0xcdb77255037eb68897cd487fdd85388cbda448f617f874449d4b11588b0b7ad8ddc20d9bb450b513bb35664ea3923900"; + + await validators.registerValidator(publicKey, blsPublicKey, blsPoP).sendAndWaitForReceipt({ + from: validator.address, + }); + + // Affiliate validator with the group + await validators.affiliate(group.address).sendAndWaitForReceipt({ + from: validator.address, + }); +} + +export async function addValidatorToGroupMembers( + group: SignerWithAddress, + validator: SignerWithAddress +) { + const validators = await kit.contracts.getValidators(); + const tx = await validators.addMember(group.address, validator.address); + await tx.sendAndWaitForReceipt({ + from: group.address, + }); +} + +export async function removeMembersFromGroup(group: SignerWithAddress) { + // get validators contract + const validators = await kit.contracts.getValidators(); + + // get validator group + const validatorGroup = await validators.getValidatorGroup(group.address); + + // deaffiliate then deregister + const txs: Promise[] = []; + for (const validator of validatorGroup.members) { + const tx = validators.removeMember(validator).sendAndWaitForReceipt({ from: group.address }); + txs.push(tx); + } + + await Promise.all(txs); +} + +export async function deregisterValidatorGroup(group: SignerWithAddress) { + const validators = await kit.contracts.getValidators(); + await removeMembersFromGroup(group); + const groupRequirementEndTime = await validators.getGroupLockedGoldRequirements(); + + await timeTravel(groupRequirementEndTime.duration.toNumber() + 2 * DAY); + + await ( + await validators.deregisterValidatorGroup(group.address) + ).sendAndWaitForReceipt({ from: group.address }); +} + +export async function activateValidators( + defaultStrategyContract: DefaultStrategy, + groupHealthContract: GroupHealth, + multisigOwner: Signer, + groupAddresses: string[] +) { + let [nextGroup] = await defaultStrategyContract.getGroupsTail(); + for (let i = 0; i < groupAddresses.length; i++) { + const isGroupValid = await groupHealthContract.isGroupValid(groupAddresses[i]); + if (!isGroupValid) { + throw new Error(`Group ${groupAddresses[i]} is not valid group!`); + } + await submitAndExecuteMultiSigProposal( + [defaultStrategyContract.address], + ["0"], + [ + defaultStrategyContract.interface.encodeFunctionData("addActivatableGroup", [ + groupAddresses[i], + ]), + ], + multisigOwner + ); + await submitAndExecuteMultiSigProposal( + [defaultStrategyContract.address], + ["0"], + [ + defaultStrategyContract.interface.encodeFunctionData("activateGroup", [ + groupAddresses[i], + ADDRESS_ZERO, + nextGroup, + ]), + ], + multisigOwner + ); + nextGroup = groupAddresses[i]; + } +} + +export async function voteForGroup(groupAddress: string, voter: SignerWithAddress) { + const lockedGold = await kit.contracts.getLockedGold(); + const election = await kit.contracts.getElection(); + await lockedGold.lock().sendAndWaitForReceipt({ + from: voter.address, + value: parseUnits("1").toString(), + }); + + const voteTx = await election.vote(groupAddress, new BigNumberJs(parseUnits("1").toString())); + await voteTx.sendAndWaitForReceipt({ from: voter.address }); +} + +export async function activateVotesForGroup(voter: SignerWithAddress) { + const election = await kit.contracts.getElection(); + const activateTxs = await election.activate(voter.address); + const txs: Promise[] = []; + for (let i = 0; i < activateTxs.length; i++) { + const tx = activateTxs[i].sendAndWaitForReceipt({ from: voter.address }); + txs.push(tx); + } + await Promise.all(txs); +} + +export async function electGroup(groupAddress: string, voter: SignerWithAddress) { + await voteForGroup(groupAddress, voter); + await mineToNextEpoch(kit.web3); + await activateVotesForGroup(voter); +} + +export async function updateGroupSlashingMultiplier( + registryContract: MockRegistry, + lockedGoldContract: MockLockedGold, + validatorsContract: MockValidators, + group: SignerWithAddress, + mockSlasher: SignerWithAddress +) { + const coreContractsOwnerAddr = await registryContract.owner(); + + await impersonateAccount(coreContractsOwnerAddr); + const coreContractsOwner = await hre.ethers.getSigner(coreContractsOwnerAddr); + + await registryContract + .connect(coreContractsOwner) + .setAddressFor("MockSlasher", mockSlasher.address); + + await lockedGoldContract.connect(coreContractsOwner).addSlasher("MockSlasher"); + await validatorsContract.connect(mockSlasher).halveSlashingMultiplier(group.address); + + await mineToNextEpoch(hre.web3); +} + +export async function electMockValidatorGroupsAndUpdate( + validators: ValidatorsWrapper, + groupHealthContract: MockGroupHealth, + validatorGroups: string[], + revoke = false, + update = true, + makeOneValidatorGroupUseSigner = true +): Promise { + let validatorsProcessed = 0; + const mockedIndexes: number[] = []; + + for (let j = 0; j < validatorGroups.length; j++) { + const validatorGroup = validatorGroups[j]; + const isValidatorGroup = await validators.isValidatorGroup(validatorGroup); + + if (isValidatorGroup) { + const validatorGroupDetail = await validators.getValidatorGroup(validatorGroup); + for (let i = 0; i < validatorGroupDetail.members.length; i++) { + const memberOriginalAccount = validatorGroupDetail.members[i]; + const signer = makeOneValidatorGroupUseSigner + ? await makeValidatorUseSigner(memberOriginalAccount) + : memberOriginalAccount; + const mockIndex = validatorsProcessed++; + await groupHealthContract.setElectedValidator(mockIndex, revoke ? ADDRESS_ZERO : signer); + mockedIndexes.push(mockIndex); + } + } + if (update) { + await groupHealthContract.updateGroupHealth(validatorGroup); + } + + makeOneValidatorGroupUseSigner = false; + } + return mockedIndexes; +} + +async function makeValidatorUseSigner(validatorAddress: string) { + const newAccountWallet = hre.ethers.Wallet.createRandom(); + const newSignerAddress = await newAccountWallet.getAddress(); + + const accounts = await hre.kit.contracts.getAccounts(); + + const pop = await accounts.generateProofOfKeyPossessionLocally( + validatorAddress, + newSignerAddress, + newAccountWallet.privateKey + ); + const publicKey = stringToSolidityBytes(newAccountWallet.publicKey.slice(4)); + const authWithPubKey = await accounts["contract"].methods.authorizeValidatorSignerWithPublicKey( + newSignerAddress, + pop.v, + pop.r, + pop.s, + publicKey + ); + await authWithPubKey.send({ from: validatorAddress }); + return newSignerAddress; +} diff --git a/test-ts/utils.ts b/test-ts/utils.ts index 8d5489ac..5e9a9d6f 100644 --- a/test-ts/utils.ts +++ b/test-ts/utils.ts @@ -1,14 +1,12 @@ -import { CeloTxReceipt } from "@celo/connect"; import { AccountsWrapper } from "@celo/contractkit/lib/wrappers/Accounts"; -import { stringToSolidityBytes } from "@celo/contractkit/lib/wrappers/BaseWrapper"; import { ElectionWrapper } from "@celo/contractkit/lib/wrappers/Election"; import { LockedGoldWrapper } from "@celo/contractkit/lib/wrappers/LockedGold"; import { ValidatorsWrapper } from "@celo/contractkit/lib/wrappers/Validators"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { default as BigNumber, default as BigNumberJs } from "bignumber.js"; -import { BigNumber as EthersBigNumber, Contract, Wallet } from "ethers"; +import { default as BigNumberJs } from "bignumber.js"; +import { BigNumber as EthersBigNumber, Wallet } from "ethers"; import { formatEther, parseUnits } from "ethers/lib/utils"; -import hre, { ethers, kit } from "hardhat"; +import hre, { ethers } from "hardhat"; import Web3 from "web3"; import { ACCOUNT_ACTIVATE_AND_VOTE, @@ -24,17 +22,9 @@ import { Manager } from "../typechain-types/Manager"; import { MockAccount } from "../typechain-types/MockAccount"; import { MockDefaultStrategy } from "../typechain-types/MockDefaultStrategy"; import { MockGroupHealth } from "../typechain-types/MockGroupHealth"; -import { MockLockedGold } from "../typechain-types/MockLockedGold"; -import { MockRegistry } from "../typechain-types/MockRegistry"; -import { MockValidators } from "../typechain-types/MockValidators"; import { SpecificGroupStrategy } from "../typechain-types/SpecificGroupStrategy"; import electionContractData from "./code/abi/electionAbi.json"; -import { - DefaultGroupContract, - ExpectVsReal, - OrderedGroup, - RebalanceContract, -} from "./utils-interfaces"; +import { ExpectVsReal, OrderedGroup, RebalanceContract } from "./utils-interfaces"; export const ADDRESS_ZERO = "0x0000000000000000000000000000000000000000"; export const REGISTRY_ADDRESS = "0x000000000000000000000000000000000000ce10"; @@ -42,218 +32,11 @@ export const REGISTRY_ADDRESS = "0x000000000000000000000000000000000000ce10"; // This is hardcoded into ganache export const BLOCKS_PER_EPOCH = 100; -const MIN_VALIDATOR_LOCKED_CELO = Web3.utils.toWei("10000", "ether"); +export const MIN_VALIDATOR_LOCKED_CELO = Web3.utils.toWei("10000", "ether"); const HOUR = 60 * 60; export const DAY = 24 * HOUR; export const LOCKED_GOLD_UNLOCKING_PERIOD = 3 * DAY; -// ---- Validator utils ---- - -// Locks the required CELO and registers as a validator group. -export async function registerValidatorGroup(account: SignerWithAddress, members = 1) { - const accounts = await kit.contracts.getAccounts(); - const tx = accounts.createAccount(); - await tx.sendAndWaitForReceipt({ - from: account.address, - }); - - const lockedGold = await kit.contracts.getLockedGold(); - - // lock up the minimum of 10k per validator - await lockedGold.lock().sendAndWaitForReceipt({ - from: account.address, - value: EthersBigNumber.from(MIN_VALIDATOR_LOCKED_CELO).mul(members).toString(), - }); - - const validators = await kit.contracts.getValidators(); - - await ( - await validators.registerValidatorGroup(new BigNumber("0")) - ).sendAndWaitForReceipt({ - from: account.address, - }); -} - -// Locks the required CELO and registers as a validator in the group `groupAddress` -export async function registerValidatorAndAddToGroupMembers( - group: SignerWithAddress, - validator: SignerWithAddress, - validatorWallet: Wallet -) { - await registerValidatorAndOnlyAffiliateToGroup(group, validator, validatorWallet); - await addValidatorToGroupMembers(group, validator); -} - -export async function registerValidatorAndOnlyAffiliateToGroup( - group: SignerWithAddress, - validator: SignerWithAddress, - validatorWallet: Wallet -) { - const accounts = await kit.contracts.getAccounts(); - - await accounts.createAccount().sendAndWaitForReceipt({ - from: validator.address, - }); - - const lockedGold = await kit.contracts.getLockedGold(); - - // lock up the 10k minimum - await lockedGold.lock().sendAndWaitForReceipt({ - from: validator.address, - value: MIN_VALIDATOR_LOCKED_CELO, - }); - - const validators = await kit.contracts.getValidators(); - - // Validators.sol needs a 64 byte public key, the one stored in a Wallet is 65 - // bytes. The first byte is unnecessary, and we also want to strip the leading - // 0x, so we `.slice(4)`. - const publicKey = validatorWallet.publicKey.slice(4); - // A random 64 byte hex string. Taken from the monorepo. - const blsPublicKey = - "0x4fa3f67fc913878b068d1fa1cdddc54913d3bf988dbe5a36a20fa888f20d4894c408a6773f3d7bde11154f2a3076b700d345a42fd25a0e5e83f4db5586ac7979ac2053cd95d8f2efd3e959571ceccaa743e02cf4be3f5d7aaddb0b06fc9aff00"; - const blsPoP = - "0xcdb77255037eb68897cd487fdd85388cbda448f617f874449d4b11588b0b7ad8ddc20d9bb450b513bb35664ea3923900"; - - await validators.registerValidator(publicKey, blsPublicKey, blsPoP).sendAndWaitForReceipt({ - from: validator.address, - }); - - // Affiliate validator with the group - await validators.affiliate(group.address).sendAndWaitForReceipt({ - from: validator.address, - }); -} - -export async function addValidatorToGroupMembers( - group: SignerWithAddress, - validator: SignerWithAddress -) { - const validators = await kit.contracts.getValidators(); - const tx = await validators.addMember(group.address, validator.address); - await tx.sendAndWaitForReceipt({ - from: group.address, - }); -} - -export async function removeMembersFromGroup(group: SignerWithAddress) { - // get validators contract - const validators = await kit.contracts.getValidators(); - - // get validator group - const validatorGroup = await validators.getValidatorGroup(group.address); - - // deaffiliate then deregister - const txs: Promise[] = []; - for (const validator of validatorGroup.members) { - const tx = validators.removeMember(validator).sendAndWaitForReceipt({ from: group.address }); - txs.push(tx); - } - - await Promise.all(txs); -} - -export async function deregisterValidatorGroup(group: SignerWithAddress) { - const validators = await kit.contracts.getValidators(); - await removeMembersFromGroup(group); - const groupRequirementEndTime = await validators.getGroupLockedGoldRequirements(); - - await timeTravel(groupRequirementEndTime.duration.toNumber() + 2 * DAY); - - await ( - await validators.deregisterValidatorGroup(group.address) - ).sendAndWaitForReceipt({ from: group.address }); -} - -export async function activateValidators( - defaultStrategyContract: DefaultStrategy, - groupHealthContract: GroupHealth, - multisigOwner: string, - groupAddresses: string[] -) { - let [nextGroup] = await defaultStrategyContract.getGroupsTail(); - for (let i = 0; i < groupAddresses.length; i++) { - const isGroupValid = await groupHealthContract.isGroupValid(groupAddresses[i]); - if (!isGroupValid) { - throw new Error(`Group ${groupAddresses[i]} is not valid group!`); - } - await submitAndExecuteProposal( - multisigOwner, - [defaultStrategyContract.address], - ["0"], - [ - defaultStrategyContract.interface.encodeFunctionData("addActivatableGroup", [ - groupAddresses[i], - ]), - ] - ); - await submitAndExecuteProposal( - multisigOwner, - [defaultStrategyContract.address], - ["0"], - [ - defaultStrategyContract.interface.encodeFunctionData("activateGroup", [ - groupAddresses[i], - ADDRESS_ZERO, - nextGroup, - ]), - ] - ); - nextGroup = groupAddresses[i]; - } -} - -export async function voteForGroup(groupAddress: string, voter: SignerWithAddress) { - const lockedGold = await kit.contracts.getLockedGold(); - const election = await kit.contracts.getElection(); - await lockedGold.lock().sendAndWaitForReceipt({ - from: voter.address, - value: parseUnits("1").toString(), - }); - - const voteTx = await election.vote(groupAddress, new BigNumberJs(parseUnits("1").toString())); - await voteTx.sendAndWaitForReceipt({ from: voter.address }); -} - -export async function activateVotesForGroup(voter: SignerWithAddress) { - const election = await kit.contracts.getElection(); - const activateTxs = await election.activate(voter.address); - const txs: Promise[] = []; - for (let i = 0; i < activateTxs.length; i++) { - const tx = activateTxs[i].sendAndWaitForReceipt({ from: voter.address }); - txs.push(tx); - } - await Promise.all(txs); -} - -export async function electGroup(groupAddress: string, voter: SignerWithAddress) { - await voteForGroup(groupAddress, voter); - await mineToNextEpoch(kit.web3); - await activateVotesForGroup(voter); -} - -export async function updateGroupSlashingMultiplier( - registryContract: MockRegistry, - lockedGoldContract: MockLockedGold, - validatorsContract: MockValidators, - group: SignerWithAddress, - mockSlasher: SignerWithAddress -) { - const coreContractsOwnerAddr = await registryContract.owner(); - - await impersonateAccount(coreContractsOwnerAddr); - const coreContractsOwner = await hre.ethers.getSigner(coreContractsOwnerAddr); - - await registryContract - .connect(coreContractsOwner) - .setAddressFor("MockSlasher", mockSlasher.address); - - await lockedGoldContract.connect(coreContractsOwner).addSlasher("MockSlasher"); - await validatorsContract.connect(mockSlasher).halveSlashingMultiplier(group.address); - - await mineToNextEpoch(hre.web3); -} - // ---- Account utils ---- export function randomAddress(): string { @@ -431,26 +214,6 @@ export async function submitAndExecuteProposal( } } -export async function waitForEvent( - contract: Contract, - eventName: string, - expectedValue: string, - timeout = 10000 -) { - await new Promise((resolve, reject) => { - setTimeout(() => { - reject( - `Event ${eventName} with expectedValue: ${expectedValue} wasn't emitted in timely manner.` - ); - }, timeout); - contract.on(eventName, (implementation) => { - if (implementation == expectedValue) { - resolve(); - } - }); - }); -} - export async function activateAndVoteTest(deployerAccountName = "deployer") { try { await hre.run(ACCOUNT_ACTIVATE_AND_VOTE, { @@ -485,7 +248,9 @@ export async function setGovernanceConcurrentProposals(count: number) { }); } -export async function getDefaultGroups(defaultStrategy: DefaultGroupContract): Promise { +export async function getDefaultGroups( + defaultStrategy: DefaultStrategy | MockDefaultStrategy +): Promise { const activeGroupsLengthPromise = defaultStrategy.getNumberOfGroups(); let [key] = await defaultStrategy.getGroupsHead(); @@ -626,65 +391,6 @@ export async function rebalanceGroups( await rebalanceInternal(managerContract, expectedVsReal); } -export async function electMockValidatorGroupsAndUpdate( - validators: ValidatorsWrapper, - groupHealthContract: MockGroupHealth, - validatorGroups: string[], - revoke = false, - update = true, - makeOneValidatorGroupUseSigner = true -): Promise { - let validatorsProcessed = 0; - const mockedIndexes: number[] = []; - - for (let j = 0; j < validatorGroups.length; j++) { - const validatorGroup = validatorGroups[j]; - const isValidatorGroup = await validators.isValidatorGroup(validatorGroup); - - if (isValidatorGroup) { - const validatorGroupDetail = await validators.getValidatorGroup(validatorGroup); - for (let i = 0; i < validatorGroupDetail.members.length; i++) { - const memberOriginalAccount = validatorGroupDetail.members[i]; - const signer = makeOneValidatorGroupUseSigner - ? await makeValidatorUseSigner(memberOriginalAccount) - : memberOriginalAccount; - const mockIndex = validatorsProcessed++; - await groupHealthContract.setElectedValidator(mockIndex, revoke ? ADDRESS_ZERO : signer); - mockedIndexes.push(mockIndex); - } - } - if (update) { - await groupHealthContract.updateGroupHealth(validatorGroup); - } - - makeOneValidatorGroupUseSigner = false; - } - return mockedIndexes; -} - -async function makeValidatorUseSigner(validatorAddress: string) { - const newAccountWallet = hre.ethers.Wallet.createRandom(); - const newSignerAddress = await newAccountWallet.getAddress(); - - const accounts = await hre.kit.contracts.getAccounts(); - - const pop = await accounts.generateProofOfKeyPossessionLocally( - validatorAddress, - newSignerAddress, - newAccountWallet.privateKey - ); - const publicKey = stringToSolidityBytes(newAccountWallet.publicKey.slice(4)); - const authWithPubKey = await accounts["contract"].methods.authorizeValidatorSignerWithPublicKey( - newSignerAddress, - pop.v, - pop.r, - pop.s, - publicKey - ); - await authWithPubKey.send({ from: validatorAddress }); - return newSignerAddress; -} - export async function revokeElectionOnMockValidatorGroupsAndUpdate( validators: ValidatorsWrapper, accounts: AccountsWrapper, @@ -739,21 +445,6 @@ export async function upgradeToMockGroupHealthE2E( return mockGroupHealthFactory.attach(groupHealthContract.address); } -export async function getIndexesOfElectedValidatorGroupMembers( - election: ElectionWrapper, - validators: ValidatorsWrapper, - validatorGroup: string -) { - const validatorGroupDetail = await validators.getValidatorGroup(validatorGroup); - const currentValidatorSigners = await election.getCurrentValidatorSigners(); - const finalIndexes: number[] = []; - for (const member of validatorGroupDetail.members) { - const index = currentValidatorSigners.indexOf(member); - finalIndexes.push(index === -1 ? currentValidatorSigners.length : index); - } - return finalIndexes; -} - export async function getOrderedActiveGroups( defaultStrategyContract: MockDefaultStrategy, account?: Account @@ -787,7 +478,7 @@ export async function getUnsortedGroups(defaultStrategyContract: MockDefaultStra } export async function prepareOverflow( - defaultStrategyContract: DefaultGroupContract, + defaultStrategyContract: DefaultStrategy | MockDefaultStrategy, election: ElectionWrapper, lockedGold: LockedGoldWrapper, voter: SignerWithAddress, diff --git a/test-ts/vote.test.ts b/test-ts/vote.test.ts index 729a4610..d2722b52 100644 --- a/test-ts/vote.test.ts +++ b/test-ts/vote.test.ts @@ -15,19 +15,28 @@ import { MockGroupHealth } from "../typechain-types/MockGroupHealth"; import { Vote } from "../typechain-types/Vote"; import { ADDRESS_ZERO, - electMockValidatorGroupsAndUpdate, getImpersonatedSigner, mineToNextEpoch, randomSigner, - registerValidatorAndAddToGroupMembers, - registerValidatorGroup, resetNetwork, setGovernanceConcurrentProposals, timeTravel, } from "./utils"; +import { + electMockValidatorGroupsAndUpdate, + registerValidatorAndAddToGroupMembers, + registerValidatorGroup, +} from "./utils-validators"; + +after(() => { + hre.kit.stop(); +}); // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-explicit-any describe("Vote", async function (this: any) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let snapshotId: any; + this.timeout(0); // Disable test timeout let managerContract: Manager; let groupHealthContract: MockGroupHealth; @@ -163,9 +172,7 @@ describe("Vote", async function (this: any) { } catch (error) { console.error(error); } - }); - beforeEach(async () => { await hre.deployments.fixture("TestVote"); governanceWrapper = await hre.kit.contracts.getGovernance(); managerContract = await hre.ethers.getContract("Manager"); @@ -212,6 +219,14 @@ describe("Vote", async function (this: any) { } }); + beforeEach(async () => { + snapshotId = await hre.ethers.provider.send("evm_snapshot", []); + }); + + afterEach(async () => { + await hre.ethers.provider.send("evm_revert", [snapshotId]); + }); + describe("#getVoteWeight()", () => { it("should return 0 when account doesn't have any stCelo", async () => { const voteWeight = await voteContract.getVoteWeight(depositor0.address);