Skip to content

Commit 7f556a2

Browse files
committed
exit validator tests added
1 parent 4a0dcec commit 7f556a2

File tree

3 files changed

+194
-0
lines changed

3 files changed

+194
-0
lines changed

test/common/events.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export const Events = {
22
VALIDATOR_ADDED: "ValidatorAdded",
33
VALIDATOR_REMOVED: "ValidatorRemoved",
4+
VALIDATOR_EXITED: "ValidatorExited",
45
CLUSTER_LIQUIDATED: "ClusterLiquidated",
56
CLUSTER_REACTIVATED: "ClusterReactivated",
67
CLUSTER_DEPOSITED: "ClusterDeposited",
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { expect } from "chai";
2+
import type { NetworkConnection } from "hardhat/types/network";
3+
import type { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/types";
4+
import { getTestConnection } from "../../setup/connection.ts";
5+
import { ssvClustersHarnessFixture } from "../../setup/fixtures.ts";
6+
import type { NetworkHelpersType } from "../../common/types.ts";
7+
import { makePublicKey } from "../../common/helpers.ts";
8+
import { DEFAULT_ETH_REGISTER_VALUE, DEFAULT_SHARES, EMPTY_CLUSTER } from "../../common/constants.ts";
9+
import { Events } from "../../common/events.ts";
10+
import { Errors } from "../../common/errors.ts";
11+
12+
const createCluster = () => ({
13+
...EMPTY_CLUSTER,
14+
active: true,
15+
});
16+
17+
describe("SSVClusters function `bulkExitValidator()`", async () => {
18+
let connection: NetworkConnection<"generic">;
19+
let networkHelpers: NetworkHelpersType;
20+
21+
let clusterOwner: HardhatEthersSigner;
22+
23+
before(async function () {
24+
({ connection, networkHelpers } = await getTestConnection());
25+
26+
[clusterOwner] = await connection.ethers.getSigners();
27+
});
28+
29+
const deploySSVClustersAndPrepareOperatorsFixture = async () => {
30+
return ssvClustersHarnessFixture(connection);
31+
};
32+
33+
it("Exits multiple validators and emits events", async function () {
34+
const { clusters, operatorIds } =
35+
await networkHelpers.loadFixture(deploySSVClustersAndPrepareOperatorsFixture);
36+
37+
const publicKeys = [makePublicKey(1), makePublicKey(2)];
38+
await clusters.bulkRegisterValidator(
39+
publicKeys,
40+
operatorIds,
41+
[DEFAULT_SHARES, DEFAULT_SHARES],
42+
0,
43+
createCluster(),
44+
{ value: DEFAULT_ETH_REGISTER_VALUE }
45+
);
46+
47+
const tx = await clusters.bulkExitValidator(publicKeys, operatorIds);
48+
49+
await expect(tx).to.emit(clusters, Events.VALIDATOR_EXITED).withArgs(clusterOwner.address, operatorIds, publicKeys[0]);
50+
await expect(tx).to.emit(clusters, Events.VALIDATOR_EXITED).withArgs(clusterOwner.address, operatorIds, publicKeys[1]);
51+
});
52+
53+
it("Is reverted with 'ValidatorDoesNotExist' when no public keys are provided", async function () {
54+
const { clusters, operatorIds } =
55+
await networkHelpers.loadFixture(deploySSVClustersAndPrepareOperatorsFixture);
56+
57+
await expect(clusters.bulkExitValidator(
58+
[],
59+
operatorIds
60+
)).to.be.revertedWithCustomError(clusters, Errors.VALIDATOR_DOES_NOT_EXIST);
61+
});
62+
63+
it("Is reverted with 'IncorrectValidatorStateWithData' when any validator is not registered", async function () {
64+
const { clusters, operatorIds } =
65+
await networkHelpers.loadFixture(deploySSVClustersAndPrepareOperatorsFixture);
66+
67+
const publicKeys = [makePublicKey(1), makePublicKey(2)];
68+
await clusters.registerValidator(
69+
publicKeys[0],
70+
operatorIds,
71+
DEFAULT_SHARES,
72+
0,
73+
createCluster(),
74+
{ value: DEFAULT_ETH_REGISTER_VALUE }
75+
);
76+
77+
await expect(clusters.bulkExitValidator(
78+
publicKeys,
79+
operatorIds
80+
)).to.be.revertedWithCustomError(clusters, Errors.INCORRECT_VALIDATOR_STATE_WITH_DATA).withArgs(publicKeys[1]);
81+
});
82+
83+
it("Is reverted with 'IncorrectValidatorStateWithData' when operator ids do not match stored validators", async function () {
84+
const { clusters, operatorIds } =
85+
await networkHelpers.loadFixture(deploySSVClustersAndPrepareOperatorsFixture);
86+
87+
const publicKeys = [makePublicKey(1), makePublicKey(2)];
88+
await clusters.bulkRegisterValidator(
89+
publicKeys,
90+
operatorIds,
91+
[DEFAULT_SHARES, DEFAULT_SHARES],
92+
0,
93+
createCluster(),
94+
{ value: DEFAULT_ETH_REGISTER_VALUE }
95+
);
96+
97+
const mismatchedOperatorIds = [...operatorIds];
98+
mismatchedOperatorIds[0] = mismatchedOperatorIds[0] + 1n;
99+
100+
await expect(clusters.bulkExitValidator(
101+
publicKeys,
102+
mismatchedOperatorIds
103+
)).to.be.revertedWithCustomError(clusters, Errors.INCORRECT_VALIDATOR_STATE_WITH_DATA).withArgs(publicKeys[0]);
104+
});
105+
});
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { expect } from "chai";
2+
import type { NetworkConnection } from "hardhat/types/network";
3+
import type { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/types";
4+
import { getTestConnection } from "../../setup/connection.ts";
5+
import { ssvClustersHarnessFixture } from "../../setup/fixtures.ts";
6+
import type { NetworkHelpersType } from "../../common/types.ts";
7+
import { makePublicKey } from "../../common/helpers.ts";
8+
import { DEFAULT_ETH_REGISTER_VALUE, DEFAULT_SHARES, EMPTY_CLUSTER } from "../../common/constants.ts";
9+
import { Events } from "../../common/events.ts";
10+
import { Errors } from "../../common/errors.ts";
11+
12+
const createCluster = () => ({
13+
...EMPTY_CLUSTER,
14+
active: true,
15+
});
16+
17+
describe("SSVClusters function `exitValidator()`", async () => {
18+
let connection: NetworkConnection<"generic">;
19+
let networkHelpers: NetworkHelpersType;
20+
21+
let clusterOwner: HardhatEthersSigner;
22+
23+
before(async function () {
24+
({ connection, networkHelpers } = await getTestConnection());
25+
26+
[clusterOwner] = await connection.ethers.getSigners();
27+
});
28+
29+
const deploySSVClustersAndPrepareOperatorsFixture = async () => {
30+
return ssvClustersHarnessFixture(connection);
31+
};
32+
33+
it("Exits an existing validator and emits the correct event", async function () {
34+
const { clusters, operatorIds } =
35+
await networkHelpers.loadFixture(deploySSVClustersAndPrepareOperatorsFixture);
36+
37+
const publicKey = makePublicKey(1);
38+
39+
await clusters.registerValidator(
40+
publicKey,
41+
operatorIds,
42+
DEFAULT_SHARES,
43+
0,
44+
createCluster(),
45+
{ value: DEFAULT_ETH_REGISTER_VALUE }
46+
);
47+
48+
await expect(clusters.exitValidator(
49+
publicKey,
50+
operatorIds
51+
)).to.emit(clusters, Events.VALIDATOR_EXITED).withArgs(clusterOwner.address, operatorIds, publicKey);
52+
});
53+
54+
it("Is reverted with 'IncorrectValidatorStateWithData' when validator was not registered", async function () {
55+
const { clusters, operatorIds } =
56+
await networkHelpers.loadFixture(deploySSVClustersAndPrepareOperatorsFixture);
57+
58+
const missingPk = makePublicKey(1);
59+
60+
await expect(clusters.exitValidator(
61+
missingPk,
62+
operatorIds
63+
)).to.be.revertedWithCustomError(clusters, Errors.INCORRECT_VALIDATOR_STATE_WITH_DATA).withArgs(missingPk);
64+
});
65+
66+
it("Is reverted with 'IncorrectValidatorStateWithData' when operator ids do not match the validator", async function () {
67+
const { clusters, operatorIds } =
68+
await networkHelpers.loadFixture(deploySSVClustersAndPrepareOperatorsFixture);
69+
70+
const publicKey = makePublicKey(1);
71+
await clusters.registerValidator(
72+
publicKey,
73+
operatorIds,
74+
DEFAULT_SHARES,
75+
0,
76+
createCluster(),
77+
{ value: DEFAULT_ETH_REGISTER_VALUE }
78+
);
79+
80+
const mismatchedOperatorIds = [...operatorIds];
81+
mismatchedOperatorIds[0] = mismatchedOperatorIds[0] + 1n; // alter first id
82+
83+
await expect(clusters.exitValidator(
84+
publicKey,
85+
mismatchedOperatorIds
86+
)).to.be.revertedWithCustomError(clusters, Errors.INCORRECT_VALIDATOR_STATE_WITH_DATA).withArgs(publicKey);
87+
});
88+
});

0 commit comments

Comments
 (0)