From eef95235b2981a152b5078e52fb973ab358fa0aa Mon Sep 17 00:00:00 2001 From: Yuri Tkachenko Date: Mon, 10 Feb 2025 12:48:10 +0000 Subject: [PATCH] feat: simplify provisioning --- .github/workflows/analyse.yml | 2 +- lib/protocol/helpers/nor.ts | 10 ++++-- lib/protocol/helpers/sdvt.ts | 9 +++-- lib/protocol/helpers/staking.ts | 36 +++++++++---------- lib/protocol/helpers/withdrawal.ts | 11 ++---- lib/protocol/provision.ts | 3 +- .../protocol-happy-path.integration.ts | 10 +++--- 7 files changed, 38 insertions(+), 43 deletions(-) diff --git a/.github/workflows/analyse.yml b/.github/workflows/analyse.yml index 016a2b748..3a4a625cb 100644 --- a/.github/workflows/analyse.yml +++ b/.github/workflows/analyse.yml @@ -40,7 +40,7 @@ jobs: - name: Run slither run: > - poetry run slither . --no-fail-pedantic --sarif results.sarif + poetry run slither . --no-fail-pedantic --sarif results.sarif - name: Check results.sarif presence id: results diff --git a/lib/protocol/helpers/nor.ts b/lib/protocol/helpers/nor.ts index a6ca84fa2..c5185d82a 100644 --- a/lib/protocol/helpers/nor.ts +++ b/lib/protocol/helpers/nor.ts @@ -5,6 +5,9 @@ import { certainAddress, log, trace } from "lib"; import { ProtocolContext, StakingModuleName } from "../types"; +import { depositAndReportValidators } from "./staking"; + +const NOR_MODULE_ID = 1n; const MIN_OPS_COUNT = 3n; const MIN_OP_KEYS_COUNT = 10n; @@ -16,10 +19,9 @@ export const norEnsureOperators = async ( minOperatorsCount = MIN_OPS_COUNT, minOperatorKeysCount = MIN_OP_KEYS_COUNT, ) => { - const newOperatorsCount = await norEnsureOperatorsHaveMinKeys(ctx, minOperatorsCount, minOperatorKeysCount); - const { nor } = ctx.contracts; + const newOperatorsCount = await norEnsureOperatorsHaveMinKeys(ctx, minOperatorsCount, minOperatorKeysCount); for (let operatorId = 0n; operatorId < minOperatorsCount; operatorId++) { const nodeOperatorBefore = await nor.getNodeOperator(operatorId, false); @@ -40,7 +42,9 @@ export const norEnsureOperators = async ( "Min keys count": minOperatorKeysCount, }); - return newOperatorsCount; + if (newOperatorsCount > 0) { + await depositAndReportValidators(ctx, NOR_MODULE_ID, newOperatorsCount); + } }; /** diff --git a/lib/protocol/helpers/sdvt.ts b/lib/protocol/helpers/sdvt.ts index 593334f4a..cc722e580 100644 --- a/lib/protocol/helpers/sdvt.ts +++ b/lib/protocol/helpers/sdvt.ts @@ -1,13 +1,14 @@ import { expect } from "chai"; import { randomBytes } from "ethers"; -import { impersonate, log, streccak, trace } from "lib"; +import { ether, impersonate, log, streccak, trace } from "lib"; -import { ether } from "../../units"; import { ProtocolContext } from "../types"; import { getOperatorManagerAddress, getOperatorName, getOperatorRewardAddress } from "./nor"; +import { depositAndReportValidators } from "./staking"; +const SDVT_MODULE_ID = 2n; const MIN_OPS_COUNT = 3n; const MIN_OP_KEYS_COUNT = 10n; @@ -40,7 +41,9 @@ export const sdvtEnsureOperators = async ( expect(nodeOperatorAfter.totalVettedValidators).to.equal(nodeOperatorBefore.totalAddedValidators); } - return newOperatorsCount; + if (newOperatorsCount > 0) { + await depositAndReportValidators(ctx, SDVT_MODULE_ID, newOperatorsCount); + } }; /** diff --git a/lib/protocol/helpers/staking.ts b/lib/protocol/helpers/staking.ts index 82a7039e6..39b8b9884 100644 --- a/lib/protocol/helpers/staking.ts +++ b/lib/protocol/helpers/staking.ts @@ -8,11 +8,6 @@ import { ProtocolContext } from "../types"; import { report } from "./accounting"; -const AMOUNT = ether("100"); -const MAX_DEPOSIT = 150n; -const CURATED_MODULE_ID = 1n; -const SIMPLE_DVT_MODULE_ID = 2n; - /** * Unpauses the staking contract. */ @@ -47,36 +42,37 @@ export const ensureStakeLimit = async (ctx: ProtocolContext) => { } }; -export const depositAndReportValidators = async (ctx: ProtocolContext) => { +export const depositAndReportValidators = async (ctx: ProtocolContext, moduleId: bigint, depositsCount: bigint) => { const { lido, depositSecurityModule } = ctx.contracts; - const ethHolder = await impersonate(certainAddress("provision:eht:whale"), ether("100000")); + const ethHolder = await impersonate(certainAddress("provision:eth:whale"), ether("100000")); await lido.connect(ethHolder).submit(ZeroAddress, { value: ether("10000") }); - // Deposit node operators - const dsmSigner = await impersonate(depositSecurityModule.address, AMOUNT); - await lido.connect(dsmSigner).deposit(MAX_DEPOSIT, CURATED_MODULE_ID, ZERO_HASH); - await lido.connect(dsmSigner).deposit(MAX_DEPOSIT, SIMPLE_DVT_MODULE_ID, ZERO_HASH); + // Deposit validators + const dsmSigner = await impersonate(depositSecurityModule.address, ether("100000")); + await lido.connect(dsmSigner).deposit(depositsCount, moduleId, ZERO_HASH); const before = await lido.getBeaconStat(); log.debug("Validators on beacon chain before provisioning", { - depositedValidators: before.depositedValidators, - beaconValidators: before.beaconValidators, - beaconBalance: before.beaconBalance, + "Module ID to deposit": moduleId, + "Deposited": before.depositedValidators, + "Total": before.beaconValidators, + "Balance": before.beaconBalance, }); // Add new validators to beacon chain await report(ctx, { - clDiff: ether("32") * before.depositedValidators, - clAppearedValidators: before.depositedValidators, + clDiff: ether("32") * depositsCount, + clAppearedValidators: depositsCount, }); const after = await lido.getBeaconStat(); - log.debug("Validators on beacon chain after provisioning", { - depositedValidators: after.depositedValidators, - beaconValidators: after.beaconValidators, - beaconBalance: after.beaconBalance, + log.debug("Validators on beacon chain after depositing", { + "Module ID deposited": moduleId, + "Deposited": after.depositedValidators, + "Total": after.beaconValidators, + "Balance": after.beaconBalance, }); }; diff --git a/lib/protocol/helpers/withdrawal.ts b/lib/protocol/helpers/withdrawal.ts index 329ed913d..3066a8a73 100644 --- a/lib/protocol/helpers/withdrawal.ts +++ b/lib/protocol/helpers/withdrawal.ts @@ -1,4 +1,3 @@ -import { expect } from "chai"; import { ZeroAddress } from "ethers"; import { certainAddress, ether, impersonate, log, trace } from "lib"; @@ -33,20 +32,14 @@ export const unpauseWithdrawalQueue = async (ctx: ProtocolContext) => { export const finalizeWithdrawalQueue = async (ctx: ProtocolContext) => { const { lido, withdrawalQueue } = ctx.contracts; - const seed = Math.random() * 1000000; - - const ethHolder = await impersonate(certainAddress(`withdrawalQueue:eth:whale:${seed}`), ether("100000")); - const stEthHolder = await impersonate(certainAddress(`withdrawalQueue:stEth:whale:${seed}`), ether("100000")); + const ethHolder = await impersonate(certainAddress("withdrawalQueue:eth:whale"), ether("100000")); + const stEthHolder = await impersonate(certainAddress("withdrawalQueue:stEth:whale"), ether("100000")); const stEthHolderAmount = ether("10000"); // Here sendTransaction is used to validate native way of submitting ETH for stETH const tx = await stEthHolder.sendTransaction({ to: lido.address, value: stEthHolderAmount }); await trace("stEthHolder.sendTransaction", tx); - const stEthHolderBalance = await lido.balanceOf(stEthHolder.address); - - expect(stEthHolderBalance).to.approximately(stEthHolderAmount, 10n, "stETH balance increased"); - let lastFinalizedRequestId = await withdrawalQueue.getLastFinalizedRequestId(); let lastRequestId = await withdrawalQueue.getLastRequestId(); diff --git a/lib/protocol/provision.ts b/lib/protocol/provision.ts index 76ce732b7..e22e1ca75 100644 --- a/lib/protocol/provision.ts +++ b/lib/protocol/provision.ts @@ -1,7 +1,6 @@ import { log } from "lib"; import { - depositAndReportValidators, ensureHashConsensusInitialEpoch, ensureOracleCommitteeMembers, ensureStakeLimit, @@ -33,7 +32,7 @@ export const provision = async (ctx: ProtocolContext) => { await norEnsureOperators(ctx, 3n, 5n); await sdvtEnsureOperators(ctx, 3n, 5n); - await depositAndReportValidators(ctx); + await finalizeWithdrawalQueue(ctx); await ensureStakeLimit(ctx); diff --git a/test/integration/protocol-happy-path.integration.ts b/test/integration/protocol-happy-path.integration.ts index 590f38527..1a5ec6e30 100644 --- a/test/integration/protocol-happy-path.integration.ts +++ b/test/integration/protocol-happy-path.integration.ts @@ -30,6 +30,7 @@ describe("Protocol Happy Path", () => { let uncountedStETHShares: bigint; let amountWithRewards: bigint; + let depositCount: bigint; before(async () => { ctx = await getProtocolContext(); @@ -220,7 +221,7 @@ describe("Protocol Happy Path", () => { const dsmSigner = await impersonate(depositSecurityModule.address, ether("100")); const stakingModules = await stakingRouter.getStakingModules(); - let depositCount = 0n; + depositCount = 0n; let expectedBufferedEtherAfterDeposit = bufferedEtherBeforeDeposit; for (const module of stakingModules) { const depositTx = await lido.connect(dsmSigner).deposit(MAX_DEPOSIT, module.id, ZERO_HASH); @@ -294,11 +295,10 @@ describe("Protocol Happy Path", () => { const treasuryBalanceBeforeRebase = await lido.sharesOf(treasuryAddress); - // Stranger deposited 100 ETH, enough to deposit 3 validators, need to reflect this in the report - // 0.01 ETH is added to the clDiff to simulate some rewards + // 0.001 – to simulate rewards const reportData: Partial = { - clDiff: ether("96.01"), - clAppearedValidators: 3n, + clDiff: ether("32") * depositCount + ether("0.001"), + clAppearedValidators: depositCount, }; const { reportTx, extraDataTx } = (await report(ctx, reportData)) as {