Skip to content

Commit

Permalink
test: integrate predeposit guarantee into vault tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DiRaiks committed Mar 2, 2025
1 parent 6f37fc5 commit 65bbd88
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: UNLICENSED
// for testing purposes only

pragma solidity 0.8.25;

import {GIndex} from "contracts/0.8.25/lib/GIndex.sol";
import {PredepositGuarantee} from "contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol";

contract PredepositGuarantee_HarnessForFactory is PredepositGuarantee {
constructor(
GIndex _gIFirstValidator,
GIndex _gIFirstValidatorAfterChange,
uint64 _changeSlot
) PredepositGuarantee(_gIFirstValidator, _gIFirstValidatorAfterChange, _changeSlot) {}
}
6 changes: 5 additions & 1 deletion test/0.8.25/vaults/delegation/delegation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ describe("Delegation.sol", () => {

beacon = await ethers.deployContract("UpgradeableBeacon", [vaultImpl, beaconOwner]);

factory = await ethers.deployContract("VaultFactory", [beacon.getAddress(), delegationImpl.getAddress()]);
factory = await ethers.deployContract("VaultFactory", [
beacon.getAddress(),
delegationImpl.getAddress(),
depositContract.getAddress(),
]);
expect(await beacon.implementation()).to.equal(vaultImpl);
expect(await factory.BEACON()).to.equal(beacon);
expect(await factory.DELEGATION_IMPL()).to.equal(delegationImpl);
Expand Down
6 changes: 5 additions & 1 deletion test/0.8.25/vaults/permissions/permissions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ describe("Permissions", () => {
permissionsImpl = await ethers.deployContract("Permissions__Harness");

// 6. Deploy VaultFactory and use Beacon and Permissions implementations
vaultFactory = await ethers.deployContract("VaultFactory__MockPermissions", [beacon, permissionsImpl]);
vaultFactory = await ethers.deployContract("VaultFactory__MockPermissions", [
beacon,
permissionsImpl,
depositContract,
]);

// 7. Create StakingVault and Permissions proxies using VaultFactory
const vaultCreationTx = await vaultFactory.connect(deployer).createVaultWithPermissions(
Expand Down
19 changes: 10 additions & 9 deletions test/0.8.25/vaults/staking-vault/stakingVault.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe("StakingVault.sol", () => {
let stranger: HardhatEthersSigner;
let elRewardsSender: HardhatEthersSigner;
let vaultHubSigner: HardhatEthersSigner;
let depositor: HardhatEthersSigner;

let stakingVault: StakingVault;
let stakingVaultImplementation: StakingVault;
Expand All @@ -64,9 +65,9 @@ describe("StakingVault.sol", () => {
let originalState: string;

before(async () => {
[vaultOwner, operator, elRewardsSender, stranger] = await ethers.getSigners();
[vaultOwner, operator, elRewardsSender, depositor, stranger] = await ethers.getSigners();
({ stakingVault, vaultHub, stakingVaultImplementation, depositContract } =
await deployStakingVaultBehindBeaconProxy(vaultOwner, operator));
await deployStakingVaultBehindBeaconProxy(vaultOwner, operator, depositor));

// ERC7002 pre-deployed contract mock (0x00000961Ef480Eb55e80D19ad83579A64c007002)
withdrawalRequest = await deployWithdrawalsPreDeployedMock(1n);
Expand Down Expand Up @@ -542,7 +543,7 @@ describe("StakingVault.sol", () => {
});

context("depositToBeaconChain", () => {
it("reverts if called by a non-operator", async () => {
it("reverts if called by a non-depositor", async () => {
await expect(
stakingVault
.connect(stranger)
Expand All @@ -564,7 +565,7 @@ describe("StakingVault.sol", () => {
await stakingVault.connect(vaultHubSigner).lock(ether("1"));
await expect(
stakingVault
.connect(operator)
.connect(depositor)
.depositToBeaconChain([
{ pubkey: "0x", signature: "0x", amount: 0, depositDataRoot: streccak("random-root") },
]),
Expand All @@ -575,7 +576,7 @@ describe("StakingVault.sol", () => {
await stakingVault.connect(vaultOwner).pauseBeaconChainDeposits();
await expect(
stakingVault
.connect(operator)
.connect(depositor)
.depositToBeaconChain([
{ pubkey: "0x", signature: "0x", amount: 0, depositDataRoot: streccak("random-root") },
]),
Expand All @@ -592,10 +593,10 @@ describe("StakingVault.sol", () => {
const depositDataRoot = computeDepositDataRoot(withdrawalCredentials, pubkey, signature, amount);

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

it("makes multiple deposits to the beacon chain and emits the `DepositedToBeaconChain` event", async () => {
Expand All @@ -614,9 +615,9 @@ describe("StakingVault.sol", () => {
return { pubkey, signature, amount, depositDataRoot };
});

await expect(stakingVault.connect(operator).depositToBeaconChain(deposits))
await expect(stakingVault.connect(depositor).depositToBeaconChain(deposits))
.to.emit(stakingVault, "DepositedToBeaconChain")
.withArgs(operator, numberOfKeys, totalAmount);
.withArgs(depositor, numberOfKeys, totalAmount);
});
});

Expand Down
31 changes: 26 additions & 5 deletions test/0.8.25/vaults/vaultFactory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
DepositContract__MockForBeaconChainDepositor,
LidoLocator,
OssifiableProxy,
PredepositGuarantee_HarnessForFactory,
StakingVault,
StakingVault__HarnessForTestUpgrade,
StETH__HarnessForVaultHub,
Expand Down Expand Up @@ -51,6 +52,8 @@ describe("VaultFactory.sol", () => {

let locator: LidoLocator;

let predepositGuarantee: PredepositGuarantee_HarnessForFactory;

let vaultBeaconProxy: BeaconProxy;
let vaultBeaconProxyCode: string;

Expand All @@ -68,16 +71,24 @@ describe("VaultFactory.sol", () => {
weth = await ethers.deployContract("WETH9__MockForVault");
wsteth = await ethers.deployContract("WstETH__HarnessForVault", [steth]);

//predeposit guarantee
predepositGuarantee = await ethers.deployContract("PredepositGuarantee_HarnessForFactory", [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
0,
]);

locator = await deployLidoLocator({
lido: steth,
wstETH: wsteth,
predepositGuarantee: predepositGuarantee,
});

depositContract = await ethers.deployContract("DepositContract__MockForBeaconChainDepositor", deployer);

// Accounting
vaultHubImpl = await ethers.deployContract("VaultHub", [
steth,
locator,
ZeroAddress,
VAULTS_CONNECTED_VAULTS_LIMIT,
VAULTS_RELATIVE_SHARE_LIMIT_BP,
Expand All @@ -99,15 +110,17 @@ describe("VaultFactory.sol", () => {
vaultBeaconProxyCode = await ethers.provider.getCode(await vaultBeaconProxy.getAddress());

delegation = await ethers.deployContract("Delegation", [weth, locator], { from: deployer });
vaultFactory = await ethers.deployContract("VaultFactory", [beacon, delegation], { from: deployer });
vaultFactory = await ethers.deployContract("VaultFactory", [beacon, delegation, predepositGuarantee], {
from: deployer,
});

//add VAULT_MASTER_ROLE role to allow admin to connect the Vaults to the vault Hub
await vaultHub.connect(admin).grantRole(await vaultHub.VAULT_MASTER_ROLE(), admin);
//add VAULT_REGISTRY_ROLE role to allow admin to add factory and vault implementation to the hub
await vaultHub.connect(admin).grantRole(await vaultHub.VAULT_REGISTRY_ROLE(), admin);

//the initialize() function cannot be called on a contract
await expect(implOld.initialize(stranger, operator, depositContract, "0x")).to.revertedWithCustomError(
await expect(implOld.initialize(stranger, operator, vaultOwner1, "0x")).to.revertedWithCustomError(
implOld,
"InvalidInitialization",
);
Expand Down Expand Up @@ -152,17 +165,25 @@ describe("VaultFactory.sol", () => {
});

it("reverts if `_implementation` is zero address", async () => {
await expect(ethers.deployContract("VaultFactory", [ZeroAddress, steth], { from: deployer }))
await expect(ethers.deployContract("VaultFactory", [ZeroAddress, steth, predepositGuarantee], { from: deployer }))
.to.be.revertedWithCustomError(vaultFactory, "ZeroArgument")
.withArgs("_beacon");
});

it("reverts if `_delegation` is zero address", async () => {
await expect(ethers.deployContract("VaultFactory", [beacon, ZeroAddress], { from: deployer }))
await expect(
ethers.deployContract("VaultFactory", [beacon, ZeroAddress, predepositGuarantee], { from: deployer }),
)
.to.be.revertedWithCustomError(vaultFactory, "ZeroArgument")
.withArgs("_delegation");
});

it("reverts if `_predeposit_guarantee` is zero address", async () => {
await expect(ethers.deployContract("VaultFactory", [beacon, steth, ZeroAddress], { from: deployer }))
.to.be.revertedWithCustomError(vaultFactory, "ZeroArgument")
.withArgs("_predeposit_guarantee");
});

it("works and emit `OwnershipTransferred`, `Upgraded` events", async () => {
const tx = beacon.deploymentTransaction();

Expand Down
12 changes: 10 additions & 2 deletions test/0.8.25/vaults/vaultHub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { ethers } from "hardhat";

import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";

import { OssifiableProxy, StETH__Harness, VaultHub } from "typechain-types";
import { LidoLocator, OssifiableProxy, StETH__Harness, VaultHub, WstETH__HarnessForVault } from "typechain-types";

import { ether } from "lib";

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

describe("VaultHub.sol", () => {
Expand All @@ -19,6 +20,8 @@ describe("VaultHub.sol", () => {
let proxy: OssifiableProxy;
let vaultHubImpl: VaultHub;
let steth: StETH__Harness;
let wsteth: WstETH__HarnessForVault;
let locator: LidoLocator;
let vaultHub: VaultHub;

let originalState: string;
Expand All @@ -27,10 +30,15 @@ describe("VaultHub.sol", () => {
[admin, user, holder, stranger] = await ethers.getSigners();

steth = await ethers.deployContract("StETH__Harness", [holder], { value: ether("10.0") });
wsteth = await ethers.deployContract("WstETH__HarnessForVault", [steth]);
locator = await deployLidoLocator({
lido: steth,
wstETH: wsteth,
});

// VaultHub
vaultHubImpl = await ethers.deployContract("VaultHub", [
steth,
locator,
ZeroAddress,
VAULTS_CONNECTED_VAULTS_LIMIT,
VAULTS_RELATIVE_SHARE_LIMIT_BP,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ contract StakingVault__MockForVaultHub {

address public owner;
address public nodeOperator;

address public depositGuardian;
uint256 public $locked;
uint256 public $valuation;
int256 public $inOutDelta;
Expand All @@ -19,9 +19,10 @@ contract StakingVault__MockForVaultHub {
depositContract = _depositContract;
}

function initialize(address _owner, address _nodeOperator, bytes calldata) external {
function initialize(address _owner, address _nodeOperator, address _depositGuardian, bytes calldata) external {
owner = _owner;
nodeOperator = _nodeOperator;
depositGuardian = _depositGuardian;
}

function lock(uint256 amount) external {
Expand Down Expand Up @@ -56,6 +57,10 @@ contract StakingVault__MockForVaultHub {
$locked = _locked;
}

function depositor() external view returns (address) {
return depositGuardian;
}

function triggerValidatorWithdrawal(
bytes calldata _pubkeys,
uint64[] calldata _amounts,
Expand Down
25 changes: 18 additions & 7 deletions test/0.8.25/vaults/vaulthub/vaulthub.forceExit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { ethers } from "hardhat";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";

import {
DepositContract__MockForVaultHub,
LidoLocator,
PredepositGuarantee_HarnessForFactory,
StakingVault__MockForVaultHub,
StETH__HarnessForVaultHub,
VaultFactory__MockForVaultHub,
Expand All @@ -16,6 +17,7 @@ import { impersonate } from "lib";
import { findEvents } from "lib/event";
import { ether } from "lib/units";

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

const SAMPLE_PUBKEY = "0x" + "01".repeat(48);
Expand All @@ -38,7 +40,8 @@ describe("VaultHub.sol:forceExit", () => {
let vaultFactory: VaultFactory__MockForVaultHub;
let vault: StakingVault__MockForVaultHub;
let steth: StETH__HarnessForVaultHub;
let depositContract: DepositContract__MockForVaultHub;
let predepositGuarantee: PredepositGuarantee_HarnessForFactory;
let locator: LidoLocator;

let vaultAddress: string;
let vaultHubAddress: string;
Expand All @@ -51,10 +54,18 @@ describe("VaultHub.sol:forceExit", () => {
[deployer, user, stranger, feeRecipient] = await ethers.getSigners();

steth = await ethers.deployContract("StETH__HarnessForVaultHub", [user], { value: ether("10000.0") });
depositContract = await ethers.deployContract("DepositContract__MockForVaultHub");
predepositGuarantee = await ethers.deployContract("PredepositGuarantee_HarnessForFactory", [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
0,
]);
locator = await deployLidoLocator({
lido: steth,
predepositGuarantee: predepositGuarantee,
});

const vaultHubImpl = await ethers.deployContract("VaultHub__Harness", [
steth,
locator,
VAULTS_CONNECTED_VAULTS_LIMIT,
VAULTS_RELATIVE_SHARE_LIMIT_BP,
]);
Expand All @@ -72,13 +83,13 @@ describe("VaultHub.sol:forceExit", () => {

const stakingVaultImpl = await ethers.deployContract("StakingVault__MockForVaultHub", [
await vaultHub.getAddress(),
await depositContract.getAddress(),
await locator.predepositGuarantee(),
]);

vaultFactory = await ethers.deployContract("VaultFactory__MockForVaultHub", [await stakingVaultImpl.getAddress()]);

const vaultCreationTx = (await vaultFactory
.createVault(user, user, await depositContract.getAddress())
.createVault(user, user, await locator.predepositGuarantee())
.then((tx) => tx.wait())) as ContractTransactionReceipt;

const events = findEvents(vaultCreationTx, "VaultCreated");
Expand Down Expand Up @@ -183,7 +194,7 @@ describe("VaultHub.sol:forceExit", () => {
// https://github.com/lidofinance/core/pull/933#discussion_r1954876831
it("works for a synthetic example", async () => {
const vaultCreationTx = (await vaultFactory
.createVault(user, user, await depositContract.getAddress())
.createVault(user, user, await locator.predepositGuarantee())
.then((tx) => tx.wait())) as ContractTransactionReceipt;

const events = findEvents(vaultCreationTx, "VaultCreated");
Expand Down
Loading

0 comments on commit 65bbd88

Please sign in to comment.