Skip to content

Commit

Permalink
chore: update permissions and dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
tamtamchik committed Feb 4, 2025
1 parent 9b52efa commit f27d244
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 7 deletions.
17 changes: 17 additions & 0 deletions contracts/0.8.25/vaults/Dashboard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,23 @@ contract Dashboard is Permissions {
_requestValidatorExit(_validatorPublicKeys);
}

/**
* @notice Initiates a full validator withdrawal for the given validator public keys.
* @param _validatorPublicKeys The public keys of the validators to initiate withdrawal for.
*/
function initiateFullValidatorWithdrawal(bytes calldata _validatorPublicKeys) external payable {
_initiateFullValidatorWithdrawal(_validatorPublicKeys);
}

/**
* @notice Initiates a partial validator withdrawal for the given validator public keys and amounts.
* @param _validatorPublicKeys The public keys of the validators to initiate withdrawal for.
* @param _amounts The amounts of the validators to initiate withdrawal for.
*/
function initiatePartialValidatorWithdrawal(bytes calldata _validatorPublicKeys, uint64[] calldata _amounts) external payable {
_initiatePartialValidatorWithdrawal(_validatorPublicKeys, _amounts);
}

// ==================== Role Management Functions ====================

/**
Expand Down
8 changes: 4 additions & 4 deletions contracts/0.8.25/vaults/Permissions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ abstract contract Permissions is AccessControlVoteable {
stakingVault().requestValidatorExit(_pubkey);
}

function _initiateFullValidatorsWithdrawal(bytes calldata _pubkeys) internal onlyRole(INITIATE_VALIDATOR_WITHDRAWAL_ROLE) {
stakingVault().initiateFullValidatorWithdrawal(_pubkeys);
function _initiateFullValidatorWithdrawal(bytes calldata _pubkeys) internal onlyRole(INITIATE_VALIDATOR_WITHDRAWAL_ROLE) {
stakingVault().initiateFullValidatorWithdrawal{value: msg.value}(_pubkeys);
}

function _initiatePartialValidatorsWithdrawal(bytes calldata _pubkeys, uint64[] calldata _amounts) internal onlyRole(INITIATE_VALIDATOR_WITHDRAWAL_ROLE) {
stakingVault().initiatePartialValidatorWithdrawal(_pubkeys, _amounts);
function _initiatePartialValidatorWithdrawal(bytes calldata _pubkeys, uint64[] calldata _amounts) internal onlyRole(INITIATE_VALIDATOR_WITHDRAWAL_ROLE) {
stakingVault().initiatePartialValidatorWithdrawal{value: msg.value}(_pubkeys, _amounts);
}

function _voluntaryDisconnect() internal onlyRole(VOLUNTARY_DISCONNECT_ROLE) {
Expand Down
2 changes: 2 additions & 0 deletions contracts/0.8.25/vaults/VaultFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct DelegationConfig {
address depositPauser;
address depositResumer;
address exitRequester;
address withdrawalInitiator;
address disconnecter;
address curator;
address nodeOperatorManager;
Expand Down Expand Up @@ -78,6 +79,7 @@ contract VaultFactory {
delegation.grantRole(delegation.PAUSE_BEACON_CHAIN_DEPOSITS_ROLE(), _delegationConfig.depositPauser);
delegation.grantRole(delegation.RESUME_BEACON_CHAIN_DEPOSITS_ROLE(), _delegationConfig.depositResumer);
delegation.grantRole(delegation.REQUEST_VALIDATOR_EXIT_ROLE(), _delegationConfig.exitRequester);
delegation.grantRole(delegation.INITIATE_VALIDATOR_WITHDRAWAL_ROLE(), _delegationConfig.withdrawalInitiator);
delegation.grantRole(delegation.VOLUNTARY_DISCONNECT_ROLE(), _delegationConfig.disconnecter);
delegation.grantRole(delegation.CURATOR_ROLE(), _delegationConfig.curator);
delegation.grantRole(delegation.NODE_OPERATOR_MANAGER_ROLE(), _delegationConfig.nodeOperatorManager);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ contract VaultFactory__MockForDashboard is UpgradeableBeacon {
dashboard.grantRole(dashboard.PAUSE_BEACON_CHAIN_DEPOSITS_ROLE(), msg.sender);
dashboard.grantRole(dashboard.RESUME_BEACON_CHAIN_DEPOSITS_ROLE(), msg.sender);
dashboard.grantRole(dashboard.REQUEST_VALIDATOR_EXIT_ROLE(), msg.sender);
dashboard.grantRole(dashboard.INITIATE_VALIDATOR_WITHDRAWAL_ROLE(), msg.sender);
dashboard.grantRole(dashboard.VOLUNTARY_DISCONNECT_ROLE(), msg.sender);

dashboard.revokeRole(dashboard.DEFAULT_ADMIN_ROLE(), address(this));
Expand Down
49 changes: 46 additions & 3 deletions test/0.8.25/vaults/dashboard/dashboard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {

import { certainAddress, days, ether, findEvents, signPermit, stethDomain, wstethDomain } from "lib";

import { deployLidoLocator } from "test/deploy";
import { deployLidoLocator, deployWithdrawalsPreDeployedMock } from "test/deploy";
import { Snapshot } from "test/suite";

describe("Dashboard.sol", () => {
Expand Down Expand Up @@ -49,9 +49,13 @@ describe("Dashboard.sol", () => {

const BP_BASE = 10_000n;

const FEE = 10n; // some withdrawal fee for EIP-7002

before(async () => {
[factoryOwner, vaultOwner, nodeOperator, stranger] = await ethers.getSigners();

await deployWithdrawalsPreDeployedMock(FEE);

steth = await ethers.deployContract("StETHPermit__HarnessForDashboard");
await steth.mock__setTotalShares(ether("1000000"));
await steth.mock__setTotalPooledEther(ether("1400000"));
Expand Down Expand Up @@ -138,6 +142,13 @@ describe("Dashboard.sol", () => {
});
});

context("votingCommittee", () => {
it("returns the array of roles", async () => {
const votingCommittee = await dashboard.votingCommittee();
expect(votingCommittee).to.deep.equal([ZeroAddress]);
});
});

context("initialized state", () => {
it("post-initialization state is correct", async () => {
// vault state
Expand Down Expand Up @@ -606,22 +617,54 @@ describe("Dashboard.sol", () => {
});

context("requestValidatorExit", () => {
const validatorPublicKeys = "0x" + randomBytes(48).toString("hex");
it("reverts if called by a non-admin", async () => {
const validatorPublicKeys = "0x" + randomBytes(48).toString("hex");
await expect(dashboard.connect(stranger).requestValidatorExit(validatorPublicKeys)).to.be.revertedWithCustomError(
dashboard,
"AccessControlUnauthorizedAccount",
);
});

it("requests the exit of a validator", async () => {
const validatorPublicKeys = "0x" + randomBytes(48).toString("hex");
await expect(dashboard.requestValidatorExit(validatorPublicKeys))
.to.emit(vault, "ExitRequested")
.withArgs(dashboard, validatorPublicKeys);
});
});

context("initiateFullValidatorWithdrawal", () => {
const validatorPublicKeys = "0x" + randomBytes(48).toString("hex");

it("reverts if called by a non-admin", async () => {
await expect(
dashboard.connect(stranger).initiateFullValidatorWithdrawal(validatorPublicKeys),
).to.be.revertedWithCustomError(dashboard, "AccessControlUnauthorizedAccount");
});

it("initiates a full validator withdrawal", async () => {
await expect(dashboard.initiateFullValidatorWithdrawal(validatorPublicKeys, { value: FEE }))
.to.emit(vault, "FullWithdrawalInitiated")
.withArgs(dashboard, validatorPublicKeys);
});
});

context("initiatePartialValidatorWithdrawal", () => {
const validatorPublicKeys = "0x" + randomBytes(48).toString("hex");
const amounts = [ether("0.1")];

it("reverts if called by a non-admin", async () => {
await expect(
dashboard.connect(stranger).initiatePartialValidatorWithdrawal(validatorPublicKeys, amounts),
).to.be.revertedWithCustomError(dashboard, "AccessControlUnauthorizedAccount");
});

it("initiates a partial validator withdrawal", async () => {
await expect(dashboard.initiatePartialValidatorWithdrawal(validatorPublicKeys, amounts, { value: FEE }))
.to.emit(vault, "PartialWithdrawalInitiated")
.withArgs(dashboard, validatorPublicKeys, amounts);
});
});

context("mintShares", () => {
const amountShares = ether("1");
const amountFunded = ether("2");
Expand Down
1 change: 1 addition & 0 deletions test/0.8.25/vaults/vaultFactory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ describe("VaultFactory.sol", () => {
depositPauser: await vaultOwner1.getAddress(),
depositResumer: await vaultOwner1.getAddress(),
exitRequester: await vaultOwner1.getAddress(),
withdrawalInitiator: await vaultOwner1.getAddress(),
disconnecter: await vaultOwner1.getAddress(),
nodeOperatorManager: await operator.getAddress(),
nodeOperatorFeeClaimer: await operator.getAddress(),
Expand Down

0 comments on commit f27d244

Please sign in to comment.