diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 850fcd9a6..8bc15cbdb 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -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); diff --git a/scripts/scratch/steps.json b/scripts/scratch/steps.json index 973446a1f..131a00a04 100644 --- a/scripts/scratch/steps.json +++ b/scripts/scratch/steps.json @@ -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", diff --git a/scripts/scratch/steps/0090-deploy-non-aragon-contracts.ts b/scripts/scratch/steps/0090-deploy-non-aragon-contracts.ts index dde72ba34..57985aac4 100644 --- a/scripts/scratch/steps/0090-deploy-non-aragon-contracts.ts +++ b/scripts/scratch/steps/0090-deploy-non-aragon-contracts.ts @@ -1,7 +1,6 @@ import { ZeroAddress } from "ethers"; import { ethers } from "hardhat"; -import { certainAddress } from "lib"; import { getContractPath } from "lib/contract"; import { deployBehindOssifiableProxy, @@ -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; @@ -200,6 +201,34 @@ 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, @@ -207,7 +236,7 @@ export async function main() { elRewardsVault.address, legacyOracleAddress, lidoAddress, - certainAddress("dummy-locator:oracleReportSanityChecker"), // requires LidoLocator in the constructor, so deployed after it + oracleReportSanityChecker.address, ZeroAddress, burner.address, stakingRouter.address, diff --git a/scripts/scratch/steps/0095-deploy-negative-rebase-sanity-checker.ts b/scripts/scratch/steps/0095-deploy-negative-rebase-sanity-checker.ts deleted file mode 100644 index c34562fa8..000000000 --- a/scripts/scratch/steps/0095-deploy-negative-rebase-sanity-checker.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ethers } from "hardhat"; - -import { deployLidoLocatorImplementation, deployWithoutProxy } from "lib/deploy"; -import { readNetworkState, Sk } from "lib/state-file"; - -export async function main() { - const deployer = (await ethers.provider.getSigner()).address; - const state = readNetworkState({ deployer }); - - // Extract necessary addresses and parameters from the state - const locatorAddress = state[Sk.lidoLocator].proxy.address; - - const proxyContractsOwner = deployer; - const admin = deployer; - - const sanityChecks = state["oracleReportSanityChecker"].deployParameters; - - // Deploy OracleReportSanityChecker - const oracleReportSanityCheckerArgs = [ - locatorAddress, - admin, - [ - sanityChecks.exitedValidatorsPerDayLimit, - sanityChecks.appearedValidatorsPerDayLimit, - sanityChecks.annualBalanceIncreaseBPLimit, - sanityChecks.maxValidatorExitRequestsPerReport, - sanityChecks.maxItemsPerExtraDataTransaction, - sanityChecks.maxNodeOperatorsPerExtraDataItem, - sanityChecks.requestTimestampMargin, - sanityChecks.maxPositiveTokenRebase, - sanityChecks.initialSlashingAmountPWei, - sanityChecks.inactivityPenaltiesAmountPWei, - sanityChecks.clBalanceOraclesErrorUpperBPLimit, - ], - ]; - - const oracleReportSanityChecker = await deployWithoutProxy( - Sk.oracleReportSanityChecker, - "OracleReportSanityChecker", - deployer, - oracleReportSanityCheckerArgs, - ); - - await deployLidoLocatorImplementation( - locatorAddress, - { oracleReportSanityChecker: oracleReportSanityChecker.address }, - proxyContractsOwner, - ); -} diff --git a/test/0.8.25/vaults/vaultFactory.test.ts b/test/0.8.25/vaults/vaultFactory.test.ts index 1d7ca6b40..77657d947 100644 --- a/test/0.8.25/vaults/vaultFactory.test.ts +++ b/test/0.8.25/vaults/vaultFactory.test.ts @@ -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); diff --git a/test/0.8.25/vaults/vaulthub/vaulthub.pausable.test.ts b/test/0.8.25/vaults/vaulthub/vaulthub.pausable.test.ts index ee870e0f5..12954f62b 100644 --- a/test/0.8.25/vaults/vaulthub/vaulthub.pausable.test.ts +++ b/test/0.8.25/vaults/vaulthub/vaulthub.pausable.test.ts @@ -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); diff --git a/test/0.8.9/contracts/OracleReportSanityCheckerWrapper.sol b/test/0.8.9/contracts/OracleReportSanityCheckerWrapper.sol index 250aad6b4..f23a2333b 100644 --- a/test/0.8.9/contracts/OracleReportSanityCheckerWrapper.sol +++ b/test/0.8.9/contracts/OracleReportSanityCheckerWrapper.sol @@ -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); diff --git a/test/0.8.9/sanityChecker/oracleReportSanityChecker.negative-rebase.test.ts b/test/0.8.9/sanityChecker/oracleReportSanityChecker.negative-rebase.test.ts index 340180a2b..2c648d215 100644 --- a/test/0.8.9/sanityChecker/oracleReportSanityChecker.negative-rebase.test.ts +++ b/test/0.8.9/sanityChecker/oracleReportSanityChecker.negative-rebase.test.ts @@ -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, @@ -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; @@ -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, @@ -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")); }); @@ -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), ]); @@ -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; @@ -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"), diff --git a/test/deploy/accountingOracle.ts b/test/deploy/accountingOracle.ts index 090b3d447..0347e6db6 100644 --- a/test/deploy/accountingOracle.ts +++ b/test/deploy/accountingOracle.ts @@ -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(), @@ -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, diff --git a/test/deploy/validatorExitBusOracle.ts b/test/deploy/validatorExitBusOracle.ts index 9ca2c44de..6434f17b1 100644 --- a/test/deploy/validatorExitBusOracle.ts +++ b/test/deploy/validatorExitBusOracle.ts @@ -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, @@ -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(),