Skip to content

Commit

Permalink
chore: renaming
Browse files Browse the repository at this point in the history
  • Loading branch information
tamtamchik committed Jan 29, 2025
1 parent a7447df commit 41728a7
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 127 deletions.
6 changes: 3 additions & 3 deletions contracts/0.8.25/vaults/StakingVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pragma solidity 0.8.25;
import {OwnableUpgradeable} from "contracts/openzeppelin/5.2/upgradeable/access/OwnableUpgradeable.sol";

import {VaultHub} from "./VaultHub.sol";
import {VaultValidatorsManager} from "./VaultValidatorsManager.sol";
import {StakingVaultBeaconChainManager} from "./StakingVaultBeaconChainManager.sol";

import {IStakingVault} from "./interfaces/IStakingVault.sol";

Expand Down Expand Up @@ -56,7 +56,7 @@ import {IStakingVault} from "./interfaces/IStakingVault.sol";
* deposit contract.
*
*/
contract StakingVault is IStakingVault, VaultValidatorsManager, OwnableUpgradeable {
contract StakingVault is IStakingVault, StakingVaultBeaconChainManager, OwnableUpgradeable {
/**
* @notice ERC-7201 storage namespace for the vault
* @dev ERC-7201 namespace is used to prevent upgrade collisions
Expand Down Expand Up @@ -110,7 +110,7 @@ contract StakingVault is IStakingVault, VaultValidatorsManager, OwnableUpgradeab
constructor(
address _vaultHub,
address _beaconChainDepositContract
) VaultValidatorsManager(_beaconChainDepositContract) {
) StakingVaultBeaconChainManager(_beaconChainDepositContract) {
if (_vaultHub == address(0)) revert ZeroArgument("_vaultHub");

VAULT_HUB = VaultHub(_vaultHub);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {IDepositContract} from "../interfaces/IDepositContract.sol";
import {IStakingVault} from "./interfaces/IStakingVault.sol";

/// @notice Abstract contract that manages validator deposits and exits for staking vaults
abstract contract VaultValidatorsManager {
abstract contract StakingVaultBeaconChainManager {

/// @notice The Beacon Chain deposit contract used for staking validators
IDepositContract private immutable BEACON_CHAIN_DEPOSIT_CONTRACT;
Expand Down Expand Up @@ -184,18 +184,18 @@ abstract contract VaultValidatorsManager {
* @notice Emitted when a validator exit request is made
* @dev Signals `nodeOperator` to exit the validator
* @param _sender Address that requested the validator exit
* @param _pubkey Public key of the validator requested to exit
* @param _pubkeys Public key of the validator requested to exit
*/
event ValidatorsExitRequested(address indexed _sender, bytes _pubkey);
event ValidatorsExitRequested(address indexed _sender, bytes _pubkeys);

/**
* @notice Emitted when a validator partial exit request is made
* @dev Signals `nodeOperator` to exit the validator
* @param _sender Address that requested the validator partial exit
* @param _pubkey Public key of the validator requested to exit
* @param _pubkeys Public key of the validator requested to exit
* @param _amounts Amounts of ether requested to exit
*/
event ValidatorsPartialExitRequested(address indexed _sender, bytes _pubkey, uint64[] _amounts);
event ValidatorsPartialExitRequested(address indexed _sender, bytes _pubkeys, uint64[] _amounts);

/**
* @notice Emitted when an excess fee is refunded back to the sender
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
VaultHub__MockForStakingVault,
} from "typechain-types";

import { de0x, ether, impersonate } from "lib";
import { computeDepositDataRoot, de0x, ether, impersonate, streccak } from "lib";

import { deployStakingVaultBehindBeaconProxy } from "test/deploy";
import { Snapshot } from "test/suite";
Expand All @@ -21,7 +21,7 @@ const MAX_INT128 = 2n ** 127n - 1n;
const MAX_UINT128 = 2n ** 128n - 1n;

// @TODO: test reentrancy attacks
describe("StakingVault.sol:Accounting", () => {
describe("StakingVault.sol", () => {
let vaultOwner: HardhatEthersSigner;
let operator: HardhatEthersSigner;
let stranger: HardhatEthersSigner;
Expand Down Expand Up @@ -57,13 +57,9 @@ describe("StakingVault.sol:Accounting", () => {
vaultHubSigner = await impersonate(vaultHubAddress, ether("10"));
});

beforeEach(async () => {
originalState = await Snapshot.take();
});
beforeEach(async () => (originalState = await Snapshot.take()));

afterEach(async () => {
await Snapshot.restore(originalState);
});
afterEach(async () => await Snapshot.restore(originalState));

context("constructor", () => {
it("sets the vault hub address in the implementation", async () => {
Expand All @@ -82,7 +78,7 @@ describe("StakingVault.sol:Accounting", () => {

it("reverts on construction if the deposit contract address is zero", async () => {
await expect(ethers.deployContract("StakingVault", [vaultHubAddress, ZeroAddress]))
.to.be.revertedWithCustomError(stakingVaultImplementation, "ZeroArgument")
.to.be.revertedWithCustomError(stakingVaultImplementation, "ZeroBeaconChainDepositContract")
.withArgs("_beaconChainDepositContract");
});

Expand Down Expand Up @@ -118,6 +114,114 @@ describe("StakingVault.sol:Accounting", () => {
});
});

context("pauseBeaconChainDeposits", () => {
it("reverts if called by a non-owner", async () => {
await expect(stakingVault.connect(stranger).pauseBeaconChainDeposits())
.to.be.revertedWithCustomError(stakingVault, "OwnableUnauthorizedAccount")
.withArgs(await stranger.getAddress());
});

it("reverts if the beacon deposits are already paused", async () => {
await stakingVault.connect(vaultOwner).pauseBeaconChainDeposits();

await expect(stakingVault.connect(vaultOwner).pauseBeaconChainDeposits()).to.be.revertedWithCustomError(
stakingVault,
"BeaconChainDepositsResumeExpected",
);
});

it("allows to pause deposits", async () => {
await expect(stakingVault.connect(vaultOwner).pauseBeaconChainDeposits()).to.emit(
stakingVault,
"BeaconChainDepositsPaused",
);
expect(await stakingVault.beaconChainDepositsPaused()).to.be.true;
});
});

context("resumeBeaconChainDeposits", () => {
it("reverts if called by a non-owner", async () => {
await expect(stakingVault.connect(stranger).resumeBeaconChainDeposits())
.to.be.revertedWithCustomError(stakingVault, "OwnableUnauthorizedAccount")
.withArgs(await stranger.getAddress());
});

it("reverts if the beacon deposits are already resumed", async () => {
await expect(stakingVault.connect(vaultOwner).resumeBeaconChainDeposits()).to.be.revertedWithCustomError(
stakingVault,
"BeaconChainDepositsPauseExpected",
);
});

it("allows to resume deposits", async () => {
await stakingVault.connect(vaultOwner).pauseBeaconChainDeposits();

await expect(stakingVault.connect(vaultOwner).resumeBeaconChainDeposits()).to.emit(
stakingVault,
"BeaconChainDepositsResumed",
);
expect(await stakingVault.beaconChainDepositsPaused()).to.be.false;
});
});

context("depositToBeaconChain", () => {
it("reverts if called by a non-operator", async () => {
await expect(
stakingVault
.connect(stranger)
.depositToBeaconChain([
{ pubkey: "0x", signature: "0x", amount: 0, depositDataRoot: streccak("random-root") },
]),
)
.to.be.revertedWithCustomError(stakingVault, "NotAuthorized")
.withArgs("depositToBeaconChain", stranger);
});

it("reverts if the number of deposits is zero", async () => {
await expect(stakingVault.depositToBeaconChain([]))
.to.be.revertedWithCustomError(stakingVault, "ZeroArgument")
.withArgs("_deposits");
});

it("reverts if the vault is not balanced", async () => {
await stakingVault.connect(vaultHubSigner).lock(ether("1"));
await expect(
stakingVault
.connect(operator)
.depositToBeaconChain([
{ pubkey: "0x", signature: "0x", amount: 0, depositDataRoot: streccak("random-root") },
]),
).to.be.revertedWithCustomError(stakingVault, "Unbalanced");
});

it("reverts if the deposits are paused", async () => {
await stakingVault.connect(vaultOwner).pauseBeaconChainDeposits();
await expect(
stakingVault
.connect(operator)
.depositToBeaconChain([
{ pubkey: "0x", signature: "0x", amount: 0, depositDataRoot: streccak("random-root") },
]),
).to.be.revertedWithCustomError(stakingVault, "BeaconChainDepositsArePaused");
});

it("makes deposits to the beacon chain and emits the DepositedToBeaconChain event", async () => {
await stakingVault.fund({ value: ether("32") });

const pubkey = "0x" + "ab".repeat(48);
const signature = "0x" + "ef".repeat(96);
const amount = ether("32");
const withdrawalCredentials = await stakingVault.withdrawalCredentials();
const depositDataRoot = computeDepositDataRoot(withdrawalCredentials, pubkey, signature, amount);

await expect(
stakingVault.connect(operator).depositToBeaconChain([{ pubkey, signature, amount, depositDataRoot }]),
)
.to.emit(stakingVault, "DepositedToBeaconChain")
.withArgs(operator, 1, amount);
});
});

context("unlocked", () => {
it("returns the correct unlocked balance", async () => {
expect(await stakingVault.unlocked()).to.equal(0n);
Expand Down
Loading

0 comments on commit 41728a7

Please sign in to comment.