Skip to content

Commit

Permalink
feat: untangle Sanity Checker and Locator deployment
Browse files Browse the repository at this point in the history
don't read addresses from locator in Sanity Checker ctor
  • Loading branch information
arwer13 committed Mar 7, 2025
1 parent cac27de commit 42c64b6
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 72 deletions.
11 changes: 7 additions & 4 deletions contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,23 @@ contract OracleReportSanityChecker is AccessControlEnumerable {
ISecondOpinionOracle public secondOpinionOracle;

/// @param _lidoLocator address of the LidoLocator instance
/// @param _accountingOracle address of the AccountingOracle instance
/// @param _accounting address of the Accounting instance
/// @param _admin address to grant DEFAULT_ADMIN_ROLE of the AccessControl contract
/// @param _limitsList initial values to be set for the limits list
constructor(
address _lidoLocator,
address _accountingOracle,
address _accounting,
address _admin,
LimitsList memory _limitsList
) {
if (_admin == address(0)) revert AdminCannotBeZero();
LIDO_LOCATOR = ILidoLocator(_lidoLocator);

address accountingOracle = LIDO_LOCATOR.accountingOracle();
GENESIS_TIME = IBaseOracle(accountingOracle).GENESIS_TIME();
SECONDS_PER_SLOT = IBaseOracle(accountingOracle).SECONDS_PER_SLOT();
ACCOUNTING_ADDRESS = LIDO_LOCATOR.accounting();
GENESIS_TIME = IBaseOracle(_accountingOracle).GENESIS_TIME();
SECONDS_PER_SLOT = IBaseOracle(_accountingOracle).SECONDS_PER_SLOT();
ACCOUNTING_ADDRESS = _accounting;

_updateLimits(_limitsList);

Expand Down
1 change: 0 additions & 1 deletion scripts/scratch/steps.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"scratch/steps/0070-deploy-dao",
"scratch/steps/0080-issue-tokens",
"scratch/steps/0090-deploy-non-aragon-contracts",
"scratch/steps/0095-deploy-negative-rebase-sanity-checker",
"scratch/steps/0100-gate-seal",
"scratch/steps/0110-finalize-dao",
"scratch/steps/0120-initialize-non-aragon-contracts",
Expand Down
33 changes: 31 additions & 2 deletions scripts/scratch/steps/0090-deploy-non-aragon-contracts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ZeroAddress } from "ethers";
import { ethers } from "hardhat";

import { certainAddress } from "lib";
import { getContractPath } from "lib/contract";
import {
deployBehindOssifiableProxy,
Expand Down Expand Up @@ -31,6 +30,8 @@ export async function main() {
const withdrawalQueueERC721Params = state[Sk.withdrawalQueueERC721].deployParameters;
const minFirstAllocationStrategyAddress = state[Sk.minFirstAllocationStrategy].address;

const sanityCheckerParams = state["oracleReportSanityChecker"].deployParameters;

const proxyContractsOwner = deployer;
const admin = deployer;

Expand Down Expand Up @@ -200,14 +201,42 @@ export async function main() {
burnerParams.totalNonCoverSharesBurnt,
]);

// Deploy OracleReportSanityChecker
const oracleReportSanityCheckerArgs = [
locator.address,
accountingOracle.address,
accounting.address,
admin,
[
sanityCheckerParams.exitedValidatorsPerDayLimit,
sanityCheckerParams.appearedValidatorsPerDayLimit,
sanityCheckerParams.annualBalanceIncreaseBPLimit,
sanityCheckerParams.maxValidatorExitRequestsPerReport,
sanityCheckerParams.maxItemsPerExtraDataTransaction,
sanityCheckerParams.maxNodeOperatorsPerExtraDataItem,
sanityCheckerParams.requestTimestampMargin,
sanityCheckerParams.maxPositiveTokenRebase,
sanityCheckerParams.initialSlashingAmountPWei,
sanityCheckerParams.inactivityPenaltiesAmountPWei,
sanityCheckerParams.clBalanceOraclesErrorUpperBPLimit,
],
];

const oracleReportSanityChecker = await deployWithoutProxy(
Sk.oracleReportSanityChecker,
"OracleReportSanityChecker",
deployer,
oracleReportSanityCheckerArgs,
);

// Update LidoLocator with valid implementation
const locatorConfig: string[] = [
accountingOracle.address,
depositSecurityModuleAddress,
elRewardsVault.address,
legacyOracleAddress,
lidoAddress,
certainAddress("dummy-locator:oracleReportSanityChecker"), // requires LidoLocator in the constructor, so deployed after it
oracleReportSanityChecker.address,
ZeroAddress,
burner.address,
stakingRouter.address,
Expand Down

This file was deleted.

7 changes: 6 additions & 1 deletion test/0.8.25/vaults/vaultFactory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ describe("VaultFactory.sol", () => {
depositContract = await ethers.deployContract("DepositContract__MockForBeaconChainDepositor", deployer);

// Accounting
vaultHubImpl = await ethers.deployContract("VaultHub", [steth, ZeroAddress, VAULTS_CONNECTED_VAULTS_LIMIT, VAULTS_RELATIVE_SHARE_LIMIT_BP]);
vaultHubImpl = await ethers.deployContract("VaultHub", [
steth,
ZeroAddress,
VAULTS_CONNECTED_VAULTS_LIMIT,
VAULTS_RELATIVE_SHARE_LIMIT_BP,
]);
proxy = await ethers.deployContract("OssifiableProxy", [vaultHubImpl, admin, new Uint8Array()], admin);
vaultHub = await ethers.getContractAt("VaultHub", proxy, deployer);
await vaultHub.initialize(admin);
Expand Down
7 changes: 6 additions & 1 deletion test/0.8.25/vaults/vaulthub/vaulthub.pausable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ describe("VaultHub.sol:pausableUntil", () => {

steth = await ethers.deployContract("StETH__HarnessForVaultHub", [user], { value: ether("1.0") });

const vaultHubImpl = await ethers.deployContract("VaultHub", [steth, ZeroAddress, VAULTS_CONNECTED_VAULTS_LIMIT, VAULTS_RELATIVE_SHARE_LIMIT_BP]);
const vaultHubImpl = await ethers.deployContract("VaultHub", [
steth,
ZeroAddress,
VAULTS_CONNECTED_VAULTS_LIMIT,
VAULTS_RELATIVE_SHARE_LIMIT_BP,
]);
const proxy = await ethers.deployContract("OssifiableProxy", [vaultHubImpl, deployer, new Uint8Array()]);

vaultHubAdmin = await ethers.getContractAt("VaultHub", proxy);
Expand Down
4 changes: 3 additions & 1 deletion test/0.8.9/contracts/OracleReportSanityCheckerWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ contract OracleReportSanityCheckerWrapper is OracleReportSanityChecker {

constructor(
address _lidoLocator,
address _accountingOracle,
address _accounting,
address _admin,
LimitsList memory _limitsList
) OracleReportSanityChecker(_lidoLocator, _admin, _limitsList) {}
) OracleReportSanityChecker(_lidoLocator, _accountingOracle, _accounting, _admin, _limitsList) {}

function addReportData(uint256 _timestamp, uint256 _exitedValidatorsCount, uint256 _negativeCLRebase) public {
_addReportData(_timestamp, _exitedValidatorsCount, _negativeCLRebase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";

import {
Accounting__MockForSanityChecker,
AccountingOracle__MockForSanityChecker,
LidoLocator__MockForSanityChecker,
OracleReportSanityChecker,
Expand All @@ -22,6 +23,7 @@ describe("OracleReportSanityChecker.sol:negative-rebase", () => {
let locator: LidoLocator__MockForSanityChecker;
let checker: OracleReportSanityChecker;
let accountingOracle: AccountingOracle__MockForSanityChecker;
let accounting: Accounting__MockForSanityChecker;
let stakingRouter: StakingRouter__MockForSanityChecker;
let deployer: HardhatEthersSigner;
let accountingSigner: HardhatEthersSigner;
Expand Down Expand Up @@ -60,7 +62,7 @@ describe("OracleReportSanityChecker.sol:negative-rebase", () => {
const sanityCheckerAddress = deployer.address;

const burner = await ethers.deployContract("Burner__MockForSanityChecker", []);
const accounting = await ethers.deployContract("Accounting__MockForSanityChecker", []);
accounting = await ethers.deployContract("Accounting__MockForSanityChecker", []);

accountingOracle = await ethers.deployContract("AccountingOracle__MockForSanityChecker", [
deployer.address,
Expand Down Expand Up @@ -92,10 +94,14 @@ describe("OracleReportSanityChecker.sol:negative-rebase", () => {
]);

const locatorAddress = await locator.getAddress();
const accountingOracleAddress = await accountingOracle.getAddress();
const accountingAddress = await accounting.getAddress();

checker = await ethers
.getContractFactory("OracleReportSanityChecker")
.then((f) => f.deploy(locatorAddress, deployer.address, defaultLimitsList));
.then((f) =>
f.deploy(locatorAddress, accountingOracleAddress, accountingAddress, deployer.address, defaultLimitsList),
);

accountingSigner = await impersonate(await accounting.getAddress(), ether("1"));
});
Expand Down Expand Up @@ -178,6 +184,8 @@ describe("OracleReportSanityChecker.sol:negative-rebase", () => {
async function newChecker() {
return await ethers.deployContract("OracleReportSanityCheckerWrapper", [
await locator.getAddress(),
await accountingOracle.getAddress(),
await accounting.getAddress(),
deployer.address,
Object.values(defaultLimitsList),
]);
Expand Down Expand Up @@ -255,7 +263,7 @@ describe("OracleReportSanityChecker.sol:negative-rebase", () => {
.withArgs(20n * ether("1"), 10n * ether("1") + 10n * ether("0.101"));
});

it("works as accamulation for IncorrectCLBalanceDecrease", async () => {
it("works as accumulation for IncorrectCLBalanceDecrease", async () => {
const genesisTime = await accountingOracle.GENESIS_TIME();
const timestamp = await getCurrentBlockTimestamp();
const refSlot = (timestamp - genesisTime) / 12n;
Expand Down Expand Up @@ -411,7 +419,7 @@ describe("OracleReportSanityChecker.sol:negative-rebase", () => {

const secondOpinionOracle = await deploySecondOpinionOracle();

// Second opinion balance is almost equal general Oracle's (<0.74%) and withdrawal vauls is the same - should pass
// Second opinion balance is almost equal general Oracle's (<0.74%) and withdrawal value is the same - should pass
await secondOpinionOracle.addReport(refSlot, {
success: true,
clBalanceGwei: parseUnits("300", "gwei"),
Expand Down
23 changes: 18 additions & 5 deletions test/deploy/accountingOracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,22 @@ export async function deployAccountingOracleSetup(
initialEpoch,
});

const accountingOracleAddress = await oracle.getAddress();
const accountingAddress = await accounting.getAddress();

await updateLidoLocatorImplementation(locatorAddr, {
stakingRouter: await stakingRouter.getAddress(),
withdrawalQueue: await withdrawalQueue.getAddress(),
accountingOracle: await oracle.getAddress(),
accounting: await accounting.getAddress(),
accountingOracle: accountingOracleAddress,
accounting: accountingAddress,
});

const oracleReportSanityChecker = await deployOracleReportSanityCheckerForAccounting(locatorAddr, admin);
const oracleReportSanityChecker = await deployOracleReportSanityCheckerForAccounting(
locatorAddr,
accountingOracleAddress,
accountingAddress,
admin,
);

await updateLidoLocatorImplementation(locatorAddr, {
oracleReportSanityChecker: await oracleReportSanityChecker.getAddress(),
Expand Down Expand Up @@ -153,11 +161,16 @@ export async function initAccountingOracle({
return initTx;
}

async function deployOracleReportSanityCheckerForAccounting(lidoLocator: string, admin: string) {
async function deployOracleReportSanityCheckerForAccounting(
lidoLocator: string,
accountingOracle: string,
accounting: string,
admin: string,
) {
const exitedValidatorsPerDayLimit = 55;
const appearedValidatorsPerDayLimit = 100;
return await ethers.getContractFactory("OracleReportSanityChecker").then((f) =>
f.deploy(lidoLocator, admin, {
f.deploy(lidoLocator, accountingOracle, accounting, admin, {
exitedValidatorsPerDayLimit,
appearedValidatorsPerDayLimit,
annualBalanceIncreaseBPLimit: 0n,
Expand Down
21 changes: 17 additions & 4 deletions test/deploy/validatorExitBusOracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ async function deployMockAccountingOracle(secondsPerSlot = SECONDS_PER_SLOT, gen
return { ao, lido };
}

async function deployOracleReportSanityCheckerForExitBus(lidoLocator: string, admin: string) {
async function deployOracleReportSanityCheckerForExitBus(
lidoLocator: string,
accountingOracle: string,
accounting: string,
admin: string,
) {
return await ethers.getContractFactory("OracleReportSanityChecker").then((f) =>
f.deploy(lidoLocator, admin, {
f.deploy(lidoLocator, accountingOracle, accounting, admin, {
exitedValidatorsPerDayLimit: 0n,
appearedValidatorsPerDayLimit: 0n,
annualBalanceIncreaseBPLimit: 0n,
Expand Down Expand Up @@ -69,12 +74,20 @@ export async function deployVEBO(

const { ao, lido } = await deployMockAccountingOracle(secondsPerSlot, genesisTime);

const accountingOracleAddress = await ao.getAddress();
const accountingAddress = await locator.accounting();

await updateLidoLocatorImplementation(locatorAddr, {
lido: await lido.getAddress(),
accountingOracle: await ao.getAddress(),
accountingOracle: accountingOracleAddress,
});

const oracleReportSanityChecker = await deployOracleReportSanityCheckerForExitBus(locatorAddr, admin);
const oracleReportSanityChecker = await deployOracleReportSanityCheckerForExitBus(
locatorAddr,
accountingOracleAddress,
accountingAddress,
admin,
);

await updateLidoLocatorImplementation(locatorAddr, {
validatorsExitBusOracle: await oracle.getAddress(),
Expand Down

0 comments on commit 42c64b6

Please sign in to comment.