From 5a4d5c2243e3229d0b9a8465b27f546d0944a491 Mon Sep 17 00:00:00 2001 From: Andrei Date: Fri, 10 Feb 2023 14:29:34 +0700 Subject: [PATCH 01/82] test: base oracle: add deploy test, mock base oracle, mock hash consensus --- .../oracle/BaseOracleTimeTravellable.sol | 69 ++++++++++++ .../oracle/MockConsensusContract.sol | 80 +++++++++++++ test/0.8.9/oracle/base-oracle-deploy.test.js | 106 ++++++++++++++++++ .../hash-consensus-access-control.test.js | 2 +- 4 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol create mode 100644 contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol create mode 100644 test/0.8.9/oracle/base-oracle-deploy.test.js diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol new file mode 100644 index 000000000..1cfa15130 --- /dev/null +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.9; + +import { UnstructuredStorage } from "../../lib/UnstructuredStorage.sol"; +import { BaseOracle } from "../../oracle/BaseOracle.sol"; + + +struct ConsensusReport { + bytes32 hash; + uint64 refSlot; + uint64 processingDeadlineTime; +} + + +contract BaseOracleTimeTravellable is BaseOracle { + using UnstructuredStorage for bytes32; + uint256 internal _time = 2513040315; + + struct HandleConsensusReportLastCall { + ConsensusReport report; + uint256 prevSubmittedRefSlot; + uint256 prevProcessingRefSlot; + uint256 callCount; + } + HandleConsensusReportLastCall internal _handleConsensusReportLastCall; + + constructor( + uint256 secondsPerSlot, + uint256 genesisTime + ) BaseOracle( + secondsPerSlot, + genesisTime + ) { + CONTRACT_VERSION_POSITION.setStorageUint256(0); + require(genesisTime <= _time, "GENESIS_TIME_CANNOT_BE_MORE_THAN_MOCK_TIME"); + } + + function initialize( + address consensusContract, + uint256 consensusVersion, + uint256 lastProcessingRefSlot + ) external { + _initialize(consensusContract, consensusVersion, lastProcessingRefSlot); + } + + function _getTime() internal override view returns (uint256) { + return _time; + } + + function getTime() external view returns (uint256) { + return _time; + } + + function setTime(uint256 newTime) external { + _time = newTime; + } + + function advanceTimeBy(uint256 timeAdvance) external { + _time += timeAdvance; + } + + function _handleConsensusReport(ConsensusReport memory report, uint256 prevSubmittedRefSlot, uint256 prevProcessingRefSlot) internal override virtual { + _handleConsensusReportLastCall.report = report; + _handleConsensusReportLastCall.prevSubmittedRefSlot = prevSubmittedRefSlot; + _handleConsensusReportLastCall.prevProcessingRefSlot = prevProcessingRefSlot; + ++_handleConsensusReportLastCall.callCount; + } +} diff --git a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol new file mode 100644 index 000000000..2ffaca2fc --- /dev/null +++ b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.9; + +import { SafeCast } from "@openzeppelin/contracts-v4.4/utils/math/SafeCast.sol"; + +import { IConsensusContract } from "../../oracle/BaseOracle.sol"; + +contract MockConsensusContract is IConsensusContract { + using SafeCast for uint256; + + uint64 internal immutable SLOTS_PER_EPOCH; + uint64 internal immutable SECONDS_PER_SLOT; + uint64 internal immutable GENESIS_TIME; + + mapping(address => uint256) internal _memberIndices1b; + + struct ConsensusFrame { + uint256 index; + uint256 refSlot; + uint256 reportProcessingDeadlineSlot; + } + struct FrameConfig { + uint64 initialEpoch; + uint64 epochsPerFrame; + uint64 fastLaneLengthSlots; + } + FrameConfig internal _frameConfig; + ConsensusFrame internal _consensusFrame; + + constructor( + uint256 slotsPerEpoch, + uint256 secondsPerSlot, + uint256 genesisTime, + uint256 epochsPerFrame, + uint256 initialEpoch, + uint256 fastLaneLengthSlots + ) { + SLOTS_PER_EPOCH = slotsPerEpoch.toUint64(); + SECONDS_PER_SLOT = secondsPerSlot.toUint64(); + GENESIS_TIME = genesisTime.toUint64(); + + _setFrameConfig(initialEpoch, epochsPerFrame, fastLaneLengthSlots); + } + + function getIsMember(address addr) external view returns (bool) { + return _memberIndices1b[addr] != 0; + } + + function getCurrentFrame() external view returns ( + uint256 refSlot, + uint256 reportProcessingDeadlineSlot + ) { + return (_consensusFrame.refSlot, _consensusFrame.reportProcessingDeadlineSlot); + } + + function getChainConfig() external view returns ( + uint256 slotsPerEpoch, + uint256 secondsPerSlot, + uint256 genesisTime + ) { + return (SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME); + } + + function getFrameConfig() external view returns (uint256 initialEpoch, uint256 epochsPerFrame) { + return (_frameConfig.initialEpoch, _frameConfig.epochsPerFrame); + } + + function _setFrameConfig( + uint256 initialEpoch, + uint256 epochsPerFrame, + uint256 fastLaneLengthSlots + ) internal { + _frameConfig = FrameConfig( + initialEpoch.toUint64(), + epochsPerFrame.toUint64(), + fastLaneLengthSlots.toUint64() + ); + } +} diff --git a/test/0.8.9/oracle/base-oracle-deploy.test.js b/test/0.8.9/oracle/base-oracle-deploy.test.js new file mode 100644 index 000000000..a061abed6 --- /dev/null +++ b/test/0.8.9/oracle/base-oracle-deploy.test.js @@ -0,0 +1,106 @@ +const { assert } = require('chai') +const { bn } = require('@aragon/contract-helpers-test') + +const BaseOracle = artifacts.require('BaseOracleTimeTravellable') +const MockConsensusContract = artifacts.require('MockConsensusContract') + +const SLOTS_PER_EPOCH = 32 +const SECONDS_PER_SLOT = 12 +const GENESIS_TIME = 100 +const EPOCHS_PER_FRAME = 225 // one day +const INITIAL_EPOCH = 1 +const INITIAL_FAST_LANE_LENGHT_SLOTS = 0 + +const SECONDS_PER_EPOCH = SLOTS_PER_EPOCH * SECONDS_PER_SLOT +const SECONDS_PER_FRAME = SECONDS_PER_EPOCH * EPOCHS_PER_FRAME +const SLOTS_PER_FRAME = EPOCHS_PER_FRAME * SLOTS_PER_EPOCH + +const computeSlotAt = (time) => Math.floor((time - GENESIS_TIME) / SECONDS_PER_SLOT) +const computeEpochAt = (time) => Math.floor(computeSlotAt(time) / SLOTS_PER_EPOCH) +const computeEpochFirstSlot = (epoch) => epoch * SLOTS_PER_EPOCH +const computeEpochFirstSlotAt = (time) => computeEpochFirstSlot(computeEpochAt(time)) +const computeTimestampAtEpoch = (epoch) => GENESIS_TIME + epoch * SECONDS_PER_EPOCH +const computeTimestampAtSlot = (slot) => GENESIS_TIME + slot * SECONDS_PER_SLOT + +const ZERO_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000' + +const HASH_1 = '0x1111111111111111111111111111111111111111111111111111111111111111' +const HASH_2 = '0x2222222222222222222222222222222222222222222222222222222222222222' +const HASH_3 = '0x3333333333333333333333333333333333333333333333333333333333333333' +const HASH_4 = '0x4444444444444444444444444444444444444444444444444444444444444444' +const HASH_5 = '0x5555555555555555555555555555555555555555555555555555555555555555' + +const UNREACHABLE_QUORUM = bn('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') + +const CONSENSUS_VERSION = 1 + +async function deployBaseOracle( + admin, + { + secondsPerSlot = SECONDS_PER_SLOT, + genesisTime = GENESIS_TIME, + slotsPerEpoch = SLOTS_PER_EPOCH, + consensusContract = null, + epochsPerFrame = EPOCHS_PER_FRAME, + fastLaneLengthSlots = INITIAL_FAST_LANE_LENGHT_SLOTS, + initialEpoch = INITIAL_EPOCH + } = {} +) { + if (!consensusContract) { + consensusContract = await MockConsensusContract.new( + slotsPerEpoch, + secondsPerSlot, + genesisTime, + epochsPerFrame, + fastLaneLengthSlots, + initialEpoch, + { from: admin } + ) + } + + const oracle = await BaseOracle.new(secondsPerSlot, genesisTime, { from: admin }) + + await oracle.initialize(consensusContract.address, CONSENSUS_VERSION, 0) + + return { oracle } +} + +module.exports = { + INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_EPOCH, + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + SECONDS_PER_EPOCH, + SECONDS_PER_FRAME, + SLOTS_PER_FRAME, + computeSlotAt, + computeEpochAt, + computeEpochFirstSlot, + computeEpochFirstSlotAt, + computeTimestampAtSlot, + computeTimestampAtEpoch, + ZERO_HASH, + HASH_1, + HASH_2, + HASH_3, + HASH_4, + HASH_5, + CONSENSUS_VERSION, + UNREACHABLE_QUORUM, + deployBaseOracle +} + +contract('BaseOracle', ([admin, member1]) => { + context('Deployment and initial configuration', () => { + let oracle + + it('deploying base oracle', async () => { + const deployed = await deployBaseOracle(admin) + oracle = deployed.oracle + }) + + // TODO: add more base tests + }) +}) diff --git a/test/0.8.9/oracle/hash-consensus-access-control.test.js b/test/0.8.9/oracle/hash-consensus-access-control.test.js index 1f831602d..1990b9a83 100644 --- a/test/0.8.9/oracle/hash-consensus-access-control.test.js +++ b/test/0.8.9/oracle/hash-consensus-access-control.test.js @@ -3,7 +3,7 @@ const { assert } = require('../../helpers/assert') const { deployHashConsensus, EPOCHS_PER_FRAME } = require('./hash-consensus-deploy.test') -contract('HashConsensus', ([admin, account1, account2, member1, member2, stranger]) => { +contract('HashConsensus', ([admin, account1, account2, member1, member2]) => { let consensus = null let reportProcessor = null const manageMembersAndQuorumRoleKeccak156 = web3.utils.keccak256('MANAGE_MEMBERS_AND_QUORUM_ROLE') From b4617e8c0f637b88bb9d0efc894a403f5d3c49fb Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 10 Feb 2023 20:03:10 +0700 Subject: [PATCH 02/82] feat: added baseOracle submitReport tests and updated helpers&mocks --- .../oracle/BaseOracleTimeTravellable.sol | 10 ++ .../oracle/MockConsensusContract.sol | 31 ++++- test/0.8.9/oracle/base-oracle-deploy.test.js | 8 +- .../oracle/base-oracle-submit-report.test.js | 111 ++++++++++++++++++ 4 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 test/0.8.9/oracle/base-oracle-submit-report.test.js diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index 1cfa15130..3599fd7c5 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -66,4 +66,14 @@ contract BaseOracleTimeTravellable is BaseOracle { _handleConsensusReportLastCall.prevProcessingRefSlot = prevProcessingRefSlot; ++_handleConsensusReportLastCall.callCount; } + + function getConsensusReportLastCall() view external returns (HandleConsensusReportLastCall memory) { + return _handleConsensusReportLastCall; + } + + function startProcessing() external { + _startProcessing(); + } + + } diff --git a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol index 2ffaca2fc..6ef7c2844 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.9; import { SafeCast } from "@openzeppelin/contracts-v4.4/utils/math/SafeCast.sol"; import { IConsensusContract } from "../../oracle/BaseOracle.sol"; +import {IReportAsyncProcessor} from '../../oracle/HashConsensus.sol'; contract MockConsensusContract is IConsensusContract { using SafeCast for uint256; @@ -13,6 +14,8 @@ contract MockConsensusContract is IConsensusContract { uint64 internal immutable SECONDS_PER_SLOT; uint64 internal immutable GENESIS_TIME; + address internal _reportProcessor; + mapping(address => uint256) internal _memberIndices1b; struct ConsensusFrame { @@ -34,15 +37,20 @@ contract MockConsensusContract is IConsensusContract { uint256 genesisTime, uint256 epochsPerFrame, uint256 initialEpoch, - uint256 fastLaneLengthSlots + uint256 fastLaneLengthSlots, + address mockMember ) { SLOTS_PER_EPOCH = slotsPerEpoch.toUint64(); SECONDS_PER_SLOT = secondsPerSlot.toUint64(); GENESIS_TIME = genesisTime.toUint64(); _setFrameConfig(initialEpoch, epochsPerFrame, fastLaneLengthSlots); + _memberIndices1b[mockMember] = 1; + } + + function getIsMember(address addr) external view returns (bool) { return _memberIndices1b[addr] != 0; } @@ -77,4 +85,25 @@ contract MockConsensusContract is IConsensusContract { fastLaneLengthSlots.toUint64() ); } + + // + // IReportAsyncProcessor relevant mocks&handels + // + + function setAsyncProcessor(address reportProcessor) external { + _reportProcessor = reportProcessor; + } + + function submitReportAsConsensus(bytes32 reportHash, uint256 refSlot, uint256 deadline) external { + IReportAsyncProcessor(_reportProcessor).submitConsensusReport( + reportHash, + refSlot, + deadline + ); + } + + + + + } diff --git a/test/0.8.9/oracle/base-oracle-deploy.test.js b/test/0.8.9/oracle/base-oracle-deploy.test.js index a061abed6..32367a78c 100644 --- a/test/0.8.9/oracle/base-oracle-deploy.test.js +++ b/test/0.8.9/oracle/base-oracle-deploy.test.js @@ -43,7 +43,8 @@ async function deployBaseOracle( consensusContract = null, epochsPerFrame = EPOCHS_PER_FRAME, fastLaneLengthSlots = INITIAL_FAST_LANE_LENGHT_SLOTS, - initialEpoch = INITIAL_EPOCH + initialEpoch = INITIAL_EPOCH, + mockMember = admin } = {} ) { if (!consensusContract) { @@ -54,6 +55,7 @@ async function deployBaseOracle( epochsPerFrame, fastLaneLengthSlots, initialEpoch, + mockMember, { from: admin } ) } @@ -62,7 +64,9 @@ async function deployBaseOracle( await oracle.initialize(consensusContract.address, CONSENSUS_VERSION, 0) - return { oracle } + await consensusContract.setAsyncProcessor(oracle.address) + + return { oracle, consensusContract } } module.exports = { diff --git a/test/0.8.9/oracle/base-oracle-submit-report.test.js b/test/0.8.9/oracle/base-oracle-submit-report.test.js new file mode 100644 index 000000000..e9875a88d --- /dev/null +++ b/test/0.8.9/oracle/base-oracle-submit-report.test.js @@ -0,0 +1,111 @@ +const { assert } = require('chai') +const { assertEvent, assertAmountOfEvents, assertBn } = require('@aragon/contract-helpers-test/src/asserts') +const { assertRevert } = require('../../helpers/assertThrow') + +const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') + +const { + INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_EPOCH, + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + SECONDS_PER_EPOCH, + SECONDS_PER_FRAME, + SLOTS_PER_FRAME, + computeSlotAt, + computeEpochAt, + computeEpochFirstSlot, + computeEpochFirstSlotAt, + computeTimestampAtSlot, + computeTimestampAtEpoch, + ZERO_HASH, + HASH_1, + HASH_2, + HASH_3, + HASH_4, + HASH_5, + CONSENSUS_VERSION, + UNREACHABLE_QUORUM, + deployBaseOracle +} = require('./base-oracle-deploy.test') + +contract('BaseOracle', ([admin]) => { + let consensus + let baseOracle + let initialRefSlot + + const deployContract = async () => { + const deployed = await deployBaseOracle(admin, { initialEpoch: 1 }) + consensus = deployed.consensusContract + baseOracle = deployed.oracle + initialRefSlot = +(await baseOracle.getTime()) + } + + describe('submitConsensusReport is called and changes the contract state', () => { + context('submitConsensusReport passes pre-conditions', () => { + before(deployContract) + + it('only setConsensus contract can call submitConsensusReport', async () => { + assertRevert( + baseOracle.submitConsensusReport(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), + 'OnlyConsensusContractCanSubmitReport()' + ) + }) + + it('initial report is submitted and virtual handle is called', async () => { + const tx = await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) + assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 1) + assertEvent(tx, 'ReportSubmitted', { + decodeForAbi: baseOracleAbi, + expectedArgs: { + refSlot: initialRefSlot, + hash: HASH_1, + processingDeadlineTime: initialRefSlot + SLOTS_PER_FRAME + } + }) + }) + + it('older report cannot be submitted', async () => { + assertRevert( + baseOracle.submitConsensusReport(HASH_1, initialRefSlot - 1, initialRefSlot + SLOTS_PER_FRAME), + 'RefSlotCannotDecrease(29,31)' + ) + }) + + it('oracle starts processing last report', async () => { + await baseOracle.startProcessing() + }) + + it('consensus cannot resubmit already processing report', async () => { + assertRevert( + baseOracle.submitConsensusReport(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), + 'RefSlotMustBeGreaterThanProcessingOne(31,31)' + ) + }) + + it('warning event is emitted when newer report is submitted and prev has not started processing yet', async () => { + const tx1 = await consensus.submitReportAsConsensus( + HASH_1, + initialRefSlot + 10, + initialRefSlot + SLOTS_PER_FRAME + ) + assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 2) + assertEvent(tx1, 'ReportSubmitted', { decodeForAbi: baseOracleAbi }) + + const tx2 = await consensus.submitReportAsConsensus( + HASH_1, + initialRefSlot + 20, + initialRefSlot + SLOTS_PER_FRAME + ) + assertEvent(tx2, 'WarnProcessingMissed', { + decodeForAbi: baseOracleAbi, + expectedArgs: { refSlot: initialRefSlot + 10 } + }) + assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 3) + assertEvent(tx2, 'ReportSubmitted', { decodeForAbi: baseOracleAbi }) + }) + }) + }) +}) From cae279f9b9463b99dabcd834c00e9d9a1df46f14 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sat, 11 Feb 2023 18:06:27 +0700 Subject: [PATCH 03/82] feat: submitReport => getConsensusReport tests, helpers linting --- .../oracle/BaseOracleTimeTravellable.sol | 2 +- .../oracle/MockConsensusContract.sol | 2 +- .../oracle/base-oracle-submit-report.test.js | 69 ++++++++++++++++++- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index 3599fd7c5..932f8a3fa 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -67,7 +67,7 @@ contract BaseOracleTimeTravellable is BaseOracle { ++_handleConsensusReportLastCall.callCount; } - function getConsensusReportLastCall() view external returns (HandleConsensusReportLastCall memory) { + function getConsensusReportLastCall() external view returns (HandleConsensusReportLastCall memory) { return _handleConsensusReportLastCall; } diff --git a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol index 6ef7c2844..f638e4e98 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.9; import { SafeCast } from "@openzeppelin/contracts-v4.4/utils/math/SafeCast.sol"; import { IConsensusContract } from "../../oracle/BaseOracle.sol"; -import {IReportAsyncProcessor} from '../../oracle/HashConsensus.sol'; +import {IReportAsyncProcessor} from "../../oracle/HashConsensus.sol"; contract MockConsensusContract is IConsensusContract { using SafeCast for uint256; diff --git a/test/0.8.9/oracle/base-oracle-submit-report.test.js b/test/0.8.9/oracle/base-oracle-submit-report.test.js index e9875a88d..f12c57c44 100644 --- a/test/0.8.9/oracle/base-oracle-submit-report.test.js +++ b/test/0.8.9/oracle/base-oracle-submit-report.test.js @@ -1,5 +1,6 @@ const { assert } = require('chai') const { assertEvent, assertAmountOfEvents, assertBn } = require('@aragon/contract-helpers-test/src/asserts') +const { bn } = require('@aragon/contract-helpers-test') const { assertRevert } = require('../../helpers/assertThrow') const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') @@ -54,9 +55,9 @@ contract('BaseOracle', ([admin]) => { ) }) - it('initial report is submitted and virtual handle is called', async () => { + it('initial report is submitted and _handleConsensusReport is called', async () => { + assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 0) const tx = await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) - assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 1) assertEvent(tx, 'ReportSubmitted', { decodeForAbi: baseOracleAbi, expectedArgs: { @@ -65,6 +66,11 @@ contract('BaseOracle', ([admin]) => { processingDeadlineTime: initialRefSlot + SLOTS_PER_FRAME } }) + const { report, callCount } = await baseOracle.getConsensusReportLastCall() + assert.equal(+callCount, 1) + assert.equal(report.hash, HASH_1) + assert.equal(+report.refSlot, initialRefSlot) + assert.equal(+report.processingDeadlineTime, initialRefSlot + SLOTS_PER_FRAME) }) it('older report cannot be submitted', async () => { @@ -107,5 +113,64 @@ contract('BaseOracle', ([admin]) => { assertEvent(tx2, 'ReportSubmitted', { decodeForAbi: baseOracleAbi }) }) }) + + context('submitConsensusReport updates getConsensusReport', () => { + before(deployContract) + + it('getConsensusReport at deploy returns empty state', async () => { + const report = await baseOracle.getConsensusReport() + assert.equal(report.hash, ZERO_HASH) + assertBn(report.refSlot, bn(0)) + assertBn(report.processingDeadlineTime, bn(0)) + assert(!report.processingStarted) + }) + + it('initial report is submitted', async () => { + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) + const report = await baseOracle.getConsensusReport() + assert.equal(report.hash, HASH_1) + assertBn(report.refSlot, bn(initialRefSlot)) + assertBn(report.processingDeadlineTime, bn(initialRefSlot + SLOTS_PER_FRAME)) + assert(!report.processingStarted) + }) + + it('next report is submitted, initial report is missed, warning event fired', async () => { + const nextRefSlot = initialRefSlot + 1 + const tx = await consensus.submitReportAsConsensus(HASH_2, nextRefSlot, nextRefSlot + SLOTS_PER_FRAME) + assertEvent(tx, 'WarnProcessingMissed', { + decodeForAbi: baseOracleAbi, + expectedArgs: { refSlot: initialRefSlot } + }) + const report = await baseOracle.getConsensusReport() + assert.equal(report.hash, HASH_2) + assertBn(report.refSlot, bn(nextRefSlot)) + assertBn(report.processingDeadlineTime, bn(nextRefSlot + SLOTS_PER_FRAME)) + assert(!report.processingStarted) + }) + + it('next report is re-agreed, no missed warning', async () => { + const nextRefSlot = initialRefSlot + 1 + const tx = await consensus.submitReportAsConsensus(HASH_3, nextRefSlot, nextRefSlot + SLOTS_PER_FRAME + 10) + assertAmountOfEvents(tx, 'WarnProcessingMissed', { + decodeForAbi: baseOracleAbi, + expectedAmount: 0 + }) + const report = await baseOracle.getConsensusReport() + assert.equal(report.hash, HASH_3) + assertBn(report.refSlot, bn(nextRefSlot)) + assertBn(report.processingDeadlineTime, bn(nextRefSlot + SLOTS_PER_FRAME + 10)) + assert(!report.processingStarted) + }) + + it('report processing started for last report', async () => { + const nextRefSlot = initialRefSlot + 1 + await baseOracle.startProcessing() + const report = await baseOracle.getConsensusReport() + assert.equal(report.hash, HASH_3) + assertBn(report.refSlot, bn(nextRefSlot)) + assertBn(report.processingDeadlineTime, bn(nextRefSlot + SLOTS_PER_FRAME + 10)) + assert(report.processingStarted) + }) + }) }) }) From 2bece6157d14db34d5df6453804436d17510b282 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sat, 11 Feb 2023 18:11:50 +0700 Subject: [PATCH 04/82] fix: handle report resubmit case --- contracts/0.8.9/oracle/BaseOracle.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/0.8.9/oracle/BaseOracle.sol b/contracts/0.8.9/oracle/BaseOracle.sol index 0aadda2fc..d91ffeed5 100644 --- a/contracts/0.8.9/oracle/BaseOracle.sol +++ b/contracts/0.8.9/oracle/BaseOracle.sol @@ -173,7 +173,7 @@ abstract contract BaseOracle is IReportAsyncProcessor, AccessControlEnumerable, revert RefSlotMustBeGreaterThanProcessingOne(refSlot, prevProcessingRefSlot); } - if (prevProcessingRefSlot != prevSubmittedRefSlot) { + if (refSlot != prevSubmittedRefSlot && prevProcessingRefSlot != prevSubmittedRefSlot) { emit WarnProcessingMissed(prevSubmittedRefSlot); } From f84bab4820242158aa0e4c97a44fe01e17a5d756 Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Sat, 11 Feb 2023 14:12:08 +0300 Subject: [PATCH 05/82] test fixes --- contracts/0.4.24/test_helpers/LidoMock.sol | 37 -- .../OracleReportSanityCheckerMocks.sol | 2 +- test/0.4.24/lido-handle-oracle-report.test.js | 392 ++++++++++++++++++ .../node-operators-registry-penalty.test.js | 20 +- 4 files changed, 398 insertions(+), 53 deletions(-) create mode 100644 test/0.4.24/lido-handle-oracle-report.test.js diff --git a/contracts/0.4.24/test_helpers/LidoMock.sol b/contracts/0.4.24/test_helpers/LidoMock.sol index f75454bf2..e42aba490 100644 --- a/contracts/0.4.24/test_helpers/LidoMock.sol +++ b/contracts/0.4.24/test_helpers/LidoMock.sol @@ -71,41 +71,4 @@ contract LidoMock is Lido { function burnShares(address _account, uint256 _amount) external { _burnShares(_account, _amount); } - - function handleOracleReportDirect( - // Oracle timings - uint256 _reportTimestamp, - uint256 _timeElapsed, - // CL values - uint256 _clValidators, - uint256 _clBalance, - // EL values - uint256 _withdrawalVaultBalance, - uint256 _elRewardsVaultBalance, - // Decision about withdrawals processing - uint256 _lastFinalizableRequestId, - uint256 _simulatedShareRate - ) external returns ( - uint256 totalPooledEther, - uint256 totalShares, - uint256 withdrawals, - uint256 elRewards - ) { - - OracleReportContracts memory protocolContracts = _loadOracleReportContracts(); - - return _handleOracleReport( - OracleReportedData( - _reportTimestamp, - _timeElapsed, - _clValidators, - _clBalance, - _withdrawalVaultBalance, - _elRewardsVaultBalance, - _lastFinalizableRequestId, - _simulatedShareRate - ), - protocolContracts - ); - } } diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index f7579aa55..d21e33012 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -103,4 +103,4 @@ contract OracleReportSanityCheckerStub { elRewards = _elRewardsVaultBalance; sharesToBurnLimit = _etherToLockForWithdrawals; } -} \ No newline at end of file +} diff --git a/test/0.4.24/lido-handle-oracle-report.test.js b/test/0.4.24/lido-handle-oracle-report.test.js new file mode 100644 index 000000000..3e3fbdb4b --- /dev/null +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -0,0 +1,392 @@ +const hre = require('hardhat') +const { assert } = require('../helpers/assert') +const { ETH, toBN, genKeys } = require('../helpers/utils') +const { deployProtocol } = require('../helpers/protocol') +const { EvmSnapshot } = require('../helpers/blockchain') +const { ZERO_ADDRESS } = require('../helpers/constants') +const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') + +const ONE_YEAR = 3600 * 24 * 365 + +contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, depositor, operator]) => { + let deployed, snapshot, lido, treasury, voting + let curatedModule, oracleReportSanityChecker + let strangerBalanceBefore, + anotherStrangerBalanceBefore, + totalPooledEtherBefore, + curatedModuleBalanceBefore, + treasuryBalanceBefore + + before('deploy base app', async () => { + deployed = await deployProtocol({ + stakingModulesFactory: async (protocol) => { + curatedModule = await setupNodeOperatorsRegistry(protocol) + return [ + { + module: curatedModule, + name: 'Curated', + targetShares: 10000, + moduleFee: 500, + treasuryFee: 500 + } + ] + }, + depositSecurityModuleFactory: async (protocol) => { + return { address: depositor } + } + }) + + await curatedModule.addNodeOperator('1', operator, { from: deployed.voting.address }) + const keysAmount = 50 + const keys1 = genKeys(keysAmount) + await curatedModule.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: deployed.voting.address }) + await curatedModule.setNodeOperatorStakingLimit(0, keysAmount, { from: deployed.voting.address }) + + lido = deployed.pool + treasury = deployed.treasury.address + voting = deployed.voting.address + oracleReportSanityChecker = deployed.oracleReportSanityChecker + + await lido.submit(ZERO_ADDRESS, { from: stranger, value: ETH(30) }) + await lido.submit(ZERO_ADDRESS, { from: anotherStranger, value: ETH(70) }) + + await checkStat({ depositedValidators: 0, beaconValidators: 0, beaconBalance: 0 }) + + + snapshot = new EvmSnapshot(hre.ethers.provider) + await snapshot.make() + }) + + beforeEach(async () => { + await updateBalancesBefore() + }) + + afterEach(async () => { + await snapshot.rollback() + }) + + const checkStat = async ({ depositedValidators, beaconValidators, beaconBalance }) => { + const stat = await lido.getBeaconStat() + assert.equals(stat.depositedValidators, depositedValidators, 'depositedValidators check') + assert.equals(stat.beaconValidators, beaconValidators, 'beaconValidators check') + assert.equals(stat.beaconBalance, beaconBalance, 'beaconBalance check') + } + + const updateBalancesBefore = async () => { + totalPooledEtherBefore = await lido.getTotalPooledEther() + strangerBalanceBefore = await lido.balanceOf(stranger) + anotherStrangerBalanceBefore = await lido.balanceOf(anotherStranger) + treasuryBalanceBefore = await lido.balanceOf(treasury) + curatedModuleBalanceBefore = await lido.balanceOf(curatedModule.address) + } + + const checkBalanceDeltas = async ({ + totalPooledEtherDiff, + treasuryBalanceDiff, + strangerBalanceDiff, + anotherStrangerBalanceDiff, + curatedModuleBalanceDiff + }) => { + assert.equals( + await lido.getTotalPooledEther(), + toBN(totalPooledEtherBefore).add(toBN(totalPooledEtherDiff)), + 'totalPooledEther check' + ) + assert.equalsDelta( + await lido.balanceOf(treasury), + toBN(treasuryBalanceBefore).add(toBN(treasuryBalanceDiff)), + 1, + 'treasury balance check' + ) + assert.equalsDelta( + await lido.balanceOf(curatedModule.address), + toBN(curatedModuleBalanceBefore).add(toBN(curatedModuleBalanceDiff)), + 1, + 'curated module balance check' + ) + assert.equalsDelta( + await lido.balanceOf(stranger), + toBN(strangerBalanceBefore).add(toBN(strangerBalanceDiff)), + 1, + 'stranger balance check' + ) + assert.equalsDelta( + await lido.balanceOf(anotherStranger), + toBN(anotherStrangerBalanceBefore).add(toBN(anotherStrangerBalanceDiff)), + 1, + 'another stranger balance check' + ) + } + + it('handleOracleReport access control', async () => { + await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'APP_AUTH_FAILED') + }) + + it('handleOracleReport reverts whe protocol stopped', async () => { + await lido.stop({ from: deployed.voting.address }) + await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'CONTRACT_IS_STOPPED') + }) + + it('zero report should do nothing', async () => { + await lido.handleOracleReportDirect(0, 0, 0, 0, 0, 0, 0, 0) + await checkStat({ depositedValidators: 0, beaconValidators: 0, beaconBalance: 0 }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + }) + + describe('clBalance', () => { + beforeEach(async () => { + await await lido.deposit(3, 1, '0x', { from: depositor }) + await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + }) + + it('first report after deposit without rewards', async () => { + await lido.handleOracleReportDirect(0, 0, 1, ETH(32), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 1, beaconBalance: ETH(32) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + }) + + it('first report after deposit with rewards', async () => { + // elapsed time set to 1000000 because of annualBalanceIncrease limited by 10000 + await lido.handleOracleReportDirect(0, 1000000, 1, ETH(33), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 1, beaconBalance: ETH(33) }) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: ETH(0.05), + strangerBalanceDiff: ETH(0.3 * 0.9), + anotherStrangerBalanceDiff: ETH(0.7 * 0.9), + curatedModuleBalanceDiff: ETH(0.05) + }) + }) + }) + + describe('sanity checks', async () => { + beforeEach(async () => { + await await lido.deposit(3, 1, '0x', { from: depositor }) + }) + + it('reverts on reported more than deposited', async () => { + await assert.reverts(lido.handleOracleReportDirect(0, 0, 4, 0, 0, 0, 0, 0), 'REPORTED_MORE_DEPOSITED') + }) + + it('reverts on reported less than reported previously', async () => { + await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await assert.reverts(lido.handleOracleReportDirect(0, 0, 2, 0, 0, 0, 0, 0), 'REPORTED_LESS_VALIDATORS') + }) + + it('withdrawal vault balance check', async () => { + await assert.reverts(lido.handleOracleReportDirect(0, 0, 0, 0, 1, 0, 0, 0), 'IncorrectWithdrawalsVaultBalance(0)') + }) + + it('withdrawal vault balance check', async () => { + await assert.reverts(lido.handleOracleReportDirect(0, 0, 0, 0, 1, 0, 0, 0), 'IncorrectWithdrawalsVaultBalance(0)') + }) + + it('does not revert on new total balance stay the same', async () => { + await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + }) + + it('does not revert on new total balance decrease under the limit', async () => { + // set oneOffCLBalanceDecreaseBPLimit = 1% + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsByEpochLimit: 255, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000 + }, + { from: voting } + ) + + await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + await lido.handleOracleReportDirect(0, 0, 3, ETH(95.04), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.04) }) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(-0.96), + treasuryBalanceDiff: ETH(0), + strangerBalanceDiff: ETH(-30 * 0.0096), + anotherStrangerBalanceDiff: toBN(ETH(0.0096)).mul(toBN(-70)).toString(), + curatedModuleBalanceDiff: ETH(0) + }) + }) + + it('reverts on new total balance decrease over the limit', async () => { + // set oneOffCLBalanceDecreaseBPLimit = 1% + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsByEpochLimit: 255, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000 + }, + { from: voting } + ) + + await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + await assert.reverts( + lido.handleOracleReportDirect(0, 0, 3, ETH(95.03), 0, 0, 0, 0), + 'IncorrectCLBalanceDecrease(101)' + ) + }) + + it('does not revert on new total balance increase under the limit', async () => { + // set annualBalanceIncreaseBPLimit = 1% + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsByEpochLimit: 255, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 100, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000 + }, + { from: voting } + ) + + await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.96) }) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(0.96), + treasuryBalanceDiff: ETH(0.96 * 0.05), + strangerBalanceDiff: ETH(30 * 0.0096 * 0.9), + anotherStrangerBalanceDiff: ETH(70 * 0.0096 * 0.9), + curatedModuleBalanceDiff: ETH(0.96 * 0.05) + }) + }) + + it('reverts on new total balance increase over the limit', async () => { + // set annualBalanceIncreaseBPLimit = 1% + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsByEpochLimit: 255, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 100, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000 + }, + { from: voting } + ) + + await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + await assert.reverts( + lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0), + 'IncorrectCLBalanceIncrease(101)' + ) + }) + + it('check finalization share rate', async () => { + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsByEpochLimit: 255, + oneOffCLBalanceDecreaseBPLimit: 10000, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 100, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000 + }, + { from: voting } + ) + await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, ETH(1)) + assert.equals(await lido.getPooledEthByShares(ETH(1)), ETH(1.009)) + await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, ETH(1)) + }) + + it('check finalization share rate', async () => { + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsByEpochLimit: 255, + oneOffCLBalanceDecreaseBPLimit: 10000, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 100, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000 + }, + { from: voting } + ) + await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(95), 0, 0, 0, ETH(1)) + }) + }) +}) diff --git a/test/0.4.24/node-operators-registry-penalty.test.js b/test/0.4.24/node-operators-registry-penalty.test.js index 8bde1f2c1..33c31d5ae 100644 --- a/test/0.4.24/node-operators-registry-penalty.test.js +++ b/test/0.4.24/node-operators-registry-penalty.test.js @@ -1,7 +1,7 @@ const hre = require('hardhat') const { assert } = require('../helpers/assert') const { assertRevert } = require('../helpers/assertThrow') -const { toBN, padRight, shares } = require('../helpers/utils') +const { toBN, padRight, printEvents } = require('../helpers/utils') const { BN } = require('bn.js') const { AragonDAO } = require('./helpers/dao') const { EvmSnapshot } = require('../helpers/blockchain') @@ -173,8 +173,6 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) - // calls distributeRewards() inside await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) @@ -187,8 +185,6 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) - // calls distributeRewards() inside receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) @@ -203,8 +199,6 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, totalRewardShares) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) - //before // operatorId | Total | Deposited | Exited | Active (deposited-exited) // 0 3 3 0 3 @@ -244,8 +238,6 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, totalRewardShares) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) - //before // operatorId | Total | Deposited | Exited | Active (deposited-exited) // 0 3 3 0 3 @@ -284,8 +276,6 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) - //update [operator, exited, stuck] await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 1, 1 , { from: voting }) await app.unsafeUpdateValidatorsKeysCount(secondNodeOperator, 1, 0 , { from: voting }) @@ -305,7 +295,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) + //update [operator, exited, stuck] await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 1, 1, { from: voting }) @@ -326,7 +316,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) + //update [operator, exited, stuck] await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 2, 2 , { from: voting }) @@ -349,7 +339,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - await app.testing_addNodeOperator('no', no1, 10, 10, 10, 0) + assert.isFalse(await app.testing_isNodeOperatorPenalized(firstNodeOperator)) @@ -386,7 +376,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - await app.testing_addNodeOperator('no', no1, 55, 30, 15, 2) + // await app.testing_addNodeOperator('no', no1, 55, 30, 15, 2) // sum of (vetted[i] - exited[i]) await app.increaseTargetValidatorsCount(28) From 40f56b830557748ab51aa4a62aeffa0ed539a408 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 15:07:03 +0300 Subject: [PATCH 06/82] chore: inconsistent comment --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 5da5fd417..33dc2f387 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -894,6 +894,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// 3. a node operator's vetted keys count is changed. /// 4. a node operator was activated/deactivated. Activation or deactivation of node operator /// might lead to usage of unvalidated keys in the assignNextSigningKeys method. + /// 5. a node operator's deposit data is used for the deposit function getKeysOpIndex() external view returns (uint256) { return KEYS_OP_INDEX_POSITION.getStorageUint256(); } From efb01d4702b109f1c8a5479822f4961c88c269c6 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 15:21:25 +0300 Subject: [PATCH 07/82] chore: fix unsafely method comments --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 11 ++++++----- contracts/0.8.9/interfaces/IStakingModule.sol | 7 ++++--- lib/abi/NodeOperatorsRegistry.json | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 33dc2f387..d36df6dc2 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -423,20 +423,21 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { _distributeRewards(); } - /// @notice Unsafely updates the number of the validators in the EXITED state for node operator with given id + /// @notice Unsafely updates the number of validators in the EXITED/STUCK states for node operator with given id + /// 'unsafely' means that this method can both increase and decrease exited and stuck counters /// @param _nodeOperatorId Id of the node operator - /// @param _exitedValidatorsCount New number of EXITED validators of the node operator - /// @return Total number of exited validators across all node operators. + /// @param _exitedValidatorsCount New number of EXITED validators for the node operator + /// @param _stuckValidatorsCount New number of STUCK validator for the node operator function unsafeUpdateValidatorsCount( uint256 _nodeOperatorId, uint256 _exitedValidatorsCount, - uint256 _stuckValidatorsKeysCount + uint256 _stuckValidatorsCount ) external { _onlyExistedNodeOperator(_nodeOperatorId); _auth(STAKING_ROUTER_ROLE); _updateExitedValidatorsCount(_nodeOperatorId, uint64(_exitedValidatorsCount), true); - _updateStuckValidatorsCount(_nodeOperatorId, uint64(_stuckValidatorsKeysCount)); + _updateStuckValidatorsCount(_nodeOperatorId, uint64(_stuckValidatorsCount)); } function _updateExitedValidatorsCount(uint256 _nodeOperatorId, uint64 _exitedValidatorsKeysCount, bool _allowDecrease) diff --git a/contracts/0.8.9/interfaces/IStakingModule.sol b/contracts/0.8.9/interfaces/IStakingModule.sol index 16e5bd43a..38a39d1c7 100644 --- a/contracts/0.8.9/interfaces/IStakingModule.sol +++ b/contracts/0.8.9/interfaces/IStakingModule.sol @@ -84,10 +84,11 @@ interface IStakingModule { /// @param _refundedValidatorsCount New number of refunded validators of the node operator function updateRefundedValidatorsCount(uint256 _nodeOperatorId, uint256 _refundedValidatorsCount) external; - /// @notice Unsafely updates the validators count stats for node operator with given id + /// @notice Unsafely updates the number of validators in the EXITED/STUCK states for node operator with given id + /// 'unsafely' means that this method can both increase and decrease exited and stuck counters /// @param _nodeOperatorId Id of the node operator - /// @param _exitedValidatorsCount New number of EXITED validators of the node operator - /// @param _stuckValidatorsCount New number of stuck validators of the node operator + /// @param _exitedValidatorsCount New number of EXITED validators for the node operator + /// @param _stuckValidatorsCount New number of STUCK validator for the node operator function unsafeUpdateValidatorsCount( uint256 _nodeOperatorId, uint256 _exitedValidatorsCount, diff --git a/lib/abi/NodeOperatorsRegistry.json b/lib/abi/NodeOperatorsRegistry.json index 090b6601f..c49590657 100644 --- a/lib/abi/NodeOperatorsRegistry.json +++ b/lib/abi/NodeOperatorsRegistry.json @@ -1 +1 @@ -[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getType","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getNodeOperatorIds","outputs":[{"name":"nodeOperatorIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getSigningKeys","outputs":[{"name":"pubkeys","type":"bytes"},{"name":"signatures","type":"bytes"},{"name":"used","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorIsActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_name","type":"string"}],"name":"setNodeOperatorName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_totalRewardShares","type":"uint256"}],"name":"getRewardsDistribution","outputs":[{"name":"recipients","type":"address[]"},{"name":"shares","type":"uint256[]"},{"name":"penalized","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_indexFrom","type":"uint256"},{"name":"_indexTo","type":"uint256"}],"name":"invalidateReadyToDepositKeysRange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint64"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_delay","type":"uint256"}],"name":"setStuckPenaltyDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStuckPenaltyDelay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"deactivateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_ROUTER_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onAllValidatorCountersUpdated","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getActiveNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_rewardAddress","type":"address"}],"name":"addNodeOperator","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getUnusedSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_NODE_OPERATOR_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onWithdrawalCredentialsChanged","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"activateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_rewardAddress","type":"address"}],"name":"setNodeOperatorRewardAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fullInfo","type":"bool"}],"name":"getNodeOperator","outputs":[{"name":"active","type":"bool"},{"name":"name","type":"string"},{"name":"rewardAddress","type":"address"},{"name":"stakingLimit","type":"uint64"},{"name":"stoppedValidators","type":"uint64"},{"name":"totalSigningKeys","type":"uint64"},{"name":"usedSigningKeys","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakingModuleSummary","outputs":[{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_vettedSigningKeysCount","type":"uint64"}],"name":"setNodeOperatorStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"name":"isTargetLimitActive","type":"bool"},{"name":"targetValidatorsCount","type":"uint256"},{"name":"stuckValidatorsCount","type":"uint256"},{"name":"refundedValidatorsCount","type":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256"},{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"getSigningKey","outputs":[{"name":"key","type":"bytes"},{"name":"depositSignature","type":"bytes"},{"name":"used","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATOR_NAME_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"name":"depositsCount","type":"uint256"},{"name":"publicKeys","type":"bytes"},{"name":"signatures","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getKeysOpIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SET_NODE_OPERATOR_LIMIT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getTotalSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"}],"name":"updateExitedValidatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"updateStuckValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATORS_COUNT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKeyOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"handleRewardsMinted","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"},{"name":"_stuckValidatorsKeysCount","type":"uint256"}],"name":"unsafeUpdateValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_SIGNING_KEYS","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"active","type":"bool"}],"name":"NodeOperatorActiveSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"}],"name":"NodeOperatorNameSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"rewardAddress","type":"address"}],"name":"NodeOperatorRewardAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorStakingLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalStopped","type":"uint64"}],"name":"NodeOperatorTotalStoppedValidatorsReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalKeysTrimmed","type":"uint64"}],"name":"NodeOperatorTotalKeysTrimmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keysOpIndex","type":"uint256"}],"name":"KeysOpIndexSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"moduleType","type":"bytes32"}],"name":"StakingModuleTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"RewardsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"locatorAddress","type":"address"}],"name":"LocatorContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"approvedValidatorsCount","type":"uint256"}],"name":"VettedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"depositedValidatorsCount","type":"uint256"}],"name":"DepositedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"exitedValidatorsCount","type":"uint256"}],"name":"ExitedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalValidatorsCount","type":"uint256"}],"name":"TotalSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nonce","type":"uint256"}],"name":"NonceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"}],"name":"StuckValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"RefundedValidatorsCount","type":"uint256"}],"name":"RefundedValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"targetValidatorsCount","type":"uint256"}],"name":"TargetValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipientAddress","type":"address"},{"indexed":false,"name":"sharesPenalizedAmount","type":"uint256"}],"name":"NodeOperatorPenalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getType","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getNodeOperatorIds","outputs":[{"name":"nodeOperatorIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getSigningKeys","outputs":[{"name":"pubkeys","type":"bytes"},{"name":"signatures","type":"bytes"},{"name":"used","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorIsActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_name","type":"string"}],"name":"setNodeOperatorName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_totalRewardShares","type":"uint256"}],"name":"getRewardsDistribution","outputs":[{"name":"recipients","type":"address[]"},{"name":"shares","type":"uint256[]"},{"name":"penalized","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_indexFrom","type":"uint256"},{"name":"_indexTo","type":"uint256"}],"name":"invalidateReadyToDepositKeysRange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint64"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_delay","type":"uint256"}],"name":"setStuckPenaltyDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStuckPenaltyDelay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"deactivateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_ROUTER_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onAllValidatorCountersUpdated","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getActiveNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_rewardAddress","type":"address"}],"name":"addNodeOperator","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getUnusedSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_NODE_OPERATOR_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onWithdrawalCredentialsChanged","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"activateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_rewardAddress","type":"address"}],"name":"setNodeOperatorRewardAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fullInfo","type":"bool"}],"name":"getNodeOperator","outputs":[{"name":"active","type":"bool"},{"name":"name","type":"string"},{"name":"rewardAddress","type":"address"},{"name":"stakingLimit","type":"uint64"},{"name":"stoppedValidators","type":"uint64"},{"name":"totalSigningKeys","type":"uint64"},{"name":"usedSigningKeys","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakingModuleSummary","outputs":[{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_vettedSigningKeysCount","type":"uint64"}],"name":"setNodeOperatorStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"name":"isTargetLimitActive","type":"bool"},{"name":"targetValidatorsCount","type":"uint256"},{"name":"stuckValidatorsCount","type":"uint256"},{"name":"refundedValidatorsCount","type":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256"},{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"getSigningKey","outputs":[{"name":"key","type":"bytes"},{"name":"depositSignature","type":"bytes"},{"name":"used","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATOR_NAME_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"name":"depositsCount","type":"uint256"},{"name":"publicKeys","type":"bytes"},{"name":"signatures","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getKeysOpIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SET_NODE_OPERATOR_LIMIT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getTotalSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"}],"name":"updateExitedValidatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"updateStuckValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATORS_COUNT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKeyOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"handleRewardsMinted","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"unsafeUpdateValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_SIGNING_KEYS","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"active","type":"bool"}],"name":"NodeOperatorActiveSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"}],"name":"NodeOperatorNameSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"rewardAddress","type":"address"}],"name":"NodeOperatorRewardAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorStakingLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalStopped","type":"uint64"}],"name":"NodeOperatorTotalStoppedValidatorsReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalKeysTrimmed","type":"uint64"}],"name":"NodeOperatorTotalKeysTrimmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keysOpIndex","type":"uint256"}],"name":"KeysOpIndexSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"moduleType","type":"bytes32"}],"name":"StakingModuleTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"RewardsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"locatorAddress","type":"address"}],"name":"LocatorContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"approvedValidatorsCount","type":"uint256"}],"name":"VettedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"depositedValidatorsCount","type":"uint256"}],"name":"DepositedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"exitedValidatorsCount","type":"uint256"}],"name":"ExitedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalValidatorsCount","type":"uint256"}],"name":"TotalSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nonce","type":"uint256"}],"name":"NonceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"}],"name":"StuckValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"RefundedValidatorsCount","type":"uint256"}],"name":"RefundedValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"targetValidatorsCount","type":"uint256"}],"name":"TargetValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipientAddress","type":"address"},{"indexed":false,"name":"sharesPenalizedAmount","type":"uint256"}],"name":"NodeOperatorPenalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"}] \ No newline at end of file From 963cfecb2baca7de11868b25badfeed70c6ea4c5 Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Sat, 11 Feb 2023 16:09:18 +0300 Subject: [PATCH 08/82] fix tests --- .../OracleReportSanityCheckerMocks.sol | 11 +- test/0.4.24/lido-handle-oracle-report.test.js | 109 ++++++++---------- test/helpers/oracle.js | 2 +- test/helpers/protocol.js | 12 +- test/helpers/staking-modules.js | 4 +- .../scenario/changing_oracles_during_epoch.js | 5 +- 6 files changed, 68 insertions(+), 75 deletions(-) diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index 35feafa8c..cb83f4ecf 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -76,11 +76,18 @@ contract LidoLocatorStub is ILidoLocator { } contract OracleReportSanityCheckerStub { + + error SelectorNotFound(bytes4 sig, uint256 value, bytes data); + + fallback() external payable { revert SelectorNotFound(msg.sig, msg.value, msg.data); } + function checkLidoOracleReport( uint256 _timeElapsed, uint256 _preCLBalance, uint256 _postCLBalance, - uint256 _withdrawalVaultBalance + uint256 _withdrawalVaultBalance, + uint256 _preCLValidators, + uint256 _postCLValidators ) external view {} function checkWithdrawalQueueOracleReport( @@ -102,4 +109,6 @@ contract OracleReportSanityCheckerStub { elRewards = _elRewardsVaultBalance; sharesToBurnLimit = _etherToLockForWithdrawals; } + + function checkAccountingExtraDataListItemsCount(uint256 _extraDataListItemsCount) external view {} } diff --git a/test/0.4.24/lido-handle-oracle-report.test.js b/test/0.4.24/lido-handle-oracle-report.test.js index 3e3fbdb4b..501dce80c 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -6,10 +6,11 @@ const { EvmSnapshot } = require('../helpers/blockchain') const { ZERO_ADDRESS } = require('../helpers/constants') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') +const ETHForwarderMock = artifacts.require('ETHForwarderMock') const ONE_YEAR = 3600 * 24 * 365 -contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, depositor, operator]) => { - let deployed, snapshot, lido, treasury, voting +contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, anotherStranger, depositor, operator]) => { + let deployed, snapshot, lido, treasury, voting, oracle let curatedModule, oracleReportSanityChecker let strangerBalanceBefore, anotherStrangerBalanceBefore, @@ -36,6 +37,9 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, } }) + ETHForwarderMock.new(deployed.oracle.address, { from: appManager }) + await hre.ethers.getImpersonatedSigner(deployed.oracle.address) + await curatedModule.addNodeOperator('1', operator, { from: deployed.voting.address }) const keysAmount = 50 const keys1 = genKeys(keysAmount) @@ -45,6 +49,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, lido = deployed.pool treasury = deployed.treasury.address voting = deployed.voting.address + oracle = deployed.oracle.address oracleReportSanityChecker = deployed.oracleReportSanityChecker await lido.submit(ZERO_ADDRESS, { from: stranger, value: ETH(30) }) @@ -52,7 +57,6 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, await checkStat({ depositedValidators: 0, beaconValidators: 0, beaconBalance: 0 }) - snapshot = new EvmSnapshot(hre.ethers.provider) await snapshot.make() }) @@ -128,7 +132,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, }) it('zero report should do nothing', async () => { - await lido.handleOracleReportDirect(0, 0, 0, 0, 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 0, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -153,7 +157,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, }) it('first report after deposit without rewards', async () => { - await lido.handleOracleReportDirect(0, 0, 1, ETH(32), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 1, beaconBalance: ETH(32) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -166,7 +170,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, it('first report after deposit with rewards', async () => { // elapsed time set to 1000000 because of annualBalanceIncrease limited by 10000 - await lido.handleOracleReportDirect(0, 1000000, 1, ETH(33), 0, 0, 0, 0) + await lido.handleOracleReport(0, 1000000, 1, ETH(33), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 1, beaconBalance: ETH(33) }) await checkBalanceDeltas({ @@ -185,25 +189,34 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, }) it('reverts on reported more than deposited', async () => { - await assert.reverts(lido.handleOracleReportDirect(0, 0, 4, 0, 0, 0, 0, 0), 'REPORTED_MORE_DEPOSITED') + await assert.reverts(lido.handleOracleReport(0, 0, 4, 0, 0, 0, 0, 0, { from: oracle }), 'REPORTED_MORE_DEPOSITED') }) it('reverts on reported less than reported previously', async () => { - await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) - await assert.reverts(lido.handleOracleReportDirect(0, 0, 2, 0, 0, 0, 0, 0), 'REPORTED_LESS_VALIDATORS') + await assert.reverts( + lido.handleOracleReport(0, 0, 2, 0, 0, 0, 0, 0, { from: oracle }), + 'REPORTED_LESS_VALIDATORS' + ) }) it('withdrawal vault balance check', async () => { - await assert.reverts(lido.handleOracleReportDirect(0, 0, 0, 0, 1, 0, 0, 0), 'IncorrectWithdrawalsVaultBalance(0)') + await assert.reverts( + lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, { from: oracle }), + 'IncorrectWithdrawalsVaultBalance(0)' + ) }) it('withdrawal vault balance check', async () => { - await assert.reverts(lido.handleOracleReportDirect(0, 0, 0, 0, 1, 0, 0, 0), 'IncorrectWithdrawalsVaultBalance(0)') + await assert.reverts( + lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, { from: oracle }), + 'IncorrectWithdrawalsVaultBalance(0)' + ) }) it('does not revert on new total balance stay the same', async () => { - await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -212,7 +225,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, anotherStrangerBalanceDiff: 0, curatedModuleBalanceDiff: 0 }) - await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -227,18 +240,19 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits( { - churnValidatorsByEpochLimit: 255, + churnValidatorsPerDayLimit: 255, oneOffCLBalanceDecreaseBPLimit: 100, annualBalanceIncreaseBPLimit: 10000, shareRateDeviationBPLimit: 10000, maxValidatorExitRequestsPerReport: 10000, requestTimestampMargin: 0, - maxPositiveTokenRebase: 1000000000 + maxPositiveTokenRebase: 1000000000, + maxAccountingExtraDataListItemsCount: 10000 }, { from: voting } ) - await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -247,7 +261,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, anotherStrangerBalanceDiff: 0, curatedModuleBalanceDiff: 0 }) - await lido.handleOracleReportDirect(0, 0, 3, ETH(95.04), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.04) }) await checkBalanceDeltas({ @@ -263,18 +277,19 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits( { - churnValidatorsByEpochLimit: 255, + churnValidatorsPerDayLimit: 255, oneOffCLBalanceDecreaseBPLimit: 100, annualBalanceIncreaseBPLimit: 10000, shareRateDeviationBPLimit: 10000, maxValidatorExitRequestsPerReport: 10000, requestTimestampMargin: 0, - maxPositiveTokenRebase: 1000000000 + maxPositiveTokenRebase: 1000000000, + maxAccountingExtraDataListItemsCount: 10000 }, { from: voting } ) - await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -284,7 +299,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, curatedModuleBalanceDiff: 0 }) await assert.reverts( - lido.handleOracleReportDirect(0, 0, 3, ETH(95.03), 0, 0, 0, 0), + lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, 0, { from: oracle }), 'IncorrectCLBalanceDecrease(101)' ) }) @@ -293,18 +308,19 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, // set annualBalanceIncreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits( { - churnValidatorsByEpochLimit: 255, + churnValidatorsPerDayLimit: 255, oneOffCLBalanceDecreaseBPLimit: 100, annualBalanceIncreaseBPLimit: 100, shareRateDeviationBPLimit: 10000, maxValidatorExitRequestsPerReport: 10000, requestTimestampMargin: 0, - maxPositiveTokenRebase: 1000000000 + maxPositiveTokenRebase: 1000000000, + maxAccountingExtraDataListItemsCount: 10000 }, { from: voting } ) - await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -313,7 +329,7 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, anotherStrangerBalanceDiff: 0, curatedModuleBalanceDiff: 0 }) - await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.96) }) await checkBalanceDeltas({ @@ -329,18 +345,19 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, // set annualBalanceIncreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits( { - churnValidatorsByEpochLimit: 255, + churnValidatorsPerDayLimit: 255, oneOffCLBalanceDecreaseBPLimit: 100, annualBalanceIncreaseBPLimit: 100, shareRateDeviationBPLimit: 10000, maxValidatorExitRequestsPerReport: 10000, requestTimestampMargin: 0, - maxPositiveTokenRebase: 1000000000 + maxPositiveTokenRebase: 1000000000, + maxAccountingExtraDataListItemsCount: 10000 }, { from: voting } ) - await lido.handleOracleReportDirect(0, 0, 3, ETH(96), 0, 0, 0, 0) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -350,43 +367,9 @@ contract('Lido: handleOracleReport', ([, , , , , , , stranger, anotherStranger, curatedModuleBalanceDiff: 0 }) await assert.reverts( - lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0), + lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0, { from: oracle }), 'IncorrectCLBalanceIncrease(101)' ) }) - - it('check finalization share rate', async () => { - await oracleReportSanityChecker.setOracleReportLimits( - { - churnValidatorsByEpochLimit: 255, - oneOffCLBalanceDecreaseBPLimit: 10000, - annualBalanceIncreaseBPLimit: 10000, - shareRateDeviationBPLimit: 100, - maxValidatorExitRequestsPerReport: 10000, - requestTimestampMargin: 0, - maxPositiveTokenRebase: 1000000000 - }, - { from: voting } - ) - await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, ETH(1)) - assert.equals(await lido.getPooledEthByShares(ETH(1)), ETH(1.009)) - await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, ETH(1)) - }) - - it('check finalization share rate', async () => { - await oracleReportSanityChecker.setOracleReportLimits( - { - churnValidatorsByEpochLimit: 255, - oneOffCLBalanceDecreaseBPLimit: 10000, - annualBalanceIncreaseBPLimit: 10000, - shareRateDeviationBPLimit: 100, - maxValidatorExitRequestsPerReport: 10000, - requestTimestampMargin: 0, - maxPositiveTokenRebase: 1000000000 - }, - { from: voting } - ) - await lido.handleOracleReportDirect(0, ONE_YEAR, 3, ETH(95), 0, 0, 0, ETH(1)) - }) }) }) diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index 845e4c260..114c96e61 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -53,7 +53,7 @@ async function pushOracleReport(consensus, oracle, numValidators, clBalance, elR lastWithdrawalRequestIdToFinalize: 0, finalizationShareRate: 0, isBunkerMode: false, - extraDataFormat: 0, + extraDataFormat: 1, extraDataHash: ZERO_BYTES32, extraDataItemsCount: 0 } diff --git a/test/helpers/protocol.js b/test/helpers/protocol.js index ae0f908c0..68e1c2879 100644 --- a/test/helpers/protocol.js +++ b/test/helpers/protocol.js @@ -28,6 +28,13 @@ async function deployProtocol(factories = {}, deployParams = {}) { protocol.depositContract = await protocol.factories.depositContractFactory(protocol) + protocol.burner = await protocol.factories.burnerFactory(protocol) + protocol.lidoLocator = await protocol.factories.lidoLocatorFactory(protocol) + await updateLocatorImplementation(protocol.lidoLocator.address, protocol.appManager.address, { + lido: protocol.pool.address, + burner: protocol.burner.address + }) + protocol.withdrawalCredentials = await protocol.factories.withdrawalCredentialsFactory(protocol) protocol.stakingRouter = await protocol.factories.stakingRouterFactory(protocol) protocol.stakingModules = await addStakingModules(protocol.factories.stakingModulesFactory, protocol) @@ -36,16 +43,11 @@ async function deployProtocol(factories = {}, deployParams = {}) { protocol.elRewardsVault = await protocol.factories.elRewardsVaultFactory(protocol) protocol.withdrawalVault = await protocol.factories.withdrawalVaultFactory(protocol) protocol.eip712StETH = await protocol.factories.eip712StETHFactory(protocol) - protocol.burner = await protocol.factories.burnerFactory(protocol) - - protocol.lidoLocator = await protocol.factories.lidoLocatorFactory(protocol) await updateLocatorImplementation(protocol.lidoLocator.address, protocol.appManager.address, { - lido: protocol.pool.address, depositSecurityModule: protocol.depositSecurityModule.address, elRewardsVault: protocol.elRewardsVault.address, legacyOracle: protocol.legacyOracle.address, - burner: protocol.burner.address, stakingRouter: protocol.stakingRouter.address, treasury: protocol.treasury.address, withdrawalVault: protocol.withdrawalVault.address, diff --git a/test/helpers/staking-modules.js b/test/helpers/staking-modules.js index 0c90f68f2..85e08e404 100644 --- a/test/helpers/staking-modules.js +++ b/test/helpers/staking-modules.js @@ -2,7 +2,7 @@ const { newApp } = require('./dao') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') const NodeOperatorsRegistryMock = artifacts.require('NodeOperatorsRegistryMock') -async function setupNodeOperatorsRegistry({ dao, acl, token, stakingRouter, voting, appManager }, mock = false) { +async function setupNodeOperatorsRegistry({ dao, acl, lidoLocator, stakingRouter, voting, appManager }, mock = false) { const nodeOperatorsRegistryBase = mock ? await NodeOperatorsRegistryMock.new() : await NodeOperatorsRegistry.new() const name = 'node-operators-registry-' + Math.random().toString(36).slice(2, 6) const nodeOperatorsRegistryProxyAddress = await newApp( @@ -16,7 +16,7 @@ async function setupNodeOperatorsRegistry({ dao, acl, token, stakingRouter, voti ? await NodeOperatorsRegistryMock.at(nodeOperatorsRegistryProxyAddress) : await NodeOperatorsRegistry.at(nodeOperatorsRegistryProxyAddress) - await nodeOperatorsRegistry.initialize(token.address, '0x01') + await nodeOperatorsRegistry.initialize(lidoLocator.address, '0x01') const [ NODE_OPERATOR_REGISTRY_MANAGE_SIGNING_KEYS, diff --git a/test/scenario/changing_oracles_during_epoch.js b/test/scenario/changing_oracles_during_epoch.js index 661876c8d..d041a9ba6 100644 --- a/test/scenario/changing_oracles_during_epoch.js +++ b/test/scenario/changing_oracles_during_epoch.js @@ -38,10 +38,9 @@ contract('AccountingOracle', ([appManager, voting, malicious1, malicious2, membe lastWithdrawalRequestIdToFinalize: 0, finalizationShareRate: 0, isBunkerMode: false, - extraDataFormat: 0, + extraDataFormat: 1, extraDataHash: ZERO_HASH, - extraDataItemsCount: 0, - extraDataMaxNodeOpsCountByModule: 0, + extraDataItemsCount: 0 } const BAD_DATA = { From 729f10abedb49eef452941569832be8ff2e835cd Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 17:20:21 +0300 Subject: [PATCH 09/82] feat: DSM with custom errors instead of strs --- contracts/0.8.9/DepositSecurityModule.sol | 62 +++++++++------- lib/abi/DepositSecurityModule.json | 2 +- test/0.8.9/deposit-security-module.test.js | 86 +++++++++++++++------- 3 files changed, 94 insertions(+), 56 deletions(-) diff --git a/contracts/0.8.9/DepositSecurityModule.sol b/contracts/0.8.9/DepositSecurityModule.sol index 28dc696aa..eda576ccf 100644 --- a/contracts/0.8.9/DepositSecurityModule.sol +++ b/contracts/0.8.9/DepositSecurityModule.sol @@ -49,6 +49,14 @@ contract DepositSecurityModule { event DepositsUnpaused(uint24 indexed stakingModuleId); error ErrorStakingModuleIdTooLarge(); + error ErrorZeroAddress(string field); + error ErrorDuplicateAddress(address addr); + error ErrorNotAnOwner(address caller); + error ErrorSignature(string reason); + error ErrorDeposit(string reason); + error ErrorPauseIntentExpired(); + error ErrorNotAGuardian(address addr); + error ErrorZeroParameter(string parameter); bytes32 public immutable ATTEST_MESSAGE_PREFIX; bytes32 public immutable PAUSE_MESSAGE_PREFIX; @@ -75,9 +83,9 @@ contract DepositSecurityModule { uint256 _minDepositBlockDistance, uint256 _pauseIntentValidityPeriodBlocks ) { - require(_lido != address(0), "LIDO_CONTRACT_ZERO_ADDRESS"); - require(_stakingRouter != address(0), "STAKING_ROUTER_ZERO_ADDRESS"); - require(_depositContract != address(0), "DEPOSIT_CONTRACT_ZERO_ADDRESS"); + if (_lido == address(0)) revert ErrorZeroAddress("_lido"); + if (_depositContract == address(0)) revert ErrorZeroAddress ("_depositContract"); + if (_stakingRouter == address(0)) revert ErrorZeroAddress ("_stakingRouter"); LIDO = ILido(_lido); STAKING_ROUTER = IStakingRouter(_stakingRouter); @@ -115,7 +123,7 @@ contract DepositSecurityModule { } modifier onlyOwner() { - require(msg.sender == owner, "not an owner"); + if (msg.sender != owner) revert ErrorNotAnOwner(msg.sender); _; } @@ -131,10 +139,10 @@ contract DepositSecurityModule { _setOwner(newValue); } - function _setOwner(address newValue) internal { - require(newValue != address(0), "invalid value for owner: must be different from zero address"); - owner = newValue; - emit OwnerChanged(newValue); + function _setOwner(address _newOwner) internal { + if (_newOwner == address(0)) revert ErrorZeroAddress("_newOwner"); + owner = _newOwner; + emit OwnerChanged(_newOwner); } /** @@ -152,7 +160,7 @@ contract DepositSecurityModule { } function _setPauseIntentValidityPeriodBlocks(uint256 newValue) internal { - require(newValue > 0, "invalid value for pauseIntentValidityPeriodBlocks: must be greater then 0"); + if (newValue == 0) revert ErrorZeroParameter("pauseIntentValidityPeriodBlocks"); pauseIntentValidityPeriodBlocks = newValue; emit PauseIntentValidityPeriodBlocksChanged(newValue); } @@ -191,7 +199,7 @@ contract DepositSecurityModule { } function _setMinDepositBlockDistance(uint256 newValue) internal { - require(newValue > 0, "invalid value for minDepositBlockDistance: must be greater then 0"); + if (newValue == 0) revert ErrorZeroParameter("minDepositBlockDistance"); if (newValue != minDepositBlockDistance) { minDepositBlockDistance = newValue; emit MinDepositBlockDistanceChanged(newValue); @@ -270,12 +278,12 @@ contract DepositSecurityModule { _setGuardianQuorum(newQuorum); } - function _addGuardian(address addr) internal { - require(addr != address(0), "guardian zero address"); - require(!_isGuardian(addr), "duplicate address"); - guardians.push(addr); - guardianIndicesOneBased[addr] = guardians.length; - emit GuardianAdded(addr); + function _addGuardian(address _newGuardian) internal { + if (_newGuardian == address(0)) revert ErrorZeroAddress("_newGuardian"); + if (_isGuardian(_newGuardian)) revert ErrorDuplicateAddress(_newGuardian); + guardians.push(_newGuardian); + guardianIndicesOneBased[_newGuardian] = guardians.length; + emit GuardianAdded(_newGuardian); } /** @@ -285,7 +293,7 @@ contract DepositSecurityModule { */ function removeGuardian(address addr, uint256 newQuorum) external onlyOwner { uint256 indexOneBased = guardianIndicesOneBased[addr]; - require(indexOneBased != 0, "not a guardian"); + if (indexOneBased == 0) revert ErrorNotAGuardian(addr); uint256 totalGuardians = guardians.length; assert(indexOneBased <= totalGuardians); @@ -340,10 +348,10 @@ contract DepositSecurityModule { bytes32 msgHash = keccak256(abi.encodePacked(PAUSE_MESSAGE_PREFIX, blockNumber, stakingModuleId)); guardianAddr = ECDSA.recover(msgHash, sig.r, sig.vs); guardianIndex = _getGuardianIndex(guardianAddr); - require(guardianIndex != -1, "invalid signature"); + if (guardianIndex == -1) revert ErrorSignature("invalid"); } - require(block.number - blockNumber <= pauseIntentValidityPeriodBlocks, "pause intent expired"); + if (block.number - blockNumber > pauseIntentValidityPeriodBlocks) revert ErrorPauseIntentExpired(); STAKING_ROUTER.pauseStakingModule(stakingModuleId); emit DepositsPaused(guardianAddr, uint24(stakingModuleId)); @@ -398,19 +406,19 @@ contract DepositSecurityModule { bytes calldata depositCalldata, Signature[] calldata sortedGuardianSignatures ) external validStakingModuleId(stakingModuleId) { - require(quorum > 0 && sortedGuardianSignatures.length >= quorum, "no guardian quorum"); + if (quorum == 0 || sortedGuardianSignatures.length < quorum) revert ErrorDeposit("no quorum"); bytes32 onchainDepositRoot = IDepositContract(DEPOSIT_CONTRACT).get_deposit_root(); - require(depositRoot == onchainDepositRoot, "deposit root changed"); + if (depositRoot != onchainDepositRoot) revert ErrorDeposit("deposit root changed"); - require(STAKING_ROUTER.getStakingModuleIsActive(stakingModuleId), "module not active"); + if (!STAKING_ROUTER.getStakingModuleIsActive(stakingModuleId)) revert ErrorDeposit("inactive module"); uint256 lastDepositBlock = STAKING_ROUTER.getStakingModuleLastDepositBlock(stakingModuleId); - require(block.number - lastDepositBlock >= minDepositBlockDistance, "too frequent deposits"); - require(blockHash != bytes32(0) && blockhash(blockNumber) == blockHash, "unexpected block hash"); + if (block.number - lastDepositBlock < minDepositBlockDistance) revert ErrorDeposit("too frequent"); + if (blockHash == bytes32(0) || blockhash(blockNumber) != blockHash) revert ErrorDeposit("unexpected block hash"); uint256 onchainNonce = STAKING_ROUTER.getStakingModuleNonce(stakingModuleId); - require(nonce == onchainNonce, "nonce changed"); + if (nonce != onchainNonce) revert ErrorDeposit("nonce changed"); _verifySignatures(depositRoot, blockNumber, blockHash, stakingModuleId, nonce, sortedGuardianSignatures); @@ -433,8 +441,8 @@ contract DepositSecurityModule { for (uint256 i = 0; i < sigs.length; ++i) { address signerAddr = ECDSA.recover(msgHash, sigs[i].r, sigs[i].vs); - require(_isGuardian(signerAddr), "invalid signature"); - require(signerAddr > prevSignerAddr, "signatures not sorted"); + if (!_isGuardian(signerAddr)) revert ErrorSignature("invalid"); + if (signerAddr <= prevSignerAddr) revert ErrorSignature("not sorted"); prevSignerAddr = signerAddr; } } diff --git a/lib/abi/DepositSecurityModule.json b/lib/abi/DepositSecurityModule.json index d71f3879b..2e469d207 100644 --- a/lib/abi/DepositSecurityModule.json +++ b/lib/abi/DepositSecurityModule.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_lido","type":"address"},{"internalType":"address","name":"_depositContract","type":"address"},{"internalType":"address","name":"_stakingRouter","type":"address"},{"internalType":"uint256","name":"_maxDepositsPerBlock","type":"uint256"},{"internalType":"uint256","name":"_minDepositBlockDistance","type":"uint256"},{"internalType":"uint256","name":"_pauseIntentValidityPeriodBlocks","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorStakingModuleIdTooLarge","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"GuardianQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MaxDepositsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MinDepositBlockDistanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"PauseIntentValidityPeriodBlocksChanged","type":"event"},{"inputs":[],"name":"ATTEST_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_ROUTER","outputs":[{"internalType":"contract IStakingRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardians","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"depositRoot","type":"bytes32"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"depositCalldata","type":"bytes"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature[]","name":"sortedGuardianSignatures","type":"tuple[]"}],"name":"depositBufferedEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getGuardianIndex","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardianQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardians","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinDepositBlockDistance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauseIntentValidityPeriodBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature","name":"sig","type":"tuple"}],"name":"pauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"removeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setGuardianQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMinDepositBlockDistance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setPauseIntentValidityPeriodBlocks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_lido","type":"address"},{"internalType":"address","name":"_depositContract","type":"address"},{"internalType":"address","name":"_stakingRouter","type":"address"},{"internalType":"uint256","name":"_maxDepositsPerBlock","type":"uint256"},{"internalType":"uint256","name":"_minDepositBlockDistance","type":"uint256"},{"internalType":"uint256","name":"_pauseIntentValidityPeriodBlocks","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"ErrorDeposit","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"ErrorDuplicateAddress","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"ErrorNotAGuardian","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"ErrorNotAnOwner","type":"error"},{"inputs":[],"name":"ErrorPauseIntentExpired","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"ErrorSignature","type":"error"},{"inputs":[],"name":"ErrorStakingModuleIdTooLarge","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ErrorZeroAddress","type":"error"},{"inputs":[{"internalType":"string","name":"parameter","type":"string"}],"name":"ErrorZeroParameter","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"GuardianQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MaxDepositsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MinDepositBlockDistanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"PauseIntentValidityPeriodBlocksChanged","type":"event"},{"inputs":[],"name":"ATTEST_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_ROUTER","outputs":[{"internalType":"contract IStakingRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardians","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"depositRoot","type":"bytes32"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"depositCalldata","type":"bytes"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature[]","name":"sortedGuardianSignatures","type":"tuple[]"}],"name":"depositBufferedEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getGuardianIndex","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardianQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardians","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinDepositBlockDistance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauseIntentValidityPeriodBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature","name":"sig","type":"tuple"}],"name":"pauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"removeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setGuardianQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMinDepositBlockDistance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setPauseIntentValidityPeriodBlocks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/test/0.8.9/deposit-security-module.test.js b/test/0.8.9/deposit-security-module.test.js index 23e156c79..76a4ba38d 100644 --- a/test/0.8.9/deposit-security-module.test.js +++ b/test/0.8.9/deposit-security-module.test.js @@ -130,7 +130,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { from: stranger } ), - 'no guardian quorum' + 'ErrorDeposit("no quorum")' ) }) }) @@ -174,7 +174,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN2])] ), - 'invalid signature' + 'ErrorSignature("invalid")' ) }) @@ -189,7 +189,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [] ), - 'no guardian quorum' + 'ErrorDeposit("no quorum")' ) }) @@ -209,7 +209,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'deposit root changed' + 'ErrorDeposit("deposit root changed")' ) }) @@ -228,7 +228,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'nonce changed' + 'ErrorDeposit("nonce changed")' ) }) @@ -249,7 +249,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'too frequent deposits' + 'ErrorDeposit("too frequent")' ) }) @@ -270,7 +270,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'module not active' + 'ErrorDeposit("inactive module")' ) }) @@ -288,7 +288,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'unexpected block hash' + 'ErrorDeposit("unexpected block hash")' ) }) @@ -298,7 +298,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { depositSecurityModule.depositBufferedEther(block.number, '0x', DEPOSIT_ROOT, STAKING_MODULE, DEPOSIT_NONCE, DEPOSIT_CALLDATA, [ validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1]) ]), - 'unexpected block hash' + 'ErrorDeposit("unexpected block hash")' ) }) }) @@ -419,7 +419,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { [], { from: stranger } ), - 'no guardian quorum' + 'ErrorDeposit("no quorum")' ) }) it("cannot deposit with guardian's sigs (1,0)", async () => { @@ -439,7 +439,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { signatures, { from: stranger } ), - 'signatures not sorted' + 'ErrorSignature("not sorted")' ) }) @@ -460,7 +460,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { signatures, { from: stranger } ), - 'signatures not sorted' + 'ErrorSignature("not sorted")' ) }) @@ -481,7 +481,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { signatures, { from: stranger } ), - 'invalid signature' + 'ErrorSignature("invalid")' ) }) }) @@ -548,7 +548,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { validPauseMessage.sign(UNRELATED_SIGNER_PRIVATE_KEYS[UNRELATED_SIGNER1]), { from: guardian } ), - 'pause intent expired' + 'ErrorPauseIntentExpired()' ) }) @@ -560,7 +560,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { stalePauseMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN2]), { from: stranger } ), - 'pause intent expired' + 'ErrorPauseIntentExpired()' ) }) @@ -645,7 +645,10 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { }) it('cannot be called by non-admin', async () => { - await assertRevert(depositSecurityModule.unpauseDeposits(STAKING_MODULE, { from: stranger }), 'not an owner') + await assertRevert( + depositSecurityModule.unpauseDeposits(STAKING_MODULE, { from: stranger }), + `ErrorNotAnOwner("${stranger}")` + ) }) }) describe('Guardians', () => { @@ -654,7 +657,10 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { assert.equal((await depositSecurityModule.getGuardians()).length, 0) }) it(`addGuardian can't be called by non-admin`, async () => { - await assertRevert(depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: stranger }), 'not an owner') + await assertRevert( + depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: stranger }), + `ErrorNotAnOwner("${stranger}")` + ) }) it(`addGuardian adds a guardian`, async () => { await depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: owner }) @@ -687,10 +693,16 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { }) it(`addGuardian doesn't add duplicate`, async () => { await depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: owner }) - await assertRevert(depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: owner }), 'duplicate address') + await assertRevert( + depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: owner }), + `ErrorDuplicateAddress("${GUARDIAN1}")` + ) }) it(`addGuardians can't be called by non-admin`, async () => { - await assertRevert(depositSecurityModule.addGuardians([GUARDIAN1], 0, { from: stranger }), 'not an owner') + await assertRevert( + depositSecurityModule.addGuardians([GUARDIAN1], 0, { from: stranger }), + `ErrorNotAnOwner("${stranger}")` + ) }) it(`addGuardians adds set of guardians`, async () => { await depositSecurityModule.addGuardians([GUARDIAN1, GUARDIAN2], 0, { from: owner }) @@ -701,15 +713,27 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { assert.isTrue((await depositSecurityModule.getGuardians()).includes(GUARDIAN2)) }) it(`addGuardians doesn't add a set with duplicate`, async () => { - await assertRevert(depositSecurityModule.addGuardians([GUARDIAN1, GUARDIAN1], 0, { from: owner }), 'duplicate address') + await assertRevert( + depositSecurityModule.addGuardians([GUARDIAN1, GUARDIAN1], 0, { from: owner }), + `ErrorDuplicateAddress("${GUARDIAN1}")` + ) await depositSecurityModule.addGuardians([GUARDIAN1], 0, { from: owner }) - await assertRevert(depositSecurityModule.addGuardians([GUARDIAN1, GUARDIAN2], 0, { from: owner }), 'duplicate address') + await assertRevert( + depositSecurityModule.addGuardians([GUARDIAN1, GUARDIAN2], 0, { from: owner }), + `ErrorDuplicateAddress("${GUARDIAN1}")` + ) }) it(`removeGuardian can't be called by non-admin`, async () => { - await assertRevert(depositSecurityModule.removeGuardian(GUARDIAN1, 0, { from: stranger }), 'not an owner') + await assertRevert( + depositSecurityModule.removeGuardian(GUARDIAN1, 0, { from: stranger }), + `ErrorNotAnOwner("${stranger}")` + ) }) it(`removeGuardian reverts on incorrect address`, async () => { - await assertRevert(depositSecurityModule.removeGuardian(GUARDIAN1, 0, { from: owner }), 'not a guardian') + await assertRevert( + depositSecurityModule.removeGuardian(GUARDIAN1, 0, { from: owner }), + `ErrorNotAGuardian("${GUARDIAN1}")` + ) }) it(`removeGuardian removes guardian and sets new quorum`, async () => { await depositSecurityModule.addGuardian(GUARDIAN1, 1, { from: owner }) @@ -795,7 +819,10 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { assert.isTrue((await depositSecurityModule.getGuardians()).includes(GUARDIAN1)) }) it(`setGuardianQuorum can't be called by non-admin`, async () => { - await assertRevert(depositSecurityModule.setGuardianQuorum(1, { from: stranger }), 'not an owner') + await assertRevert( + depositSecurityModule.setGuardianQuorum(1, { from: stranger }), + `ErrorNotAnOwner("${stranger}")` + ) }) it(`setGuardianQuorum sets the quorum`, async () => { await depositSecurityModule.setGuardianQuorum(1, { from: owner }) @@ -837,12 +864,15 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { assert.equal(await depositSecurityModule.getOwner(), owner, 'wrong initial owner') }) it('not owner cannot change', async () => { - await assertRevert(depositSecurityModule.setOwner(stranger, { from: stranger }), 'not an owner') + await assertRevert( + depositSecurityModule.setOwner(stranger, { from: stranger }), + `ErrorNotAnOwner("${stranger}")` + ) }) it('set new owner to zero address should reverts', async () => { await assertRevert( depositSecurityModule.setOwner(ZERO_ADDRESS, { from: owner }), - 'invalid value for owner: must be different from zero address' + 'ErrorZeroAddress("_newOwner")' ) }) it('set new owner by owner', async () => { @@ -856,7 +886,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it('pauseIntentValidityPeriodBlocks should be gt 0', async () => { await assertRevert( depositSecurityModule.setPauseIntentValidityPeriodBlocks(0, { from: owner }), - 'invalid value for pauseIntentValidityPeriodBlocks: must be greater then 0' + 'ErrorZeroParameter("pauseIntentValidityPeriodBlocks")' ) }) it('setPauseIntentValidityPeriodBlocks sets new value for pauseIntentValidityPeriodBlocks if called by owner', async () => { @@ -896,7 +926,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it('minDepositBlockDistance should be gt 0', async () => { await assertRevert( depositSecurityModule.setMinDepositBlockDistance(0, { from: owner }), - 'invalid value for minDepositBlockDistance: must be greater then 0' + 'ErrorZeroParameter("minDepositBlockDistance")' ) }) it('setMinDepositBlockDistance sets new value for minDepositBlockDistance if called by owner', async () => { From 6fb0107a4b6d31145c4c7acaf7b7b492a107033c Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 17:21:33 +0300 Subject: [PATCH 10/82] chore: burner errors naming --- contracts/0.8.9/Burner.sol | 16 ++++++++-------- lib/abi/Burner.json | 2 +- test/0.8.9/burner.test.js | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/contracts/0.8.9/Burner.sol b/contracts/0.8.9/Burner.sol index 02b67f7ed..76fa34de2 100644 --- a/contracts/0.8.9/Burner.sol +++ b/contracts/0.8.9/Burner.sol @@ -54,10 +54,10 @@ contract Burner is IBurner, AccessControlEnumerable { error ErrorAppAuthLidoFailed(); error ErrorDirectETHTransfer(); - error ZeroRecoveryAmount(); - error StETHRecoveryWrongFunc(); - error ZeroBurnAmount(); - error NotEnoughExcessStETH(); + error ErrorZeroRecoveryAmount(); + error ErrorStETHRecoveryWrongFunc(); + error ErrorZeroBurnAmount(); + error ErrorNotEnoughExcessStETH(); error ErrorZeroAddress(string field); bytes32 public constant REQUEST_BURN_MY_STETH_ROLE = keccak256("REQUEST_BURN_MY_STETH_ROLE"); @@ -250,8 +250,8 @@ contract Burner is IBurner, AccessControlEnumerable { * @param _amount token amount */ function recoverERC20(address _token, uint256 _amount) external onlyRole(RECOVER_ASSETS_ROLE) { - if (_amount == 0) revert ZeroRecoveryAmount(); - if (_token == STETH) revert StETHRecoveryWrongFunc(); + if (_amount == 0) revert ErrorZeroRecoveryAmount(); + if (_token == STETH) revert ErrorStETHRecoveryWrongFunc(); emit ERC20Recovered(msg.sender, _token, _amount); @@ -266,7 +266,7 @@ contract Burner is IBurner, AccessControlEnumerable { * @param _tokenId minted token id */ function recoverERC721(address _token, uint256 _tokenId) external onlyRole(RECOVER_ASSETS_ROLE) { - if (_token == STETH) revert StETHRecoveryWrongFunc(); + if (_token == STETH) revert ErrorStETHRecoveryWrongFunc(); emit ERC721Recovered(msg.sender, _token, _tokenId); @@ -372,7 +372,7 @@ contract Burner is IBurner, AccessControlEnumerable { } function _requestBurn(uint256 _sharesAmount, uint256 _stETHAmount, bool _isCover) private { - if (_sharesAmount == 0) revert ZeroBurnAmount(); + if (_sharesAmount == 0) revert ErrorZeroBurnAmount(); emit StETHBurnRequested(_isCover, msg.sender, _stETHAmount, _sharesAmount); diff --git a/lib/abi/Burner.json b/lib/abi/Burner.json index 6ffd40e3d..130d96e33 100644 --- a/lib/abi/Burner.json +++ b/lib/abi/Burner.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_stETH","type":"address"},{"internalType":"uint256","name":"_totalCoverSharesBurnt","type":"uint256"},{"internalType":"uint256","name":"_totalNonCoverSharesBurnt","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorAppAuthLidoFailed","type":"error"},{"inputs":[],"name":"ErrorDirectETHTransfer","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ErrorZeroAddress","type":"error"},{"inputs":[],"name":"NotEnoughExcessStETH","type":"error"},{"inputs":[],"name":"StETHRecoveryWrongFunc","type":"error"},{"inputs":[],"name":"ZeroBurnAmount","type":"error"},{"inputs":[],"name":"ZeroRecoveryAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"ExcessStETHRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnt","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECOVER_ASSETS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_MY_STETH_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_SHARES_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesToBurnLimit","type":"uint256"}],"name":"commitSharesToBurn","outputs":[{"internalType":"uint256","name":"sharesToBurnNow","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExcessStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSharesRequestedToBurn","outputs":[{"internalType":"uint256","name":"coverShares","type":"uint256"},{"internalType":"uint256","name":"nonCoverShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverExcessStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETHForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnSharesForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_stETH","type":"address"},{"internalType":"uint256","name":"_totalCoverSharesBurnt","type":"uint256"},{"internalType":"uint256","name":"_totalNonCoverSharesBurnt","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorAppAuthLidoFailed","type":"error"},{"inputs":[],"name":"ErrorDirectETHTransfer","type":"error"},{"inputs":[],"name":"ErrorNotEnoughExcessStETH","type":"error"},{"inputs":[],"name":"ErrorStETHRecoveryWrongFunc","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ErrorZeroAddress","type":"error"},{"inputs":[],"name":"ErrorZeroBurnAmount","type":"error"},{"inputs":[],"name":"ErrorZeroRecoveryAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"ExcessStETHRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnt","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECOVER_ASSETS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_MY_STETH_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_SHARES_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesToBurnLimit","type":"uint256"}],"name":"commitSharesToBurn","outputs":[{"internalType":"uint256","name":"sharesToBurnNow","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExcessStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSharesRequestedToBurn","outputs":[{"internalType":"uint256","name":"coverShares","type":"uint256"},{"internalType":"uint256","name":"nonCoverShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverExcessStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETHForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnSharesForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/test/0.8.9/burner.test.js b/test/0.8.9/burner.test.js index 2dcee2fc0..285830845 100644 --- a/test/0.8.9/burner.test.js +++ b/test/0.8.9/burner.test.js @@ -98,13 +98,13 @@ contract('Burner', ([deployer, _, anotherAccount]) => { // but zero request on cover await assert.revertsWithCustomError( burner.requestBurnMyStETHForCover(StETH(0), { from: voting }), - `ZeroBurnAmount()` + `ErrorZeroBurnAmount()` ) // and zero request on non-cover await assert.revertsWithCustomError( burner.requestBurnMyStETH(StETH(0), { from: voting }), - `ZeroBurnAmount()` + `ErrorZeroBurnAmount()` ) }) @@ -643,7 +643,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { it(`can't recover zero ERC20 amount`, async () => { await assert.revertsWithCustomError( - burner.recoverERC20(mockERC20Token.address, bn(0), { from: voting }), `ZeroRecoveryAmount()` + burner.recoverERC20(mockERC20Token.address, bn(0), { from: voting }), `ErrorZeroRecoveryAmount()` ) }) @@ -670,7 +670,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { // need to use recoverExcessStETH await assert.revertsWithCustomError( burner.recoverERC20(lido.address, StETH(1), { from: voting }), - `StETHRecoveryWrongFunc()` + `ErrorStETHRecoveryWrongFunc()` ) // revert from deployer @@ -755,7 +755,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { ) await assert.revertsWithCustomError( burner.recoverERC721(lido.address, StETH(1), { from: voting }), - `StETHRecoveryWrongFunc()` + `ErrorStETHRecoveryWrongFunc()` ) const receipt = await burner.recoverExcessStETH({ from: voting }) From 3cdaa5973c94ad5d4a8f67421aca420c20ff058b Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 17:22:16 +0300 Subject: [PATCH 11/82] test: unstoppable stETH approvals --- test/0.4.24/steth.test.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/0.4.24/steth.test.js b/test/0.4.24/steth.test.js index e3e3bf026..9dd12219a 100644 --- a/test/0.4.24/steth.test.js +++ b/test/0.4.24/steth.test.js @@ -286,10 +286,12 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { assert(await stEth.isStopped()) await assertRevert(stEth.transfer(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') - await assertRevert(stEth.approve(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') + //NB: can approve if stopped + await stEth.approve(user2, tokens(2), { from: user1 }) await assertRevert(stEth.transferFrom(user2, user3, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') - await assertRevert(stEth.increaseAllowance(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') - await assertRevert(stEth.decreaseAllowance(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') + //NB: can change allowance if stopped + await stEth.increaseAllowance(user2, tokens(2), { from: user1 }) + await stEth.decreaseAllowance(user2, tokens(2), { from: user1 }) await stEth.resume({ from: user1 }) assert.equal(await stEth.isStopped(), false) From d99608a6ad8b09c1b209a39c8606c16ea811353a Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 17:28:37 +0300 Subject: [PATCH 12/82] chore: comment about unused deposit calldata --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index d36df6dc2..d43f79781 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -549,11 +549,13 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @notice Obtains up to _depositsCount deposit data to be used by StakingRouter /// to deposit to the Ethereum Deposit contract + /// @dev the second param is optional staking module calldata + /// (not used for NodeOperatorsRegistry) /// @param _depositsCount Desireable number of deposits to be done /// @return depositsCount Actual deposits count might be done with returned data /// @return publicKeys Batch of the concatenated public validators keys /// @return signatures Batch of the concatenated deposit signatures for returned public keys - function obtainDepositData(uint256 _depositsCount, bytes) + function obtainDepositData(uint256 _depositsCount, bytes /* _depositCalldata */) external returns ( uint256 depositsCount, From e59c88393ecf68f4facd20e6304405d3fa21ac32 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 17:39:24 +0300 Subject: [PATCH 13/82] chore: `ConsensusContractSet`->`ConsensusHashC...` --- contracts/0.8.9/oracle/BaseOracle.sol | 4 ++-- lib/abi/AccountingOracle.json | 2 +- lib/abi/BaseOracle.json | 2 +- lib/abi/ValidatorsExitBusOracle.json | 2 +- test/0.8.9/oracle/validators-exit-bus-oracle-deploy.test.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/0.8.9/oracle/BaseOracle.sol b/contracts/0.8.9/oracle/BaseOracle.sol index 0aadda2fc..827b40f34 100644 --- a/contracts/0.8.9/oracle/BaseOracle.sol +++ b/contracts/0.8.9/oracle/BaseOracle.sol @@ -46,7 +46,7 @@ abstract contract BaseOracle is IReportAsyncProcessor, AccessControlEnumerable, error UnexpectedConsensusVersion(uint256 expectedVersion, uint256 receivedVersion); error UnexpectedDataHash(bytes32 consensusHash, bytes32 receivedHash); - event ConsensusContractSet(address indexed addr, address indexed prevAddr); + event ConsensusHashContractSet(address indexed addr, address indexed prevAddr); event ConsensusVersionSet(uint256 indexed version, uint256 indexed prevVersion); event ReportSubmitted(uint256 indexed refSlot, bytes32 hash, uint256 processingDeadlineTime); event ProcessingStarted(uint256 indexed refSlot, bytes32 hash); @@ -317,7 +317,7 @@ abstract contract BaseOracle is IReportAsyncProcessor, AccessControlEnumerable, } CONSENSUS_CONTRACT_POSITION.setStorageAddress(addr); - emit ConsensusContractSet(addr, prevAddr); + emit ConsensusHashContractSet(addr, prevAddr); } function _getTime() internal virtual view returns (uint256) { diff --git a/lib/abi/AccountingOracle.json b/lib/abi/AccountingOracle.json index 4dc10d650..cb07cf69d 100644 --- a/lib/abi/AccountingOracle.json +++ b/lib/abi/AccountingOracle.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"lidoLocator","type":"address"},{"internalType":"address","name":"lido","type":"address"},{"internalType":"address","name":"legacyOracle","type":"address"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"CannotSubmitExtraDataBeforeMainData","type":"error"},{"inputs":[],"name":"ExtraDataAlreadyProcessed","type":"error"},{"inputs":[],"name":"ExtraDataListOnlySupportsSingleTx","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"IncorrectOracleMigration","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidExitedValidatorsData","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataItem","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataSortOrder","type":"error"},{"inputs":[],"name":"LegacyOracleCannotBeZero","type":"error"},{"inputs":[],"name":"LidoLocatorCannotBeZero","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NumExitedValidatorsCannotDecrease","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedFormat","type":"uint256"},{"internalType":"uint256","name":"receivedFormat","type":"uint256"}],"name":"UnexpectedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedIndex","type":"uint256"},{"internalType":"uint256","name":"receivedIndex","type":"uint256"}],"name":"UnexpectedExtraDataIndex","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedCount","type":"uint256"},{"internalType":"uint256","name":"receivedCount","type":"uint256"}],"name":"UnexpectedExtraDataItemsCount","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"dataType","type":"uint256"}],"name":"UnsupportedExtraDataType","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"ExtraDataSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processedItemsCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"WarnExtraDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_EXITED_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_STUCK_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEGACY_ORACLE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCATOR","outputs":[{"internalType":"contract ILidoLocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"mainDataHash","type":"bytes32"},{"internalType":"bool","name":"mainDataSubmitted","type":"bool"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsSubmitted","type":"uint256"}],"internalType":"struct AccountingOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initializeWithoutMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"numValidators","type":"uint256"},{"internalType":"uint256","name":"clBalanceGwei","type":"uint256"},{"internalType":"uint256[]","name":"stakingModuleIdsWithNewlyExitedValidators","type":"uint256[]"},{"internalType":"uint256[]","name":"numExitedValidatorsByStakingModule","type":"uint256[]"},{"internalType":"uint256","name":"withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"lastWithdrawalRequestIdToFinalize","type":"uint256"},{"internalType":"uint256","name":"finalizationShareRate","type":"uint256"},{"internalType":"bool","name":"isBunkerMode","type":"bool"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"}],"internalType":"struct AccountingOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"items","type":"bytes"}],"name":"submitReportExtraDataList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"lidoLocator","type":"address"},{"internalType":"address","name":"lido","type":"address"},{"internalType":"address","name":"legacyOracle","type":"address"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"CannotSubmitExtraDataBeforeMainData","type":"error"},{"inputs":[],"name":"ExtraDataAlreadyProcessed","type":"error"},{"inputs":[],"name":"ExtraDataListOnlySupportsSingleTx","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"IncorrectOracleMigration","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidExitedValidatorsData","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataItem","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataSortOrder","type":"error"},{"inputs":[],"name":"LegacyOracleCannotBeZero","type":"error"},{"inputs":[],"name":"LidoLocatorCannotBeZero","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NumExitedValidatorsCannotDecrease","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedFormat","type":"uint256"},{"internalType":"uint256","name":"receivedFormat","type":"uint256"}],"name":"UnexpectedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedIndex","type":"uint256"},{"internalType":"uint256","name":"receivedIndex","type":"uint256"}],"name":"UnexpectedExtraDataIndex","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedCount","type":"uint256"},{"internalType":"uint256","name":"receivedCount","type":"uint256"}],"name":"UnexpectedExtraDataItemsCount","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"dataType","type":"uint256"}],"name":"UnsupportedExtraDataType","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusHashContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"ExtraDataSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processedItemsCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"WarnExtraDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_EXITED_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_STUCK_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEGACY_ORACLE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCATOR","outputs":[{"internalType":"contract ILidoLocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"mainDataHash","type":"bytes32"},{"internalType":"bool","name":"mainDataSubmitted","type":"bool"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsSubmitted","type":"uint256"}],"internalType":"struct AccountingOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initializeWithoutMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"numValidators","type":"uint256"},{"internalType":"uint256","name":"clBalanceGwei","type":"uint256"},{"internalType":"uint256[]","name":"stakingModuleIdsWithNewlyExitedValidators","type":"uint256[]"},{"internalType":"uint256[]","name":"numExitedValidatorsByStakingModule","type":"uint256[]"},{"internalType":"uint256","name":"withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"lastWithdrawalRequestIdToFinalize","type":"uint256"},{"internalType":"uint256","name":"finalizationShareRate","type":"uint256"},{"internalType":"bool","name":"isBunkerMode","type":"bool"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"}],"internalType":"struct AccountingOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"items","type":"bytes"}],"name":"submitReportExtraDataList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/lib/abi/BaseOracle.json b/lib/abi/BaseOracle.json index bdaa41bba..aea674172 100644 --- a/lib/abi/BaseOracle.json +++ b/lib/abi/BaseOracle.json @@ -1 +1 @@ -[{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusHashContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/lib/abi/ValidatorsExitBusOracle.json b/lib/abi/ValidatorsExitBusOracle.json index e69b50b97..40656d47b 100644 --- a/lib/abi/ValidatorsExitBusOracle.json +++ b/lib/abi/ValidatorsExitBusOracle.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"address","name":"lidoLocator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ArgumentOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[],"name":"UnexpectedRequestsDataLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedRequestsDataFormat","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"validatorIndex","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"validatorPubkey","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ValidatorExitRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsCount","type":"uint256"}],"name":"WarnDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256[]","name":"nodeOpIds","type":"uint256[]"}],"name":"getLastRequestedValidatorIndices","outputs":[{"internalType":"int256[]","name":"","type":"int256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bool","name":"dataSubmitted","type":"bool"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"requestsSubmitted","type":"uint256"}],"internalType":"struct ValidatorsExitBusOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRequestsProcessed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ValidatorsExitBusOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"address","name":"lidoLocator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ArgumentOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[],"name":"UnexpectedRequestsDataLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedRequestsDataFormat","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusHashContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nodeOperatorId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"validatorIndex","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"validatorPubkey","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ValidatorExitRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestsCount","type":"uint256"}],"name":"WarnDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256[]","name":"nodeOpIds","type":"uint256[]"}],"name":"getLastRequestedValidatorIndices","outputs":[{"internalType":"int256[]","name":"","type":"int256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bool","name":"dataSubmitted","type":"bool"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"requestsSubmitted","type":"uint256"}],"internalType":"struct ValidatorsExitBusOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRequestsProcessed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"requestsCount","type":"uint256"},{"internalType":"uint256","name":"dataFormat","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ValidatorsExitBusOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-deploy.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-deploy.test.js index 8d7149c50..afac6493f 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-deploy.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-deploy.test.js @@ -114,7 +114,7 @@ async function deployExitBusOracle(admin, { sender: admin }}) - assertEvent(tx, 'ConsensusContractSet', {expectedArgs: { + assertEvent(tx, 'ConsensusHashContractSet', {expectedArgs: { addr: consensus.address, prevAddr: ZERO_ADDRESS }}) From 6a556c5cfe6e7206a295d5e27654b3cbb7e37086 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 18:00:26 +0300 Subject: [PATCH 14/82] fix: vars naming --- contracts/0.8.9/oracle/AccountingOracle.sol | 8 ++++---- contracts/0.8.9/test_helpers/AccountingOracleMock.sol | 8 ++++---- lib/abi/AccountingOracle.json | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index e7f5c97a1..5ed46a45f 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -237,13 +237,13 @@ contract AccountingOracle is BaseOracle { /// @dev The id of the last withdrawal request that should be finalized as the result /// of applying this oracle report. The zero value means that no requests should be /// finalized. - uint256 lastWithdrawalRequestIdToFinalize; + uint256 lastFinalizableWithdrawalRequestId; /// @dev The share/ETH rate with the 10^27 precision (i.e. the price of one stETH share /// in ETH where one ETH is denominated as 10^27) used for finalizing withdrawal requests /// up to (and including) the one passed in the lastWithdrawalRequestIdToFinalize field. /// Must be set to zero if lastWithdrawalRequestIdToFinalize is zero. - uint256 finalizationShareRate; + uint256 simulatedShareRate; /// @dev Whether, based on the state observed at the reference slot, the protocol should /// be in the bunker mode. @@ -559,8 +559,8 @@ contract AccountingOracle is BaseOracle { data.clBalanceGwei * 1e9, data.withdrawalVaultBalance, data.elRewardsVaultBalance, - data.lastWithdrawalRequestIdToFinalize, - data.finalizationShareRate + data.lastFinalizableWithdrawalRequestId, + data.simulatedShareRate ); _storageExtraDataProcessingState().value = ExtraDataProcessingState({ diff --git a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol index e96108987..8495b3de2 100644 --- a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol +++ b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol @@ -50,8 +50,8 @@ contract AccountingOracleMock { // data.clBalanceGwei * 1e9, // data.withdrawalVaultBalance, // data.elRewardsVaultBalance, - // data.lastWithdrawalRequestIdToFinalize, - // data.finalizationShareRate, + // data.lastFinalizableWithdrawalRequestId, + // data.simulatedShareRate, // data.isBunkerMode // ); @@ -60,8 +60,8 @@ contract AccountingOracleMock { data.clBalanceGwei * 1e9, data.withdrawalVaultBalance, data.elRewardsVaultBalance, - data.lastWithdrawalRequestIdToFinalize, - data.finalizationShareRate + data.lastFinalizableWithdrawalRequestId, + data.simulatedShareRate ); } diff --git a/lib/abi/AccountingOracle.json b/lib/abi/AccountingOracle.json index cb07cf69d..13f5f9002 100644 --- a/lib/abi/AccountingOracle.json +++ b/lib/abi/AccountingOracle.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"lidoLocator","type":"address"},{"internalType":"address","name":"lido","type":"address"},{"internalType":"address","name":"legacyOracle","type":"address"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"CannotSubmitExtraDataBeforeMainData","type":"error"},{"inputs":[],"name":"ExtraDataAlreadyProcessed","type":"error"},{"inputs":[],"name":"ExtraDataListOnlySupportsSingleTx","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"IncorrectOracleMigration","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidExitedValidatorsData","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataItem","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataSortOrder","type":"error"},{"inputs":[],"name":"LegacyOracleCannotBeZero","type":"error"},{"inputs":[],"name":"LidoLocatorCannotBeZero","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NumExitedValidatorsCannotDecrease","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedFormat","type":"uint256"},{"internalType":"uint256","name":"receivedFormat","type":"uint256"}],"name":"UnexpectedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedIndex","type":"uint256"},{"internalType":"uint256","name":"receivedIndex","type":"uint256"}],"name":"UnexpectedExtraDataIndex","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedCount","type":"uint256"},{"internalType":"uint256","name":"receivedCount","type":"uint256"}],"name":"UnexpectedExtraDataItemsCount","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"dataType","type":"uint256"}],"name":"UnsupportedExtraDataType","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusHashContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"ExtraDataSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processedItemsCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"WarnExtraDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_EXITED_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_STUCK_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEGACY_ORACLE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCATOR","outputs":[{"internalType":"contract ILidoLocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"mainDataHash","type":"bytes32"},{"internalType":"bool","name":"mainDataSubmitted","type":"bool"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsSubmitted","type":"uint256"}],"internalType":"struct AccountingOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initializeWithoutMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"numValidators","type":"uint256"},{"internalType":"uint256","name":"clBalanceGwei","type":"uint256"},{"internalType":"uint256[]","name":"stakingModuleIdsWithNewlyExitedValidators","type":"uint256[]"},{"internalType":"uint256[]","name":"numExitedValidatorsByStakingModule","type":"uint256[]"},{"internalType":"uint256","name":"withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"lastWithdrawalRequestIdToFinalize","type":"uint256"},{"internalType":"uint256","name":"finalizationShareRate","type":"uint256"},{"internalType":"bool","name":"isBunkerMode","type":"bool"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"}],"internalType":"struct AccountingOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"items","type":"bytes"}],"name":"submitReportExtraDataList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"lidoLocator","type":"address"},{"internalType":"address","name":"lido","type":"address"},{"internalType":"address","name":"legacyOracle","type":"address"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"CannotSubmitExtraDataBeforeMainData","type":"error"},{"inputs":[],"name":"ExtraDataAlreadyProcessed","type":"error"},{"inputs":[],"name":"ExtraDataListOnlySupportsSingleTx","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"IncorrectOracleMigration","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidExitedValidatorsData","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataItem","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"name":"InvalidExtraDataSortOrder","type":"error"},{"inputs":[],"name":"LegacyOracleCannotBeZero","type":"error"},{"inputs":[],"name":"LidoLocatorCannotBeZero","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NumExitedValidatorsCannotDecrease","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"prevRefSlot","type":"uint256"}],"name":"RefSlotCannotDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"RefSlotMustBeGreaterThanProcessingOne","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"UnexpectedChainConfig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedVersion","type":"uint256"},{"internalType":"uint256","name":"receivedVersion","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedDataHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedFormat","type":"uint256"},{"internalType":"uint256","name":"receivedFormat","type":"uint256"}],"name":"UnexpectedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedIndex","type":"uint256"},{"internalType":"uint256","name":"receivedIndex","type":"uint256"}],"name":"UnexpectedExtraDataIndex","type":"error"},{"inputs":[{"internalType":"uint256","name":"expectedCount","type":"uint256"},{"internalType":"uint256","name":"receivedCount","type":"uint256"}],"name":"UnexpectedExtraDataItemsCount","type":"error"},{"inputs":[{"internalType":"uint256","name":"consensusRefSlot","type":"uint256"},{"internalType":"uint256","name":"dataRefSlot","type":"uint256"}],"name":"UnexpectedRefSlot","type":"error"},{"inputs":[{"internalType":"uint256","name":"format","type":"uint256"}],"name":"UnsupportedExtraDataFormat","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"dataType","type":"uint256"}],"name":"UnsupportedExtraDataType","type":"error"},{"inputs":[],"name":"VersionCannotBeSame","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"prevAddr","type":"address"}],"name":"ConsensusHashContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"prevVersion","type":"uint256"}],"name":"ConsensusVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsProcessed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"ExtraDataSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"ProcessingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"}],"name":"ReportSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processedItemsCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemsCount","type":"uint256"}],"name":"WarnExtraDataIncompleteProcessing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"}],"name":"WarnProcessingMissed","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_FORMAT_LIST","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_EXITED_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTRA_DATA_TYPE_STUCK_VALIDATORS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GENESIS_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEGACY_ORACLE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCATOR","outputs":[{"internalType":"contract ILidoLocator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_CONTRACT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_CONSENSUS_VERSION_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_PER_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMIT_DATA_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusReport","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bool","name":"processingStarted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastProcessingRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProcessingState","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingDeadlineTime","type":"uint256"},{"internalType":"bytes32","name":"mainDataHash","type":"bytes32"},{"internalType":"bool","name":"mainDataSubmitted","type":"bool"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"},{"internalType":"uint256","name":"extraDataItemsSubmitted","type":"uint256"}],"internalType":"struct AccountingOracle.ProcessingState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"consensusContract","type":"address"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"lastProcessingRefSlot","type":"uint256"}],"name":"initializeWithoutMigration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setConsensusContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"name":"setConsensusVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"reportHash","type":"bytes32"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"submitConsensusReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"consensusVersion","type":"uint256"},{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"numValidators","type":"uint256"},{"internalType":"uint256","name":"clBalanceGwei","type":"uint256"},{"internalType":"uint256[]","name":"stakingModuleIdsWithNewlyExitedValidators","type":"uint256[]"},{"internalType":"uint256[]","name":"numExitedValidatorsByStakingModule","type":"uint256[]"},{"internalType":"uint256","name":"withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"lastFinalizableWithdrawalRequestId","type":"uint256"},{"internalType":"uint256","name":"simulatedShareRate","type":"uint256"},{"internalType":"bool","name":"isBunkerMode","type":"bool"},{"internalType":"uint256","name":"extraDataFormat","type":"uint256"},{"internalType":"bytes32","name":"extraDataHash","type":"bytes32"},{"internalType":"uint256","name":"extraDataItemsCount","type":"uint256"}],"internalType":"struct AccountingOracle.ReportData","name":"data","type":"tuple"},{"internalType":"uint256","name":"contractVersion","type":"uint256"}],"name":"submitReportData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"items","type":"bytes"}],"name":"submitReportExtraDataList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file From 82d768aa660c604771f9bed92e6bb92d5a07732d Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sun, 12 Feb 2023 00:11:54 +0700 Subject: [PATCH 15/82] fix: missing await in assertRevert --- .../oracle/base-oracle-submit-report.test.js | 41 ++++--------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/test/0.8.9/oracle/base-oracle-submit-report.test.js b/test/0.8.9/oracle/base-oracle-submit-report.test.js index f12c57c44..f14530285 100644 --- a/test/0.8.9/oracle/base-oracle-submit-report.test.js +++ b/test/0.8.9/oracle/base-oracle-submit-report.test.js @@ -5,32 +5,7 @@ const { assertRevert } = require('../../helpers/assertThrow') const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') -const { - INITIAL_FAST_LANE_LENGHT_SLOTS, - INITIAL_EPOCH, - SLOTS_PER_EPOCH, - SECONDS_PER_SLOT, - GENESIS_TIME, - EPOCHS_PER_FRAME, - SECONDS_PER_EPOCH, - SECONDS_PER_FRAME, - SLOTS_PER_FRAME, - computeSlotAt, - computeEpochAt, - computeEpochFirstSlot, - computeEpochFirstSlotAt, - computeTimestampAtSlot, - computeTimestampAtEpoch, - ZERO_HASH, - HASH_1, - HASH_2, - HASH_3, - HASH_4, - HASH_5, - CONSENSUS_VERSION, - UNREACHABLE_QUORUM, - deployBaseOracle -} = require('./base-oracle-deploy.test') +const { SLOTS_PER_FRAME, ZERO_HASH, HASH_1, HASH_2, HASH_3, deployBaseOracle } = require('./base-oracle-deploy.test') contract('BaseOracle', ([admin]) => { let consensus @@ -49,7 +24,7 @@ contract('BaseOracle', ([admin]) => { before(deployContract) it('only setConsensus contract can call submitConsensusReport', async () => { - assertRevert( + await assertRevert( baseOracle.submitConsensusReport(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), 'OnlyConsensusContractCanSubmitReport()' ) @@ -74,9 +49,9 @@ contract('BaseOracle', ([admin]) => { }) it('older report cannot be submitted', async () => { - assertRevert( - baseOracle.submitConsensusReport(HASH_1, initialRefSlot - 1, initialRefSlot + SLOTS_PER_FRAME), - 'RefSlotCannotDecrease(29,31)' + await assertRevert( + consensus.submitReportAsConsensus(HASH_1, initialRefSlot - 1, initialRefSlot + SLOTS_PER_FRAME), + `RefSlotCannotDecrease(${initialRefSlot - 1}, ${initialRefSlot})` ) }) @@ -85,9 +60,9 @@ contract('BaseOracle', ([admin]) => { }) it('consensus cannot resubmit already processing report', async () => { - assertRevert( - baseOracle.submitConsensusReport(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), - 'RefSlotMustBeGreaterThanProcessingOne(31,31)' + await assertRevert( + consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), + `RefSlotMustBeGreaterThanProcessingOne(${initialRefSlot}, ${initialRefSlot})` ) }) From 04eb418c3be7aaa59e828ccc7843e121913ccd92 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 20:30:22 +0300 Subject: [PATCH 16/82] chore: naming in sanity checks --- .../0.8.9/sanity_checks/OracleReportSanityChecker.sol | 6 ++++-- .../test_helpers/OracleReportSanityCheckerMocks.sol | 4 ++-- test/0.8.9/oracle-report-sanity-checker.test.js | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 4412fbc80..4ef7219e5 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -337,11 +337,13 @@ contract OracleReportSanityChecker is AccessControlEnumerable { /// @notice Applies sanity checks to the accounting params of Lido's oracle report /// @param _timeElapsed time elapsed since the previous oracle report /// @param _preCLBalance sum of all Lido validators' balances on the Consensus Layer before the - /// current oracle report + /// current oracle report (NB: also include the initial balance of newly appeared validators) /// @param _postCLBalance sum of all Lido validators' balances on the Consensus Layer after the /// current oracle report /// @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer for report block - function checkLidoOracleReport( + /// @param _preCLValidators Lido-participating validators on the CL side before the current oracle report + /// @param _postCLValidators Lido-participating validators on the CL side after the current oracle report + function checkAccountingOracleReport( uint256 _timeElapsed, uint256 _preCLBalance, uint256 _postCLBalance, diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index f1089c569..4f7348a0f 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -76,7 +76,7 @@ contract LidoLocatorStub is ILidoLocator { } contract OracleReportSanityCheckerStub { - function checkLidoOracleReport( + function checkAccountingOracleReport( uint256 _timeElapsed, uint256 _preCLBalance, uint256 _postCLBalance, @@ -102,4 +102,4 @@ contract OracleReportSanityCheckerStub { elRewards = _elRewardsVaultBalance; sharesToBurnLimit = _etherToLockForWithdrawals; } -} \ No newline at end of file +} diff --git a/test/0.8.9/oracle-report-sanity-checker.test.js b/test/0.8.9/oracle-report-sanity-checker.test.js index 873410cfb..d74a38095 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -109,7 +109,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc }) }) - describe('checkLidoOracleReport()', () => { + describe('checkAccountingOracleReport()', () => { beforeEach(async () => { await oracleReportSanityChecker.setOracleReportLimits(Object.values(defaultLimitsList), { from: managersRoster.allLimitsManagers[0] @@ -119,7 +119,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc it('reverts with error IncorrectWithdrawalsVaultBalance() when actual withdrawal vault balance is less than passed', async () => { const currentWithdrawalVaultBalance = await hre.ethers.provider.getBalance(withdrawalVault) await assert.revertsWithCustomError( - oracleReportSanityChecker.checkLidoOracleReport( + oracleReportSanityChecker.checkAccountingOracleReport( ...Object.values({ ...correctLidoOracleReport, withdrawalVaultBalance: currentWithdrawalVaultBalance.add(1) }) ), `IncorrectWithdrawalsVaultBalance(${currentWithdrawalVaultBalance.toString()})` @@ -134,7 +134,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc const unifiedPostCLBalance = postCLBalance + withdrawalVaultBalance const oneOffCLBalanceDecreaseBP = (maxBasisPoints * (preCLBalance - unifiedPostCLBalance)) / preCLBalance await assert.revertsWithCustomError( - oracleReportSanityChecker.checkLidoOracleReport( + oracleReportSanityChecker.checkAccountingOracleReport( ...Object.values({ ...correctLidoOracleReport, preCLBalance: preCLBalance.toString(), @@ -155,7 +155,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc const annualBalanceIncrease = (secondsInOneYear * maxBasisPoints * (postCLBalance - preCLBalance)) / preCLBalance / timeElapsed await assert.revertsWithCustomError( - oracleReportSanityChecker.checkLidoOracleReport( + oracleReportSanityChecker.checkAccountingOracleReport( ...Object.values({ ...correctLidoOracleReport, postCLBalance: postCLBalance.toString() @@ -166,7 +166,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc }) it('passes all checks with correct oracle report data', async () => { - await oracleReportSanityChecker.checkLidoOracleReport(...Object.values(correctLidoOracleReport)) + await oracleReportSanityChecker.checkAccountingOracleReport(...Object.values(correctLidoOracleReport)) }) }) From 8f8467582694956f0d30d05403e2187605f2cdca Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 20:39:22 +0300 Subject: [PATCH 17/82] chore: args naming in Lido ifaces --- contracts/0.4.24/Lido.sol | 29 +++++++++++++++----------- lib/abi/IPostTokenRebaseReceiver.json | 2 +- lib/abi/OracleReportSanityChecker.json | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 88e3f4af0..8ad7329ad 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -19,18 +19,18 @@ import "./utils/Versioned.sol"; interface IPostTokenRebaseReceiver { function handlePostTokenRebase( - uint256 reportTimestamp, - uint256 timeElapsed, - uint256 preTotalShares, - uint256 preTotalEther, - uint256 postTotalShares, - uint256 postTotalEther, - uint256 sharesMintedAsFees + uint256 _reportTimestamp, + uint256 _timeElapsed, + uint256 _preTotalShares, + uint256 _preTotalEther, + uint256 _postTotalShares, + uint256 _postTotalEther, + uint256 _sharesMintedAsFees ) external; } interface IOracleReportSanityChecker { - function checkLidoOracleReport( + function checkAccountingOracleReport( uint256 _timeElapsed, uint256 _preCLBalance, uint256 _postCLBalance, @@ -70,10 +70,11 @@ interface IWithdrawalVault { interface IStakingRouter { function deposit( - uint256 maxDepositsCount, - uint256 stakingModuleId, - bytes depositCalldata + uint256 _maxDepositsCount, + uint256 _stakingModuleId, + bytes _depositCalldata ) external payable returns (uint256); + function getStakingRewardsDistribution() external view @@ -84,9 +85,13 @@ interface IStakingRouter { uint96 totalFee, uint256 precisionPoints ); + function getWithdrawalCredentials() external view returns (bytes32); + function reportRewardsMinted(uint256[] _stakingModuleIds, uint256[] _totalShares) external; + function getTotalFeeE4Precision() external view returns (uint16 totalFee); + function getStakingFeeAggregateDistributionE4Precision() external view returns (uint16 modulesFee, uint16 treasuryFee); } @@ -1158,7 +1163,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 2. // Pass the report data to sanity checker (reverts if malformed) - IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkLidoOracleReport( + IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkAccountingOracleReport( _reportedData.timeElapsed, reportContext.preCLBalance, _reportedData.postCLBalance, diff --git a/lib/abi/IPostTokenRebaseReceiver.json b/lib/abi/IPostTokenRebaseReceiver.json index 98fac090f..54053fa7c 100644 --- a/lib/abi/IPostTokenRebaseReceiver.json +++ b/lib/abi/IPostTokenRebaseReceiver.json @@ -1 +1 @@ -[{"constant":false,"inputs":[{"name":"reportTimestamp","type":"uint256"},{"name":"timeElapsed","type":"uint256"},{"name":"preTotalShares","type":"uint256"},{"name":"preTotalEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"postTotalEther","type":"uint256"},{"name":"sharesMintedAsFees","type":"uint256"}],"name":"handlePostTokenRebase","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_reportTimestamp","type":"uint256"},{"name":"_timeElapsed","type":"uint256"},{"name":"_preTotalShares","type":"uint256"},{"name":"_preTotalEther","type":"uint256"},{"name":"_postTotalShares","type":"uint256"},{"name":"_postTotalEther","type":"uint256"},{"name":"_sharesMintedAsFees","type":"uint256"}],"name":"handlePostTokenRebase","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index b13709a29..0a1b914a1 100644 --- a/lib/abi/OracleReportSanityChecker.json +++ b/lib/abi/OracleReportSanityChecker.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkLidoOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkAccountingOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file From 36180507686ae684e8d31d222272f32577808969 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sun, 12 Feb 2023 01:04:17 +0700 Subject: [PATCH 18/82] feat: set consensus contract,version tests and helper contract updates --- .../oracle/BaseOracleTimeTravellable.sol | 1 + .../oracle/MockConsensusContract.sol | 63 ++++---- .../oracle/base-oracle-set-consensus.test.js | 135 ++++++++++++++++++ 3 files changed, 161 insertions(+), 38 deletions(-) create mode 100644 test/0.8.9/oracle/base-oracle-set-consensus.test.js diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index 932f8a3fa..7391aba11 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -41,6 +41,7 @@ contract BaseOracleTimeTravellable is BaseOracle { uint256 consensusVersion, uint256 lastProcessingRefSlot ) external { + _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _initialize(consensusContract, consensusVersion, lastProcessingRefSlot); } diff --git a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol index f638e4e98..f7fab7c62 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol @@ -2,9 +2,9 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.9; -import { SafeCast } from "@openzeppelin/contracts-v4.4/utils/math/SafeCast.sol"; +import {SafeCast} from "@openzeppelin/contracts-v4.4/utils/math/SafeCast.sol"; -import { IConsensusContract } from "../../oracle/BaseOracle.sol"; +import {IConsensusContract} from "../../oracle/BaseOracle.sol"; import {IReportAsyncProcessor} from "../../oracle/HashConsensus.sol"; contract MockConsensusContract is IConsensusContract { @@ -31,7 +31,7 @@ contract MockConsensusContract is IConsensusContract { FrameConfig internal _frameConfig; ConsensusFrame internal _consensusFrame; - constructor( + constructor( uint256 slotsPerEpoch, uint256 secondsPerSlot, uint256 genesisTime, @@ -46,27 +46,31 @@ contract MockConsensusContract is IConsensusContract { _setFrameConfig(initialEpoch, epochsPerFrame, fastLaneLengthSlots); _memberIndices1b[mockMember] = 1; - - } - + _consensusFrame.index = 10; + _consensusFrame.refSlot = 1; + _consensusFrame.reportProcessingDeadlineSlot = 7001; + } function getIsMember(address addr) external view returns (bool) { return _memberIndices1b[addr] != 0; } - function getCurrentFrame() external view returns ( - uint256 refSlot, - uint256 reportProcessingDeadlineSlot - ) { + function getCurrentFrame() external view returns (uint256 refSlot, uint256 reportProcessingDeadlineSlot) { return (_consensusFrame.refSlot, _consensusFrame.reportProcessingDeadlineSlot); } - function getChainConfig() external view returns ( - uint256 slotsPerEpoch, - uint256 secondsPerSlot, - uint256 genesisTime - ) { + function setCurrentFrame(uint256 index, uint256 refSlot, uint256 reportProcessingDeadlineSlot) external { + _consensusFrame.index = index; + _consensusFrame.refSlot = refSlot; + _consensusFrame.reportProcessingDeadlineSlot = reportProcessingDeadlineSlot; + } + + function getChainConfig() + external + view + returns (uint256 slotsPerEpoch, uint256 secondsPerSlot, uint256 genesisTime) + { return (SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME); } @@ -74,36 +78,19 @@ contract MockConsensusContract is IConsensusContract { return (_frameConfig.initialEpoch, _frameConfig.epochsPerFrame); } - function _setFrameConfig( - uint256 initialEpoch, - uint256 epochsPerFrame, - uint256 fastLaneLengthSlots - ) internal { - _frameConfig = FrameConfig( - initialEpoch.toUint64(), - epochsPerFrame.toUint64(), - fastLaneLengthSlots.toUint64() - ); + function _setFrameConfig(uint256 initialEpoch, uint256 epochsPerFrame, uint256 fastLaneLengthSlots) internal { + _frameConfig = FrameConfig(initialEpoch.toUint64(), epochsPerFrame.toUint64(), fastLaneLengthSlots.toUint64()); } - // + // // IReportAsyncProcessor relevant mocks&handels // function setAsyncProcessor(address reportProcessor) external { _reportProcessor = reportProcessor; - } + } function submitReportAsConsensus(bytes32 reportHash, uint256 refSlot, uint256 deadline) external { - IReportAsyncProcessor(_reportProcessor).submitConsensusReport( - reportHash, - refSlot, - deadline - ); - } - - - - - + IReportAsyncProcessor(_reportProcessor).submitConsensusReport(reportHash, refSlot, deadline); + } } diff --git a/test/0.8.9/oracle/base-oracle-set-consensus.test.js b/test/0.8.9/oracle/base-oracle-set-consensus.test.js new file mode 100644 index 000000000..5ab39c6ea --- /dev/null +++ b/test/0.8.9/oracle/base-oracle-set-consensus.test.js @@ -0,0 +1,135 @@ +const { assert } = require('../../helpers/assert') +const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') +const MockConsensusContract = artifacts.require('MockConsensusContract') + +const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') + +const { + INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_EPOCH, + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + SECONDS_PER_EPOCH, + SECONDS_PER_FRAME, + SLOTS_PER_FRAME, + computeSlotAt, + computeEpochAt, + computeEpochFirstSlot, + computeEpochFirstSlotAt, + computeTimestampAtSlot, + computeTimestampAtEpoch, + ZERO_HASH, + HASH_1, + HASH_2, + HASH_3, + HASH_4, + HASH_5, + CONSENSUS_VERSION, + UNREACHABLE_QUORUM, + deployBaseOracle +} = require('./base-oracle-deploy.test') + +contract('BaseOracle', ([admin, member]) => { + let consensus + let baseOracle + let initialRefSlot + + const deployContract = async () => { + const deployed = await deployBaseOracle(admin, { initialEpoch: 1 }) + consensus = deployed.consensusContract + baseOracle = deployed.oracle + await baseOracle.grantRole(web3.utils.keccak256('MANAGE_CONSENSUS_CONTRACT_ROLE'), admin, { from: admin }) + await baseOracle.grantRole(web3.utils.keccak256('MANAGE_CONSENSUS_VERSION_ROLE'), admin, { from: admin }) + initialRefSlot = +(await baseOracle.getTime()) + } + + describe('setConsensusContract safely changes used consensus contract', () => { + before(deployContract) + + it('reverts on zero address', async () => { + await assert.revertsWithCustomError(baseOracle.setConsensusContract(ZERO_ADDRESS), 'AddressCannotBeZero()') + }) + + it('reverts on same contract', async () => { + await assert.revertsWithCustomError(baseOracle.setConsensusContract(consensus.address), 'AddressCannotBeSame()') + }) + + it('reverts on invalid contract', async () => { + await assert.reverts(baseOracle.setConsensusContract(member)) + }) + + it('reverts on mismatched config', async () => { + const MockConsensusContract = artifacts.require('MockConsensusContract') + const wrongConsensusContract = await MockConsensusContract.new( + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT + 1, + GENESIS_TIME + 1, + EPOCHS_PER_FRAME, + 0, + 0, + admin, + { from: admin } + ) + await assert.revertsWithCustomError( + baseOracle.setConsensusContract(wrongConsensusContract.address), + 'UnexpectedChainConfig()' + ) + }) + + it('reverts on consensus current frame behind current processing', async () => { + const wrongConsensusContract = await MockConsensusContract.new( + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + 0, + 0, + admin, + { from: admin } + ) + await wrongConsensusContract.setCurrentFrame(10, 1, 2000) + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) + await baseOracle.startProcessing() + + await assert.revertsWithCustomError( + baseOracle.setConsensusContract(wrongConsensusContract.address), + `RefSlotCannotBeLessThanProcessingOne(1, ${initialRefSlot})` + ) + }) + + it('successfully sets new consensus contract', async () => { + const newConsensusContract = await MockConsensusContract.new( + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + 0, + 0, + admin, + { from: admin } + ) + await newConsensusContract.setCurrentFrame(10, initialRefSlot + 1, initialRefSlot + SLOTS_PER_FRAME) + const tx = await baseOracle.setConsensusContract(newConsensusContract.address) + assert.emits(tx, 'ConsensusContractSet', { addr: newConsensusContract.address, prevAddr: consensus.address }) + const addressAtStorage = await baseOracle.getConsensusContract() + assert.addressEqual(addressAtStorage, newConsensusContract.address) + }) + }) + + describe('setConsensusVersion updates contract state', () => { + before(deployContract) + + it('reverts on same version', async () => { + await assert.revertsWithCustomError(baseOracle.setConsensusVersion(1), 'VersionCannotBeSame()') + }) + + it('sets updated version', async () => { + const tx = await baseOracle.setConsensusVersion(2) + assert.emits(tx, 'ConsensusVersionSet', { version: 2, prevVersion: 1 }) + const versionInState = await baseOracle.getConsensusVersion() + assert.equal(versionInState, 2) + }) + }) +}) From d348148e1a747fa9aee43a6113f363c4223a8ad4 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 12 Feb 2023 01:09:46 +0700 Subject: [PATCH 19/82] test: base oracle: add access control tests, add admin to deploy --- .../oracle/BaseOracleTimeTravellable.sol | 6 +- .../oracle/MockConsensusContract.sol | 9 +- .../oracle/base-oracle-access-control.test.js | 119 ++++++++++++++++++ test/0.8.9/oracle/base-oracle-deploy.test.js | 2 +- 4 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 test/0.8.9/oracle/base-oracle-access-control.test.js diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index 932f8a3fa..a81c4d065 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -27,11 +27,13 @@ contract BaseOracleTimeTravellable is BaseOracle { constructor( uint256 secondsPerSlot, - uint256 genesisTime + uint256 genesisTime, + address admin ) BaseOracle( secondsPerSlot, genesisTime ) { + _setupRole(DEFAULT_ADMIN_ROLE, admin); CONTRACT_VERSION_POSITION.setStorageUint256(0); require(genesisTime <= _time, "GENESIS_TIME_CANNOT_BE_MORE_THAN_MOCK_TIME"); } @@ -74,6 +76,4 @@ contract BaseOracleTimeTravellable is BaseOracle { function startProcessing() external { _startProcessing(); } - - } diff --git a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol index f638e4e98..002c36e7b 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.9; import { SafeCast } from "@openzeppelin/contracts-v4.4/utils/math/SafeCast.sol"; import { IConsensusContract } from "../../oracle/BaseOracle.sol"; -import {IReportAsyncProcessor} from "../../oracle/HashConsensus.sol"; +import { IReportAsyncProcessor } from "../../oracle/HashConsensus.sol"; contract MockConsensusContract is IConsensusContract { using SafeCast for uint256; @@ -100,10 +100,5 @@ contract MockConsensusContract is IConsensusContract { refSlot, deadline ); - } - - - - - + } } diff --git a/test/0.8.9/oracle/base-oracle-access-control.test.js b/test/0.8.9/oracle/base-oracle-access-control.test.js new file mode 100644 index 000000000..26bb677b1 --- /dev/null +++ b/test/0.8.9/oracle/base-oracle-access-control.test.js @@ -0,0 +1,119 @@ +const { MaxUint256 } = require('@ethersproject/constants') +const { assert } = require('../../helpers/assert') + +const { + deployBaseOracle, + EPOCHS_PER_FRAME, + SECONDS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_EPOCH, + CONSENSUS_VERSION, + HASH_1, + SLOTS_PER_FRAME +} = require('./base-oracle-deploy.test') + +const MockConsensusContract = artifacts.require('MockConsensusContract') + +contract('BaseOracle', ([admin, account1, account2, member1, member2]) => { + let oracle = null + let consensus = null + const manageConsensusContractRoleKeccak156 = web3.utils.keccak256('MANAGE_CONSENSUS_CONTRACT_ROLE') + const manageConsensusVersionRoleKeccak156 = web3.utils.keccak256('MANAGE_CONSENSUS_VERSION_ROLE') + + const deploy = async (options = undefined) => { + const deployed = await deployBaseOracle(admin, options) + oracle = deployed.oracle + consensus = deployed.consensusContract + } + + context('deploying', () => { + before(deploy) + + it('deploying hash oracle', async () => { + assert.isNotNull(oracle) + assert.isNotNull(consensus) + }) + }) + + context('MANAGE_CONSENSUS_CONTRACT_ROLE', () => { + beforeEach(deploy) + + context('setConsensusContract', () => { + it('should revert without MANAGE_CONSENSUS_CONTRACT_ROLE role', async () => { + await assert.revertsOZAccessControl( + oracle.setConsensusContract(member1, { from: account1 }), + account1, + 'MANAGE_CONSENSUS_CONTRACT_ROLE' + ) + + assert.equal(await oracle.getConsensusContract(), consensus.address) + }) + + it('should allow calling from a possessor of MANAGE_CONSENSUS_CONTRACT_ROLE role', async () => { + const consensusContract2 = await MockConsensusContract.new( + SECONDS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_EPOCH, + admin, + { from: admin } + ) + + await oracle.grantRole(manageConsensusContractRoleKeccak156, account2, { from: admin }) + await oracle.setConsensusContract(consensusContract2.address, { from: account2 }) + + assert.equal(await oracle.getConsensusContract(), consensusContract2.address) + }) + }) + }) + + context('MANAGE_CONSENSUS_VERSION_ROLE', () => { + beforeEach(deploy) + + context('setConsensusVersion', () => { + it('should revert without MANAGE_CONSENSUS_VERSION_ROLE role', async () => { + await assert.revertsOZAccessControl( + oracle.setConsensusVersion(1, { from: account1 }), + account1, + 'MANAGE_CONSENSUS_VERSION_ROLE' + ) + + assert.equal(await oracle.getConsensusVersion(), CONSENSUS_VERSION) + }) + + it('should allow calling from a possessor of MANAGE_CONSENSUS_VERSION_ROLE role', async () => { + await oracle.grantRole(manageConsensusVersionRoleKeccak156, account2, { from: admin }) + await oracle.setConsensusVersion(2, { from: account2 }) + + assert.equal(await oracle.getConsensusVersion(), 2) + }) + }) + }) + + context('CONSENSUS_CONTRACT', () => { + beforeEach(deploy) + + context('submitConsensusReport', async () => { + const initialRefSlot = +(await oracle.getTime()) + + it('should revert from not a consensus contract', async () => { + await assert.revertsWithCustomError( + oracle.submitConsensusReport(HASH_1, initialRefSlot, initialRefSlot, { from: account1 }), + 'OnlyConsensusContractCanSubmitReport()' + ) + + assert.equal(+(await oracle.getConsensusReportLastCall()).callCount, 0) + }) + + it('should allow calling from a consensus contract', async () => { + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) + + assert.equal(+(await oracle.getConsensusReportLastCall()).callCount, 1) + }) + }) + }) +}) diff --git a/test/0.8.9/oracle/base-oracle-deploy.test.js b/test/0.8.9/oracle/base-oracle-deploy.test.js index 32367a78c..a9cdda854 100644 --- a/test/0.8.9/oracle/base-oracle-deploy.test.js +++ b/test/0.8.9/oracle/base-oracle-deploy.test.js @@ -60,7 +60,7 @@ async function deployBaseOracle( ) } - const oracle = await BaseOracle.new(secondsPerSlot, genesisTime, { from: admin }) + const oracle = await BaseOracle.new(secondsPerSlot, genesisTime, admin, { from: admin }) await oracle.initialize(consensusContract.address, CONSENSUS_VERSION, 0) From 1f75ec0df1a29de5b64dd4c1ee89cf6e05af055b Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 21:14:31 +0300 Subject: [PATCH 20/82] fix: -extra pause check `transferSharesFrom` --- contracts/0.4.24/StETH.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index f52a4a054..3e23f8e33 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -363,8 +363,6 @@ contract StETH is IERC20, Pausable { function transferSharesFrom( address _sender, address _recipient, uint256 _sharesAmount ) external returns (uint256) { - _whenNotStopped(); - uint256 currentAllowance = allowances[_sender][msg.sender]; uint256 tokensAmount = getPooledEthByShares(_sharesAmount); require(currentAllowance >= tokensAmount, "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); From f2665ca0b3dfc5840672d6065682a1e77497b011 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 21:16:11 +0300 Subject: [PATCH 21/82] fix: DSM calls canDeposit from Lido --- contracts/0.8.9/DepositSecurityModule.sol | 9 +++++++- .../LidoMockForDepositSecurityModule.sol | 14 +++++++++++ test/0.8.9/deposit-security-module.test.js | 23 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/contracts/0.8.9/DepositSecurityModule.sol b/contracts/0.8.9/DepositSecurityModule.sol index eda576ccf..3a5547cf4 100644 --- a/contracts/0.8.9/DepositSecurityModule.sol +++ b/contracts/0.8.9/DepositSecurityModule.sol @@ -12,6 +12,7 @@ interface ILido { uint256 _stakingModuleId, bytes calldata _depositCalldata ) external; + function canDeposit() external view returns (bool); } interface IDepositContract { @@ -378,7 +379,13 @@ contract DepositSecurityModule { function canDeposit(uint256 stakingModuleId) external view validStakingModuleId(stakingModuleId) returns (bool) { bool isModuleActive = STAKING_ROUTER.getStakingModuleIsActive(stakingModuleId); uint256 lastDepositBlock = STAKING_ROUTER.getStakingModuleLastDepositBlock(stakingModuleId); - return isModuleActive && quorum > 0 && block.number - lastDepositBlock >= minDepositBlockDistance; + bool isLidoCanDeposit = LIDO.canDeposit(); + return ( + isModuleActive + && quorum > 0 + && block.number - lastDepositBlock >= minDepositBlockDistance + && isLidoCanDeposit + ); } /** diff --git a/contracts/0.8.9/test_helpers/LidoMockForDepositSecurityModule.sol b/contracts/0.8.9/test_helpers/LidoMockForDepositSecurityModule.sol index 16cd03aa2..9ea4a4a04 100644 --- a/contracts/0.8.9/test_helpers/LidoMockForDepositSecurityModule.sol +++ b/contracts/0.8.9/test_helpers/LidoMockForDepositSecurityModule.sol @@ -5,9 +5,19 @@ pragma solidity 0.8.9; contract LidoMockForDepositSecurityModule { + bool internal canDepositState; + event StakingModuleDeposited(uint256 maxDepositsCount, uint24 stakingModuleId, bytes depositCalldata); event Deposited(uint256 maxDeposits); + constructor() { + canDepositState = true; + } + + function setCanDeposit(bool _canDeposit) external { + canDepositState = _canDeposit; + } + function deposit( uint256 maxDepositsCount, uint256 stakingModuleId, @@ -16,4 +26,8 @@ contract LidoMockForDepositSecurityModule { emit StakingModuleDeposited(maxDepositsCount, uint24(stakingModuleId), depositCalldata); return maxDepositsCount; } + + function canDeposit() external view returns(bool) { + return canDepositState; + } } diff --git a/test/0.8.9/deposit-security-module.test.js b/test/0.8.9/deposit-security-module.test.js index 76a4ba38d..900dd5ec4 100644 --- a/test/0.8.9/deposit-security-module.test.js +++ b/test/0.8.9/deposit-security-module.test.js @@ -1029,5 +1029,28 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { assert.isTrue(currentBlockNumber - lastDepositBlockNumber < minDepositBlockDistance) assert.isFalse(await depositSecurityModule.canDeposit(STAKING_MODULE)) }) + it('false if Lido cant deposit', async () => { + await depositSecurityModule.addGuardian(GUARDIAN1, 1, { from: owner }) + + assert.equal(await stakingRouterMock.getStakingModuleIsDepositsPaused(STAKING_MODULE), false, 'invariant failed: isPaused') + assert.isTrue((await depositSecurityModule.getGuardianQuorum()) > 0, 'invariant failed: quorum > 0') + + const lastDepositBlockNumber = await web3.eth.getBlockNumber() + stakingRouterMock.setStakingModuleLastDepositBlock(lastDepositBlockNumber) + await waitBlocks(2 * MIN_DEPOSIT_BLOCK_DISTANCE) + + const currentBlockNumber = await web3.eth.getBlockNumber() + const minDepositBlockDistance = await depositSecurityModule.getMinDepositBlockDistance() + + assert.isTrue(currentBlockNumber - lastDepositBlockNumber >= minDepositBlockDistance) + assert.isTrue(await depositSecurityModule.canDeposit(STAKING_MODULE)) + assert.isTrue(await lidoMock.canDeposit()) + + await lidoMock.setCanDeposit(false); + + assert.isFalse(await lidoMock.canDeposit()) + assert.isTrue(currentBlockNumber - lastDepositBlockNumber >= minDepositBlockDistance) + assert.isFalse(await depositSecurityModule.canDeposit(STAKING_MODULE)) + }) }) }) From 81ea055c795514b9c9124ac137a9f3d5438ee6a7 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 12 Feb 2023 01:16:13 +0700 Subject: [PATCH 22/82] test: base oracle: change mock init --- .../0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index d266b627a..a81c4d065 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -43,7 +43,6 @@ contract BaseOracleTimeTravellable is BaseOracle { uint256 consensusVersion, uint256 lastProcessingRefSlot ) external { - _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _initialize(consensusContract, consensusVersion, lastProcessingRefSlot); } From e9b74c7a5c66c4220e3d88c559d3f62cc9021030 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 21:16:52 +0300 Subject: [PATCH 23/82] chore: Lido comments and naming --- contracts/0.4.24/Lido.sol | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 8ad7329ad..669a08209 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -96,13 +96,17 @@ interface IStakingRouter { } interface IWithdrawalQueue { - function finalizationBatch(uint256 _lastRequestIdToFinalize, uint256 _shareRate) + function finalizationBatch(uint256 _nextFinalizedRequestId, uint256 _shareRate) external view returns (uint128 eth, uint128 shares); + function finalize(uint256 _lastIdToFinalize) external payable; + function isPaused() external view returns (bool); + function unfinalizedStETH() external view returns (uint256); + function isBunkerModeActive() external view returns (bool); } @@ -647,10 +651,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { _stakingModuleId, _depositCalldata ); - assert(depositsCount <= depositableEth / DEPOSIT_SIZE ); + + uint256 depositedAmount = depositsCount.mul(DEPOSIT_SIZE); + assert(depositedAmount <= depositableEth); if (depositsCount > 0) { - uint256 depositedAmount = depositsCount.mul(DEPOSIT_SIZE); DEPOSITED_VALIDATORS_POSITION.setStorageUint256(DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(depositsCount)); _markAsUnbuffered(depositedAmount); @@ -726,10 +731,10 @@ contract Lido is Versioned, StETHPermit, AragonApp { * * NB: conventions and assumptions * - * `depositedValidators` are total amount of the **ever** deposited validators - * `_postClValidators` are total amount of the **ever** deposited validators + * `depositedValidators` are total amount of the **ever** deposited Lido validators + * `_postClValidators` are total amount of the **ever** appeared on the CL side Lido validators * - * i.e., exited validators persist in the state, just with a different status + * i.e., exited Lido validators persist in the state, just with a different status */ function _processClStateUpdate( uint256 _preClValidators, @@ -738,15 +743,13 @@ contract Lido is Versioned, StETHPermit, AragonApp { ) internal returns (uint256 preCLBalance) { uint256 depositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256(); require(_postClValidators <= depositedValidators, "REPORTED_MORE_DEPOSITED"); - require(_postClValidators >= _preClValidators, "REPORTED_LESS_VALIDATORS"); - if (_postClValidators > _preClValidators) { CL_VALIDATORS_POSITION.setStorageUint256(_postClValidators); } - uint256 appearedValidators = _postClValidators.sub(_preClValidators); + uint256 appearedValidators = _postClValidators - _preClValidators; preCLBalance = CL_BALANCE_POSITION.getStorageUint256(); // Take into account the balance of the newly appeared validators preCLBalance = preCLBalance.add(appearedValidators.mul(DEPOSIT_SIZE)); From ad25d5d939d6e4dd61277e6995ef1fe71819c8b1 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 21:19:59 +0300 Subject: [PATCH 24/82] chore: handleOracleReport namings --- contracts/0.8.9/oracle/AccountingOracle.sol | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index 5ed46a45f..5b0a5540d 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -12,17 +12,18 @@ import { BaseOracle, IConsensusContract } from "./BaseOracle.sol"; interface ILido { function handleOracleReport( - uint256 currentReportTimestamp, - uint256 secondsElapsedSinceLastReport, + // Oracle timings + uint256 _currentReportTimestamp, + uint256 _timeElapsedSeconds, // CL values - uint256 beaconValidators, - uint256 beaconBalance, + uint256 _clValidators, + uint256 _clBalance, // EL values - uint256 withdrawalVaultBalance, - uint256 elRewardsVaultBalance, - // decision - uint256 requestIdToFinalizeUpTo, - uint256 finalizationShareRate + uint256 _withdrawalVaultBalance, + uint256 _elRewardsVaultBalance, + // Decision about withdrawals processing + uint256 _lastFinalizableRequestId, + uint256 _simulatedShareRate ) external; } From fe83a0303ac41410c547edd6470719a7afcf520b Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 11 Feb 2023 21:29:07 +0300 Subject: [PATCH 25/82] fix: check finalization share rate special vals --- contracts/0.8.9/lib/PositiveTokenRebaseLimiter.sol | 4 ++-- contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/0.8.9/lib/PositiveTokenRebaseLimiter.sol b/contracts/0.8.9/lib/PositiveTokenRebaseLimiter.sol index 200b59bf1..caf199d87 100644 --- a/contracts/0.8.9/lib/PositiveTokenRebaseLimiter.sol +++ b/contracts/0.8.9/lib/PositiveTokenRebaseLimiter.sol @@ -9,7 +9,7 @@ import {Math256} from "../../common/lib/Math256.sol"; /** * This library implements positive rebase limiter for `stETH` token. * One needs to initialize `LimiterState` with the desired parameters: - * - _rebaseLimit (limiter max value, nominated in LIMITER_PRECISION_POINTS) + * - _rebaseLimit (limiter max value, nominated in LIMITER_PRECISION_BASE) * - _totalPooledEther (see `Lido.getTotalPooledEther()`) * - _totalShares (see `Lido.getTotalShares()`) * @@ -38,7 +38,7 @@ library PositiveTokenRebaseLimiter { /** * @dev Initialize the new `LimiterState` structure instance - * @param _rebaseLimit max limiter value (saturation point), see `LIMITER_PRECISION_POINTS` + * @param _rebaseLimit max limiter value (saturation point), see `LIMITER_PRECISION_BASE` * @param _totalPooledEther total pooled ether, see `Lido.getTotalPooledEther()` * @param _totalShares total shares, see `Lido.getTotalShares()` * @return limiterState newly initialized limiter structure diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 4ef7219e5..5ed8d77bf 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -519,7 +519,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { ) internal view { uint256 actualShareRate = ILido(_lido).getSharesByPooledEth(1 ether); - if (actualShareRate == 0 && _simulatedShareRate == 0) { return; } + if (actualShareRate == 0 || _simulatedShareRate == 0) { return; } uint256 finalizationShareDiff = Math256.abs( SafeCast.toInt256(_simulatedShareRate) - SafeCast.toInt256(actualShareRate) From c8bbc7c13cfa788fbd63cf9e9fb4eebef090f4ec Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sun, 12 Feb 2023 14:47:27 +0700 Subject: [PATCH 26/82] feat: checkConsensusData tests & relevant mock updates --- .../oracle/BaseOracleTimeTravellable.sol | 37 +++++++-------- .../oracle/base-oracle-set-consensus.test.js | 47 ++++++++++++++++++- 2 files changed, 61 insertions(+), 23 deletions(-) diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index a81c4d065..e092bbcc2 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -2,9 +2,8 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.9; -import { UnstructuredStorage } from "../../lib/UnstructuredStorage.sol"; -import { BaseOracle } from "../../oracle/BaseOracle.sol"; - +import {UnstructuredStorage} from "../../lib/UnstructuredStorage.sol"; +import {BaseOracle} from "../../oracle/BaseOracle.sol"; struct ConsensusReport { bytes32 hash; @@ -12,12 +11,11 @@ struct ConsensusReport { uint64 processingDeadlineTime; } - contract BaseOracleTimeTravellable is BaseOracle { using UnstructuredStorage for bytes32; uint256 internal _time = 2513040315; - struct HandleConsensusReportLastCall { + struct HandleConsensusReportLastCall { ConsensusReport report; uint256 prevSubmittedRefSlot; uint256 prevProcessingRefSlot; @@ -25,28 +23,17 @@ contract BaseOracleTimeTravellable is BaseOracle { } HandleConsensusReportLastCall internal _handleConsensusReportLastCall; - constructor( - uint256 secondsPerSlot, - uint256 genesisTime, - address admin - ) BaseOracle( - secondsPerSlot, - genesisTime - ) { + constructor(uint256 secondsPerSlot, uint256 genesisTime, address admin) BaseOracle(secondsPerSlot, genesisTime) { _setupRole(DEFAULT_ADMIN_ROLE, admin); CONTRACT_VERSION_POSITION.setStorageUint256(0); require(genesisTime <= _time, "GENESIS_TIME_CANNOT_BE_MORE_THAN_MOCK_TIME"); } - function initialize( - address consensusContract, - uint256 consensusVersion, - uint256 lastProcessingRefSlot - ) external { + function initialize(address consensusContract, uint256 consensusVersion, uint256 lastProcessingRefSlot) external { _initialize(consensusContract, consensusVersion, lastProcessingRefSlot); } - function _getTime() internal override view returns (uint256) { + function _getTime() internal view override returns (uint256) { return _time; } @@ -62,7 +49,11 @@ contract BaseOracleTimeTravellable is BaseOracle { _time += timeAdvance; } - function _handleConsensusReport(ConsensusReport memory report, uint256 prevSubmittedRefSlot, uint256 prevProcessingRefSlot) internal override virtual { + function _handleConsensusReport( + ConsensusReport memory report, + uint256 prevSubmittedRefSlot, + uint256 prevProcessingRefSlot + ) internal virtual override { _handleConsensusReportLastCall.report = report; _handleConsensusReportLastCall.prevSubmittedRefSlot = prevSubmittedRefSlot; _handleConsensusReportLastCall.prevProcessingRefSlot = prevProcessingRefSlot; @@ -74,6 +65,10 @@ contract BaseOracleTimeTravellable is BaseOracle { } function startProcessing() external { - _startProcessing(); + _startProcessing(); + } + + function checkConsensusData(uint256 refSlot, uint256 consensusVersion, bytes32 hash) external view { + _checkConsensusData(refSlot, consensusVersion, hash); } } diff --git a/test/0.8.9/oracle/base-oracle-set-consensus.test.js b/test/0.8.9/oracle/base-oracle-set-consensus.test.js index 5ab39c6ea..222979936 100644 --- a/test/0.8.9/oracle/base-oracle-set-consensus.test.js +++ b/test/0.8.9/oracle/base-oracle-set-consensus.test.js @@ -31,6 +31,7 @@ const { deployBaseOracle } = require('./base-oracle-deploy.test') + contract('BaseOracle', ([admin, member]) => { let consensus let baseOracle @@ -122,14 +123,56 @@ contract('BaseOracle', ([admin, member]) => { before(deployContract) it('reverts on same version', async () => { - await assert.revertsWithCustomError(baseOracle.setConsensusVersion(1), 'VersionCannotBeSame()') + await assert.revertsWithCustomError(baseOracle.setConsensusVersion(CONSENSUS_VERSION), 'VersionCannotBeSame()') }) it('sets updated version', async () => { const tx = await baseOracle.setConsensusVersion(2) - assert.emits(tx, 'ConsensusVersionSet', { version: 2, prevVersion: 1 }) + assert.emits(tx, 'ConsensusVersionSet', { version: 2, prevVersion: CONSENSUS_VERSION }) const versionInState = await baseOracle.getConsensusVersion() assert.equal(versionInState, 2) }) }) + + describe('_checkConsensusData checks provided data against internal state', () => { + before(deployContract) + + it('report is submitted', async () => { + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + 10) + }) + + it('deadline missed on current ref slot, reverts on any arguments', async () => { + await baseOracle.advanceTimeBy(11) + await assert.revertsWithCustomError( + baseOracle.checkConsensusData(initialRefSlot, CONSENSUS_VERSION, HASH_1), + `ProcessingDeadlineMissed(${initialRefSlot + 10})` + ) + await baseOracle.setTime(initialRefSlot) + }) + + it('reverts on mismatched slot', async () => { + await assert.revertsWithCustomError( + baseOracle.checkConsensusData(initialRefSlot + 1, CONSENSUS_VERSION, HASH_1), + `UnexpectedRefSlot(${initialRefSlot}, ${initialRefSlot + 1})` + ) + }) + + it('reverts on mismatched consensus version', async () => { + await assert.revertsWithCustomError( + baseOracle.checkConsensusData(initialRefSlot, CONSENSUS_VERSION + 1, HASH_1), + `UnexpectedConsensusVersion(${CONSENSUS_VERSION}, ${CONSENSUS_VERSION + 1})` + ) + }) + + it('reverts on mismatched hash', async () => { + await assert.revertsWithCustomError( + baseOracle.checkConsensusData(initialRefSlot, CONSENSUS_VERSION, HASH_2), + `UnexpectedDataHash("${HASH_1}", "${HASH_2}")` + ) + }) + + it('check succeeds', async () => { + await baseOracle.checkConsensusData(initialRefSlot, CONSENSUS_VERSION, HASH_1) + }) + }) }) From fe0b5bfbc345ad8ed70d496f95083bbca0374c5a Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 16:07:08 +0700 Subject: [PATCH 27/82] fix: helper utils imports typo error --- test/0.8.9/oracle/hash-consensus-frames.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/oracle/hash-consensus-frames.js b/test/0.8.9/oracle/hash-consensus-frames.js index a7347f137..a130a8544 100644 --- a/test/0.8.9/oracle/hash-consensus-frames.js +++ b/test/0.8.9/oracle/hash-consensus-frames.js @@ -3,7 +3,7 @@ const { assertEvent } = require('@aragon/contract-helpers-test/src/asserts') const { assertRevert } = require('../../helpers/assertThrow') const { - INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_FAST_LANE_LENGTH_SLOTS, INITIAL_EPOCH, EPOCHS_PER_FRAME, SLOTS_PER_EPOCH, @@ -47,7 +47,7 @@ contract('HashConsensus', ([admin, member1, member2]) => { it('should return initial data', async () => { assert.equal(+(await consensus.getFrameConfig()).epochsPerFrame, EPOCHS_PER_FRAME) assert.equal(+(await consensus.getFrameConfig()).initialEpoch, INITIAL_EPOCH) - assert.equal(+(await consensus.getFrameConfig()).fastLaneLengthSlots, INITIAL_FAST_LANE_LENGHT_SLOTS) + assert.equal(+(await consensus.getFrameConfig()).fastLaneLengthSlots, INITIAL_FAST_LANE_LENGTH_SLOTS) }) it('should return new data', async () => { From f773d367d6d8ca143889124fd30fe2840c8ddd34 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 16:08:50 +0700 Subject: [PATCH 28/82] test: method getReportVariants returns empty data if lastReportRefSlot != currentFrame.refSlot --- .../hash-consensus-report-processor.test.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/0.8.9/oracle/hash-consensus-report-processor.test.js b/test/0.8.9/oracle/hash-consensus-report-processor.test.js index e9a349315..45d585e69 100644 --- a/test/0.8.9/oracle/hash-consensus-report-processor.test.js +++ b/test/0.8.9/oracle/hash-consensus-report-processor.test.js @@ -10,6 +10,7 @@ const { deployHashConsensus, computeTimestampAtEpoch } = require('./hash-consensus-deploy.test') +const { toNum } = require('../../helpers/utils') const HashConsensus = artifacts.require('HashConsensusTimeTravellable') const MockReportProcessor = artifacts.require('MockReportProcessor') @@ -132,5 +133,24 @@ contract('HashConsensus', ([admin, member1, member2, stranger]) => { assert.equal(await consensus.getConsensusVersion(), CONSENSUS_VERSION_2) }) }) + + context('method getReportVariants', () => { + beforeEach(deploy) + + it(`returns empty data if lastReportRefSlot != currentFrame.refSlot`, async () => { + const { refSlot } = await consensus.getCurrentFrame() + await consensus.addMember(member1, 1, { from: admin }) + + await consensus.submitReport(refSlot, HASH_1, CONSENSUS_VERSION, { from: member1 }) + const reportVariants1 = await consensus.getReportVariants() + assert.sameOrderedMembers(reportVariants1.variants, [HASH_1]) + assert.sameOrderedMembers(reportVariants1.support.map(toNum), [1]) + + await consensus.advanceTimeToNextFrameStart() + const reportVariants2 = await consensus.getReportVariants() + assert.sameOrderedMembers(reportVariants2.variants, []) + assert.sameOrderedMembers(reportVariants2.support.map(toNum), []) + }) + }) }) }) From e774e5c0a251bb96971109b65f251fb2f8591585 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 16:09:32 +0700 Subject: [PATCH 29/82] test: HashConsensus deploy reverts if admin or processor address equals zero --- .../oracle/hash-consensus-deploy.test.js | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/oracle/hash-consensus-deploy.test.js b/test/0.8.9/oracle/hash-consensus-deploy.test.js index 48b0a2e75..f8bcd930a 100644 --- a/test/0.8.9/oracle/hash-consensus-deploy.test.js +++ b/test/0.8.9/oracle/hash-consensus-deploy.test.js @@ -1,5 +1,5 @@ -const { assert } = require('chai') -const { bn } = require('@aragon/contract-helpers-test') +const { assert } = require('../../helpers/assert') +const { bn, ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const HashConsensus = artifacts.require('HashConsensusTimeTravellable') const MockReportProcessor = artifacts.require('MockReportProcessor') @@ -125,5 +125,38 @@ contract('HashConsensus', ([admin, member1]) => { assert.equal(+config.initialEpoch, INITIAL_EPOCH) assert.equal(+config.epochsPerFrame, EPOCHS_PER_FRAME) }) + + it('reverts if report processor address is zero', async () => { + await assert.revertsWithCustomError(HashConsensus.new( + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + INITIAL_EPOCH, + INITIAL_FAST_LANE_LENGTH_SLOTS, + admin, + ZERO_ADDRESS, + { from: admin } + ), + 'ReportProcessorCannotBeZero()' + ) + }) + + it('reverts if admin address is zero', async () => { + const reportProcessor = await MockReportProcessor.new(CONSENSUS_VERSION, { from: admin }) + await assert.revertsWithCustomError(HashConsensus.new( + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + EPOCHS_PER_FRAME, + INITIAL_EPOCH, + INITIAL_FAST_LANE_LENGTH_SLOTS, + ZERO_ADDRESS, + reportProcessor.address, + { from: admin } + ), + 'AdminCannotBeZero()' + ) + }) }) }) From 94b6cd01b36ac049c8338c912d3f040adddf6003 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 16:20:43 +0700 Subject: [PATCH 30/82] test: addMember reverts if member address equals zero --- test/0.8.9/oracle/hash-consensus-members.test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/0.8.9/oracle/hash-consensus-members.test.js b/test/0.8.9/oracle/hash-consensus-members.test.js index fef176f47..2eb434140 100644 --- a/test/0.8.9/oracle/hash-consensus-members.test.js +++ b/test/0.8.9/oracle/hash-consensus-members.test.js @@ -54,6 +54,13 @@ contract('HashConsensus', ([admin, member1, member2, member3, member4, member5, context('addMember', () => { before(deploy) + it('reverts if member address equals zero', async () => { + await assert.revertsWithCustomError( + consensus.addMember(ZERO_ADDRESS, 1, {from: admin}), + 'AddressCannotBeZero()' + ) + }) + it('allows to add a member, setting the new quorum', async () => { const newQuorum = 1 const tx = await consensus.addMember(member1, newQuorum, {from: admin}) From 39a4e6e551f3e701aecc2caee6ba96d61a67c58c Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 16:46:08 +0700 Subject: [PATCH 31/82] test: refactor helpers usage --- .../oracle/hash-consensus-deploy.test.js | 4 ++-- .../hash-consensus-report-processor.test.js | 20 +++++++++---------- test/helpers/assert.js | 6 +----- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/test/0.8.9/oracle/hash-consensus-deploy.test.js b/test/0.8.9/oracle/hash-consensus-deploy.test.js index f8bcd930a..b2ddd2f5f 100644 --- a/test/0.8.9/oracle/hash-consensus-deploy.test.js +++ b/test/0.8.9/oracle/hash-consensus-deploy.test.js @@ -127,7 +127,7 @@ contract('HashConsensus', ([admin, member1]) => { }) it('reverts if report processor address is zero', async () => { - await assert.revertsWithCustomError(HashConsensus.new( + await assert.reverts(HashConsensus.new( SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME, @@ -144,7 +144,7 @@ contract('HashConsensus', ([admin, member1]) => { it('reverts if admin address is zero', async () => { const reportProcessor = await MockReportProcessor.new(CONSENSUS_VERSION, { from: admin }) - await assert.revertsWithCustomError(HashConsensus.new( + await assert.reverts(HashConsensus.new( SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME, diff --git a/test/0.8.9/oracle/hash-consensus-report-processor.test.js b/test/0.8.9/oracle/hash-consensus-report-processor.test.js index 45d585e69..982ad4b72 100644 --- a/test/0.8.9/oracle/hash-consensus-report-processor.test.js +++ b/test/0.8.9/oracle/hash-consensus-report-processor.test.js @@ -1,14 +1,10 @@ -const { assert, getAccessControlMessage } = require('../../helpers/assert') -const { assertEvent } = require('@aragon/contract-helpers-test/src/asserts') -const { assertRevert } = require('../../helpers/assertThrow') +const { assert } = require('../../helpers/assert') const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const { HASH_1, - HASH_2, CONSENSUS_VERSION, deployHashConsensus, - computeTimestampAtEpoch } = require('./hash-consensus-deploy.test') const { toNum } = require('../../helpers/utils') @@ -40,24 +36,26 @@ contract('HashConsensus', ([admin, member1, member2, stranger]) => { beforeEach(deploy) it('checks next processor is not zero', async () => { - await assertRevert(consensus.setReportProcessor(ZERO_ADDRESS), 'ReportProcessorCannotBeZero()') + await assert.reverts(consensus.setReportProcessor(ZERO_ADDRESS), 'ReportProcessorCannotBeZero()') }) it('checks next processor is not the same as previous', async () => { - await assertRevert(consensus.setReportProcessor(reportProcessor1.address), 'NewProcessorCannotBeTheSame()') + await assert.reverts(consensus.setReportProcessor(reportProcessor1.address), 'NewProcessorCannotBeTheSame()') }) it('checks tx sender for MANAGE_REPORT_PROCESSOR_ROLE', async () => { - await assertRevert( + await assert.revertsOZAccessControl( consensus.setReportProcessor(reportProcessor2.address, { from: stranger }), - getAccessControlMessage(stranger.toLowerCase(), await consensus.MANAGE_REPORT_PROCESSOR_ROLE()) + stranger, + 'MANAGE_REPORT_PROCESSOR_ROLE' ) }) it('emits ReportProcessorSet event', async () => { const tx = await consensus.setReportProcessor(reportProcessor2.address) - assertEvent(tx, 'ReportProcessorSet', { - expectedArgs: { processor: reportProcessor2.address, prevProcessor: reportProcessor1.address } + assert.emits(tx, 'ReportProcessorSet', { + processor: reportProcessor2.address, + prevProcessor: reportProcessor1.address }) }) diff --git a/test/helpers/assert.js b/test/helpers/assert.js index c1b76c4cc..64f5bbabe 100644 --- a/test/helpers/assert.js +++ b/test/helpers/assert.js @@ -113,8 +113,4 @@ function normalizeArg(arg) { return arg } -function getAccessControlMessage(address, role) { - return `AccessControl: account ${address} is missing role ${role}` -} - -module.exports = { assert: chai.assert, getAccessControlMessage } +module.exports = { assert: chai.assert } From a426b57ef79a5b1d2dcb7958a3a79ed6a5aeecdf Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 17:04:56 +0700 Subject: [PATCH 32/82] test: HashConsensus.setFastLaneLengthSlots --- .../hash-consensus-fast-lane-length.test.js | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js diff --git a/test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js b/test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js new file mode 100644 index 000000000..1c7476222 --- /dev/null +++ b/test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js @@ -0,0 +1,62 @@ +const { assert } = require('../../helpers/assert') + +const { deployHashConsensus } = require('./hash-consensus-deploy.test') + +const HashConsensus = artifacts.require('HashConsensusTimeTravellable') +const MockReportProcessor = artifacts.require('MockReportProcessor') + +contract('HashConsensus', ([admin, member1, member2, stranger]) => { + context('Report Processor', () => { + let consensus + + const deploy = async (options = undefined) => { + const deployed = await deployHashConsensus(admin, options) + consensus = deployed.consensus + } + + context('initial data', () => { + it('sets properly', async () => { + await deploy({ fastLaneLengthSlots: 0 }) + assert.equal(+(await consensus.getFrameConfig()).fastLaneLengthSlots, 0) + await deploy({ fastLaneLengthSlots: 4 }) + assert.equal(+(await consensus.getFrameConfig()).fastLaneLengthSlots, 4) + }) + }) + + context('setFastLaneLengthSlots', () => { + beforeEach(deploy) + + const getFastLaneLengthSlotsLimit = async () => { + const { slotsPerEpoch } = await consensus.getChainConfig() + const { epochsPerFrame } = await consensus.getFrameConfig() + return +slotsPerEpoch * +epochsPerFrame + } + + it('should revert if fastLaneLengthSlots > epochsPerFrame * slotsPerEpoch', async () => { + const fastLaneLengthSlots = (await getFastLaneLengthSlotsLimit()) + 1 + await assert.reverts( + consensus.setFastLaneLengthSlots(fastLaneLengthSlots, { from: admin }), + 'FastLanePeriodCannotBeLongerThanFrame()' + ) + }) + + it('sets new value properly', async () => { + const fastLaneLengthSlots = await getFastLaneLengthSlotsLimit() + await consensus.setFastLaneLengthSlots(fastLaneLengthSlots, { from: admin }) + assert.equal(+(await consensus.getFrameConfig()).fastLaneLengthSlots, fastLaneLengthSlots) + }) + + it('emits FastLaneConfigSet event', async () => { + const fastLaneLengthSlots = await getFastLaneLengthSlotsLimit() + const tx = await consensus.setFastLaneLengthSlots(fastLaneLengthSlots, { from: admin }) + assert.emits(tx, 'FastLaneConfigSet', { fastLaneLengthSlots }) + }) + + it('not emits FastLaneConfigSet if new value is the same', async () => { + const fastLaneLengthSlots = +(await consensus.getFrameConfig()).fastLaneLengthSlots + const tx = await consensus.setFastLaneLengthSlots(fastLaneLengthSlots, { from: admin }) + assert.notEmits(tx, 'FastLaneConfigSet', { fastLaneLengthSlots }) + }) + }) + }) +}) From 830f07f9179f8eed319497364ab8e5e89a327c92 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 12 Feb 2023 19:08:50 +0700 Subject: [PATCH 33/82] test: base oracle: fix test disc --- test/0.8.9/oracle/base-oracle-access-control.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/0.8.9/oracle/base-oracle-access-control.test.js b/test/0.8.9/oracle/base-oracle-access-control.test.js index 26bb677b1..f2ce4b30e 100644 --- a/test/0.8.9/oracle/base-oracle-access-control.test.js +++ b/test/0.8.9/oracle/base-oracle-access-control.test.js @@ -1,4 +1,3 @@ -const { MaxUint256 } = require('@ethersproject/constants') const { assert } = require('../../helpers/assert') const { @@ -31,7 +30,7 @@ contract('BaseOracle', ([admin, account1, account2, member1, member2]) => { context('deploying', () => { before(deploy) - it('deploying hash oracle', async () => { + it('deploying oracle', async () => { assert.isNotNull(oracle) assert.isNotNull(consensus) }) From de17bb04f3abd320f99096c5b37513d4e57f92c3 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 19:46:31 +0700 Subject: [PATCH 34/82] test: HashConsensus Report Submitting revert cases --- .../hash-consensus-submit-report.test.js | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 test/0.8.9/oracle/hash-consensus-submit-report.test.js diff --git a/test/0.8.9/oracle/hash-consensus-submit-report.test.js b/test/0.8.9/oracle/hash-consensus-submit-report.test.js new file mode 100644 index 000000000..e54e08164 --- /dev/null +++ b/test/0.8.9/oracle/hash-consensus-submit-report.test.js @@ -0,0 +1,72 @@ +const { assert } = require('../../helpers/assert') + +const { deployHashConsensus, CONSENSUS_VERSION, ZERO_HASH, HASH_1 } = require('./hash-consensus-deploy.test') + +const HashConsensus = artifacts.require('HashConsensusTimeTravellable') +const MockReportProcessor = artifacts.require('MockReportProcessor') + +const CONSENSUS_VERSION_2 = 2 + +contract('HashConsensus', ([admin, member1, member2, stranger]) => { + context('Report Submitting', () => { + let consensus + let frame + + const deploy = async (options = { epochsPerFrame: 200 }) => { + const deployed = await deployHashConsensus(admin, options) + consensus = deployed.consensus + reportProcessor = deployed.reportProcessor + frame = await consensus.getCurrentFrame() + await consensus.addMember(member1, 1, { from: admin }) + } + + context('method sumbitReport', () => { + beforeEach(deploy) + + it('reverts with NumericOverflow', async () => { + await assert.reverts( + consensus.submitReport('20446744073709551615', HASH_1, CONSENSUS_VERSION, { from: member1 }), + 'NumericOverflow()' + ) + }) + + it('reverts with UnexpectedConsensusVersion', async () => { + await assert.reverts( + consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION_2, { from: member1 }), + `UnexpectedConsensusVersion(${CONSENSUS_VERSION}, ${CONSENSUS_VERSION_2})` + ) + }) + + it('reverts with EmptyReport', async () => { + await assert.reverts( + consensus.submitReport(frame.refSlot, ZERO_HASH, CONSENSUS_VERSION, { from: member1 }), + `EmptyReport()` + ) + }) + + it('reverts with ConsensusReportAlreadyProcessing', async () => { + await consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION, { from: member1 }) + await reportProcessor.startReportProcessing() + await assert.reverts( + consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION, { from: member1 }), + `ConsensusReportAlreadyProcessing()` + ) + }) + + it('does not reverts with ConsensusReportAlreadyProcessing if member hasn`t sent a report for this slot', async () => { + await consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION, { from: member1 }) + await reportProcessor.startReportProcessing() + await consensus.addMember(member2, 2, { from: admin }) + await consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION, { from: member2 }) + }) + + it('reverts with DuplicateReport', async () => { + await consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION, { from: member1 }) + await assert.reverts( + consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION, { from: member1 }), + `DuplicateReport()` + ) + }) + }) + }) +}) From 2ec33f936116ef42b6274e6cb26485bec1b344e3 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Sun, 12 Feb 2023 19:47:29 +0700 Subject: [PATCH 35/82] test: fix fast lane length naming --- test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js b/test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js index 1c7476222..cfb6ff3bb 100644 --- a/test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js +++ b/test/0.8.9/oracle/hash-consensus-fast-lane-length.test.js @@ -6,7 +6,7 @@ const HashConsensus = artifacts.require('HashConsensusTimeTravellable') const MockReportProcessor = artifacts.require('MockReportProcessor') contract('HashConsensus', ([admin, member1, member2, stranger]) => { - context('Report Processor', () => { + context('Fast Lane Length', () => { let consensus const deploy = async (options = undefined) => { @@ -23,7 +23,7 @@ contract('HashConsensus', ([admin, member1, member2, stranger]) => { }) }) - context('setFastLaneLengthSlots', () => { + context('method setFastLaneLengthSlots', () => { beforeEach(deploy) const getFastLaneLengthSlotsLimit = async () => { From 1745a04f0df9a5d27de41a88e63c7cbe200228ba Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sun, 12 Feb 2023 15:59:38 +0300 Subject: [PATCH 36/82] fix: simulated share rate sancheck --- contracts/0.4.24/Lido.sol | 67 +++++++++++++++---- .../OracleReportSanityChecker.sol | 45 ++++++++----- .../OracleReportSanityCheckerMocks.sol | 2 +- lib/abi/ILido.json | 2 +- lib/abi/Lido.json | 2 +- lib/abi/OracleReportSanityChecker.json | 2 +- .../oracle-report-sanity-checker.test.js | 44 +++++++++--- 7 files changed, 120 insertions(+), 44 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 669a08209..177c74fc3 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -55,9 +55,14 @@ interface IOracleReportSanityChecker { function checkWithdrawalQueueOracleReport( uint256 _lastFinalizableRequestId, - uint256 _simulatedShareRate, uint256 _reportTimestamp ) external view; + + function checkSimulatedShareRate( + uint256 _noWithdrawalsPostTotalPooledEther, + uint256 _noWithdrawalsPostTotalShares, + uint256 _simulatedShareRate + ) external view; } interface ILidoExecutionLayerRewardsVault { @@ -515,10 +520,15 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer for report block * @param _elRewardsVaultBalance elRewards vault balance on Execution Layer for report block * @param _lastFinalizableRequestId right boundary of requestId range if equals 0, no requests should be finalized - * @param _simulatedShareRate share rate that was simulated by oracle when the report data created + * @param _simulatedShareRate share rate that was simulated by oracle when the report data created (1e27 precision) * - * @return totalPooledEther amount of ether in the protocol after report - * @return totalShares amount of shares in the protocol after report + * NB: `_simulatedShareRate` should be calculated by the Oracle daemon + * invoking the method with static call and passing `_lastFinalizableRequestId` == `_simulatedShareRate` == 0 + * plugging the returned values to the following formula: + * `_simulatedShareRate = (postTotalPooledEther * 1e27) / postTotalShares` + * + * @return postTotalPooledEther amount of ether in the protocol after report + * @return postTotalShares amount of shares in the protocol after report * @return withdrawals withdrawn from the withdrawals vault * @return elRewards withdrawn from the execution layer rewards vault */ @@ -536,8 +546,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 _lastFinalizableRequestId, uint256 _simulatedShareRate ) external returns ( - uint256 totalPooledEther, - uint256 totalShares, + uint256 postTotalPooledEther, + uint256 postTotalShares, uint256 withdrawals, uint256 elRewards ) { @@ -813,10 +823,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { ) { IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(_contracts.withdrawalQueue); - if (!withdrawalQueue.isPaused() && _reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { + if (!withdrawalQueue.isPaused()) { IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkWithdrawalQueueOracleReport( _reportedData.lastFinalizableRequestId, - _reportedData.simulatedShareRate, _reportedData.reportTimestamp ); @@ -1142,6 +1151,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * 6. Distribute protocol fee (treasury & node operators) * 7. Burn excess shares (withdrawn stETH at least) * 8. Complete token rebase by informing observers (emit an event and call the external receivers if any) + * 9. Sanity check for the provided simulated share rate */ function _handleOracleReport( OracleReportedData memory _reportedData, @@ -1177,10 +1187,12 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 3. // Pre-calculate the ether to lock for withdrawal queue and shares to be burnt - ( - reportContext.etherToLockOnWithdrawalQueue, - reportContext.sharesToBurnFromWithdrawalQueue - ) = _calculateWithdrawals(_contracts, _reportedData); + if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { + ( + reportContext.etherToLockOnWithdrawalQueue, + reportContext.sharesToBurnFromWithdrawalQueue + ) = _calculateWithdrawals(_contracts, _reportedData); + } // Step 4. // Pass the accounting values to sanity checker to smoothen positive token rebase @@ -1227,7 +1239,10 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 7. // Burn excess shares (withdrawn stETH at least) - _burnSharesLimited(IBurner(_contracts.burner), reportContext.sharesToBurnLimit); + uint256 postponedSharesToBurn = _burnSharesLimited( + IBurner(_contracts.burner), + reportContext.sharesToBurnLimit + ); // Step 8. // Complete token rebase by informing observers (emit an event and call the external receivers if any) @@ -1239,6 +1254,22 @@ contract Lido is Versioned, StETHPermit, AragonApp { reportContext, IPostTokenRebaseReceiver(_contracts.postTokenRebaseReceiver) ); + + // Step 9. Sanity check for the provided simulated share rate + if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { + uint256 noWithdrawalsPostTotalShares = postTotalShares; + if (postponedSharesToBurn < reportContext.sharesToBurnFromWithdrawalQueue) { + noWithdrawalsPostTotalShares = noWithdrawalsPostTotalShares.sub( + reportContext.sharesToBurnFromWithdrawalQueue - postponedSharesToBurn + ); + } + + IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkSimulatedShareRate( + postTotalPooledEther.sub(reportContext.etherToLockOnWithdrawalQueue), + noWithdrawalsPostTotalShares, + _reportedData.simulatedShareRate + ); + } } /** @@ -1281,8 +1312,12 @@ contract Lido is Versioned, StETHPermit, AragonApp { * * NB: some of the burning amount can be postponed for the next reports * if positive token rebase smoothened. + * + * @return unburnt shares (postponed for next oracle reports) */ - function _burnSharesLimited(IBurner _burner, uint256 _sharesToBurnLimit) internal { + function _burnSharesLimited( + IBurner _burner, uint256 _sharesToBurnLimit + ) internal returns (uint256 postponedSharesToBurn) { if (_sharesToBurnLimit > 0) { uint256 sharesCommittedToBurnNow = _burner.commitSharesToBurn(_sharesToBurnLimit); @@ -1290,6 +1325,10 @@ contract Lido is Versioned, StETHPermit, AragonApp { _burnShares(address(_burner), sharesCommittedToBurnNow); } } + + (uint256 coverShares, uint256 nonCoverShares) = _burner.getSharesRequestedToBurn(); + + return coverShares.add(nonCoverShares); } /** diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 5ed8d77bf..7722fea1d 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -11,10 +11,6 @@ import {AccessControlEnumerable} from "../utils/access/AccessControlEnumerable.s import {PositiveTokenRebaseLimiter, TokenRebaseLimiterData} from "../lib/PositiveTokenRebaseLimiter.sol"; import {ILidoLocator} from "../../common/interfaces/ILidoLocator.sol"; -interface ILido { - function getSharesByPooledEth(uint256 _sharesAmount) external view returns (uint256); -} - interface IWithdrawalQueue { function getWithdrawalRequestStatus(uint256 _requestId) external @@ -81,6 +77,7 @@ struct LimitsListPacked { } uint256 constant MAX_BASIS_POINTS = 10_000; +uint256 constant SHARE_RATE_PRECISION_E27 = 1e27; /// @title Sanity checks for the Lido's oracle report /// @notice The contracts contain view methods to perform sanity checks of the Lido's oracle report @@ -415,27 +412,37 @@ contract OracleReportSanityChecker is AccessControlEnumerable { revert MaxAccountingExtraDataItemsCountExceeded(limit, _extraDataListItemsCount); } - /// @notice Applies sanity checks to the withdrawal requests params of Lido's oracle report + /// @notice Applies sanity checks to the withdrawal requests finalization /// @param _lastFinalizableRequestId right boundary of requestId range if equals 0, no requests /// should be finalized - /// @param _simulatedShareRate share rate that should be used for finalization /// @param _reportTimestamp timestamp when the originated oracle report was submitted function checkWithdrawalQueueOracleReport( uint256 _lastFinalizableRequestId, - uint256 _simulatedShareRate, uint256 _reportTimestamp - ) + ) external view { LimitsList memory limitsList = _limits.unpack(); address withdrawalQueue = LIDO_LOCATOR.withdrawalQueue(); - // 1. No finalized id up to newer than the allowed report margin + _checkRequestIdToFinalizeUpTo(limitsList, withdrawalQueue, _lastFinalizableRequestId, _reportTimestamp); + } - address lido = LIDO_LOCATOR.lido(); - // 2. shareRate calculated off-chain is consistent with the on-chain one - _checkFinalizationShareRate(limitsList, lido, _simulatedShareRate); + /// @notice Applies sanity checks to the simulated share rate for withdrawal requests finalization + /// @param _noWithdrawalsPostTotalPooledEther total pooled ether after report applied if no withdrawal requests finalized + /// @param _noWithdrawalsPostTotalShares total shares after report applied if no withdrawal requests finalized + /// @param _simulatedShareRate share rate provided with the oracle report (simulated via static call) + function checkSimulatedShareRate( + uint256 _noWithdrawalsPostTotalPooledEther, + uint256 _noWithdrawalsPostTotalShares, + uint256 _simulatedShareRate + ) external view { + LimitsList memory limitsList = _limits.unpack(); + + _checkFinalizationShareRate( + limitsList, _noWithdrawalsPostTotalPooledEther, _noWithdrawalsPostTotalShares, _simulatedShareRate + ); } function _checkWithdrawalVaultBalance( @@ -504,8 +511,6 @@ contract OracleReportSanityChecker is AccessControlEnumerable { uint256 _requestIdToFinalizeUpTo, uint256 _reportTimestamp ) internal view { - if (_requestIdToFinalizeUpTo == 0) { return; } - (, , , uint256 requestTimestampToFinalizeUpTo, , ) = IWithdrawalQueue(_withdrawalQueue) .getWithdrawalRequestStatus(_requestIdToFinalizeUpTo); if (_reportTimestamp < requestTimestampToFinalizeUpTo + _limitsList.requestTimestampMargin) @@ -514,12 +519,18 @@ contract OracleReportSanityChecker is AccessControlEnumerable { function _checkFinalizationShareRate( LimitsList memory _limitsList, - address _lido, + uint256 _noWithdrawalsPostTotalPooledEther, + uint256 _noWithdrawalsPostTotalShares, uint256 _simulatedShareRate ) internal view { - uint256 actualShareRate = ILido(_lido).getSharesByPooledEth(1 ether); + uint256 actualShareRate = ( + _noWithdrawalsPostTotalPooledEther * SHARE_RATE_PRECISION_E27 + ) / _noWithdrawalsPostTotalShares; - if (actualShareRate == 0 || _simulatedShareRate == 0) { return; } + if (actualShareRate == 0) { + // can't finalize anything if the actual share rate is zero + revert IncorrectFinalizationShareRate(MAX_BASIS_POINTS); + } uint256 finalizationShareDiff = Math256.abs( SafeCast.toInt256(_simulatedShareRate) - SafeCast.toInt256(actualShareRate) diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index 4f7348a0f..7c1eef4d5 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -4,7 +4,7 @@ /* See contracts/COMPILERS.md */ pragma solidity 0.8.9; -import {ILido, IWithdrawalQueue} from "../sanity_checks/OracleReportSanityChecker.sol"; +import {IWithdrawalQueue} from "../sanity_checks/OracleReportSanityChecker.sol"; contract LidoStub { uint256 private _shareRate = 1 ether; diff --git a/lib/abi/ILido.json b/lib/abi/ILido.json index c440961b0..e79a4bf07 100644 --- a/lib/abi/ILido.json +++ b/lib/abi/ILido.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"},{"internalType":"uint256","name":"_timeElapsedSeconds","type":"uint256"},{"internalType":"uint256","name":"_clValidators","type":"uint256"},{"internalType":"uint256","name":"_clBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/Lido.json b/lib/abi/Lido.json index 8d36a3481..9c3939399 100644 --- a/lib/abi/Lido.json +++ b/lib/abi/Lido.json @@ -1 +1 @@ -[{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_CONTROL_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ethAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStakingPaused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxStakeLimit","type":"uint256"},{"name":"_stakeLimitIncreasePerBlock","type":"uint256"}],"name":"setStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"RESUME_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalPooledEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTreasury","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBufferedEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveELRewards","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentStakeLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakeLimitFullInfo","outputs":[{"name":"isStakingPaused","type":"bool"},{"name":"isStakingLimitSet","type":"bool"},{"name":"currentStakeLimit","type":"uint256"},{"name":"maxStakeLimit","type":"uint256"},{"name":"maxStakeLimitGrowthBlocks","type":"uint256"},{"name":"prevStakeLimit","type":"uint256"},{"name":"prevStakeBlockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFeeDistribution","outputs":[{"name":"treasuryFeeBasisPoints","type":"uint16"},{"name":"insuranceFeeBasisPoints","type":"uint16"},{"name":"operatorsFeeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"receiveWithdrawals","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_sharesAmount","type":"uint256"}],"name":"getPooledEthByShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"nonces","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_referral","type":"address"}],"name":"submit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxDepositsCount","type":"uint256"},{"name":"_stakingModuleId","type":"uint256"},{"name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconStat","outputs":[{"name":"depositedValidators","type":"uint256"},{"name":"beaconValidators","type":"uint256"},{"name":"beaconBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_reportTimestamp","type":"uint256"},{"name":"_timeElapsed","type":"uint256"},{"name":"_clValidators","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_withdrawalVaultBalance","type":"uint256"},{"name":"_elRewardsVaultBalance","type":"uint256"},{"name":"_lastFinalizableRequestId","type":"uint256"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"totalPooledEther","type":"uint256"},{"name":"totalShares","type":"uint256"},{"name":"withdrawals","type":"uint256"},{"name":"elRewards","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveStakingRouterDepositRemainder","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getFee","outputs":[{"name":"totalFee","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLidoLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canDeposit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalELRewardsCollected","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[],"name":"StakingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxStakeLimit","type":"uint256"},{"indexed":false,"name":"stakeLimitIncreasePerBlock","type":"uint256"}],"name":"StakingLimitSet","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingLimitRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLBalance","type":"uint256"},{"indexed":false,"name":"postCLBalance","type":"uint256"},{"indexed":false,"name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"name":"executionLayerRewardsWithdrawn","type":"uint256"},{"indexed":false,"name":"postBufferedEther","type":"uint256"}],"name":"ETHDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"preTotalShares","type":"uint256"},{"indexed":false,"name":"preTotalEther","type":"uint256"},{"indexed":false,"name":"postTotalShares","type":"uint256"},{"indexed":false,"name":"postTotalEther","type":"uint256"},{"indexed":false,"name":"sharesMintedAsFees","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"lidoLocator","type":"address"}],"name":"LidoLocatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"ELRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unbuffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"StakingRouterDepositRemainderReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"eip712StETH","type":"address"}],"name":"EIP712StETHInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_CONTROL_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ethAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStakingPaused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxStakeLimit","type":"uint256"},{"name":"_stakeLimitIncreasePerBlock","type":"uint256"}],"name":"setStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"RESUME_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalPooledEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTreasury","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBufferedEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveELRewards","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentStakeLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakeLimitFullInfo","outputs":[{"name":"isStakingPaused","type":"bool"},{"name":"isStakingLimitSet","type":"bool"},{"name":"currentStakeLimit","type":"uint256"},{"name":"maxStakeLimit","type":"uint256"},{"name":"maxStakeLimitGrowthBlocks","type":"uint256"},{"name":"prevStakeLimit","type":"uint256"},{"name":"prevStakeBlockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFeeDistribution","outputs":[{"name":"treasuryFeeBasisPoints","type":"uint16"},{"name":"insuranceFeeBasisPoints","type":"uint16"},{"name":"operatorsFeeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"receiveWithdrawals","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_sharesAmount","type":"uint256"}],"name":"getPooledEthByShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"nonces","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_referral","type":"address"}],"name":"submit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxDepositsCount","type":"uint256"},{"name":"_stakingModuleId","type":"uint256"},{"name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconStat","outputs":[{"name":"depositedValidators","type":"uint256"},{"name":"beaconValidators","type":"uint256"},{"name":"beaconBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_reportTimestamp","type":"uint256"},{"name":"_timeElapsed","type":"uint256"},{"name":"_clValidators","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_withdrawalVaultBalance","type":"uint256"},{"name":"_elRewardsVaultBalance","type":"uint256"},{"name":"_lastFinalizableRequestId","type":"uint256"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"postTotalPooledEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"withdrawals","type":"uint256"},{"name":"elRewards","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveStakingRouterDepositRemainder","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getFee","outputs":[{"name":"totalFee","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLidoLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canDeposit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalELRewardsCollected","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[],"name":"StakingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxStakeLimit","type":"uint256"},{"indexed":false,"name":"stakeLimitIncreasePerBlock","type":"uint256"}],"name":"StakingLimitSet","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingLimitRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLBalance","type":"uint256"},{"indexed":false,"name":"postCLBalance","type":"uint256"},{"indexed":false,"name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"name":"executionLayerRewardsWithdrawn","type":"uint256"},{"indexed":false,"name":"postBufferedEther","type":"uint256"}],"name":"ETHDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"preTotalShares","type":"uint256"},{"indexed":false,"name":"preTotalEther","type":"uint256"},{"indexed":false,"name":"postTotalShares","type":"uint256"},{"indexed":false,"name":"postTotalEther","type":"uint256"},{"indexed":false,"name":"sharesMintedAsFees","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"lidoLocator","type":"address"}],"name":"LidoLocatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"ELRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unbuffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"StakingRouterDepositRemainderReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"eip712StETH","type":"address"}],"name":"EIP712StETHInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"}] \ No newline at end of file diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index 0a1b914a1..3fdf5f2ee 100644 --- a/lib/abi/OracleReportSanityChecker.json +++ b/lib/abi/OracleReportSanityChecker.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkAccountingOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkAccountingOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_noWithdrawalsPostTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_noWithdrawalsPostTotalShares","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"checkSimulatedShareRate","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/test/0.8.9/oracle-report-sanity-checker.test.js b/test/0.8.9/oracle-report-sanity-checker.test.js index d74a38095..fe9c1f26d 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -176,7 +176,6 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc let oldRequestCreationTimestamp, newRequestCreationTimestamp const correctWithdrawalQueueOracleReport = { requestIdToFinalizeUpTo: oldRequestId, - finalizationShareRate: ETH(1), refReportTimestamp: -1 } @@ -203,24 +202,51 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc ) }) + it('passes all checks with correct withdrawal queue report data', async () => { + await oracleReportSanityChecker.checkWithdrawalQueueOracleReport( + ...Object.values(correctWithdrawalQueueOracleReport) + ) + }) + }) + + describe('checkSimulatedShareRate', async () => { + const correctSimulatedShareRate = { + noWithdrawalsPostTotalPooledEther: ETH(10), + noWithdrawalsPostTotalShares: ETH(5), + simulatedShareRate: (BigInt(2) * 10n ** 27n).toString() + } + it('reverts with error IncorrectFinalizationShareRate() when reported and onchain share rate differs', async () => { - const finalizationShareRate = BigInt(ETH(1.05)) - const actualShareRate = BigInt(ETH(1)) + const finalizationShareRate = BigInt(ETH(2.10)) * 10n ** 9n + const actualShareRate = BigInt(2) * 10n ** 27n const deviation = (100_00n * (finalizationShareRate - actualShareRate)) / actualShareRate await assert.revertsWithCustomError( - oracleReportSanityChecker.checkWithdrawalQueueOracleReport( + oracleReportSanityChecker.checkSimulatedShareRate( ...Object.values({ - ...correctWithdrawalQueueOracleReport, - finalizationShareRate: finalizationShareRate.toString() + ...correctSimulatedShareRate, + simulatedShareRate: finalizationShareRate.toString() }) ), `IncorrectFinalizationShareRate(${deviation.toString()})` ) }) - it('passes all checks with correct withdrawal queue report data', async () => { - await oracleReportSanityChecker.checkWithdrawalQueueOracleReport( - ...Object.values(correctWithdrawalQueueOracleReport) + it('reverts with error IncorrectFinalizationShareRate() when actual share rate is zero', async () => { + const deviation = 100_00n + await assert.revertsWithCustomError( + oracleReportSanityChecker.checkSimulatedShareRate( + ...Object.values({ + ...correctSimulatedShareRate, + noWithdrawalsPostTotalPooledEther: ETH(0) + }) + ), + `IncorrectFinalizationShareRate(${deviation.toString()})` + ) + }) + + it('passes all checks with correct share rate', async () => { + await oracleReportSanityChecker.checkSimulatedShareRate( + ...Object.values(correctSimulatedShareRate) ) }) }) From bfc7d74d42844f89c8edd5bb191e00f59237275e Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sun, 12 Feb 2023 20:02:03 +0700 Subject: [PATCH 37/82] feat: startProcessing tests & update helper --- .../oracle/BaseOracleTimeTravellable.sol | 6 ++- .../oracle/base-oracle-submit-report.test.js | 49 ++++++++++++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index e092bbcc2..7eb59c2b2 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -15,6 +15,9 @@ contract BaseOracleTimeTravellable is BaseOracle { using UnstructuredStorage for bytes32; uint256 internal _time = 2513040315; + event MockStartProcessingResult(uint256 prevProcessingRefSlot); + + struct HandleConsensusReportLastCall { ConsensusReport report; uint256 prevSubmittedRefSlot; @@ -65,7 +68,8 @@ contract BaseOracleTimeTravellable is BaseOracle { } function startProcessing() external { - _startProcessing(); + uint256 _res = _startProcessing(); + emit MockStartProcessingResult(_res); } function checkConsensusData(uint256 refSlot, uint256 consensusVersion, bytes32 hash) external view { diff --git a/test/0.8.9/oracle/base-oracle-submit-report.test.js b/test/0.8.9/oracle/base-oracle-submit-report.test.js index f14530285..1d454733f 100644 --- a/test/0.8.9/oracle/base-oracle-submit-report.test.js +++ b/test/0.8.9/oracle/base-oracle-submit-report.test.js @@ -1,7 +1,5 @@ -const { assert } = require('chai') -const { assertEvent, assertAmountOfEvents, assertBn } = require('@aragon/contract-helpers-test/src/asserts') +const { assert } = require('../../helpers/assert') const { bn } = require('@aragon/contract-helpers-test') -const { assertRevert } = require('../../helpers/assertThrow') const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') @@ -24,7 +22,7 @@ contract('BaseOracle', ([admin]) => { before(deployContract) it('only setConsensus contract can call submitConsensusReport', async () => { - await assertRevert( + await assert.revertsWithCustomError( baseOracle.submitConsensusReport(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), 'OnlyConsensusContractCanSubmitReport()' ) @@ -49,7 +47,7 @@ contract('BaseOracle', ([admin]) => { }) it('older report cannot be submitted', async () => { - await assertRevert( + await assert.revertsWithCustomError( consensus.submitReportAsConsensus(HASH_1, initialRefSlot - 1, initialRefSlot + SLOTS_PER_FRAME), `RefSlotCannotDecrease(${initialRefSlot - 1}, ${initialRefSlot})` ) @@ -60,7 +58,7 @@ contract('BaseOracle', ([admin]) => { }) it('consensus cannot resubmit already processing report', async () => { - await assertRevert( + await assert.revertsWithCustomError( consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), `RefSlotMustBeGreaterThanProcessingOne(${initialRefSlot}, ${initialRefSlot})` ) @@ -148,4 +146,43 @@ contract('BaseOracle', ([admin]) => { }) }) }) + + describe('_startProcessing safely advances processing state', () => { + before(deployContract) + + it('initial contract state,no reports, can not startProcessing', async () => { + await assert.revertsWithCustomError(baseOracle.startProcessing(), 'ProcessingDeadlineMissed(0)') + }) + + it('submit first report for initial slot', async () => { + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + 20) + const tx = await baseOracle.startProcessing() + assert.emits(tx, 'ProcessingStarted', { refSlot: initialRefSlot, hash: HASH_1 }) + assert.emits(tx, 'MockStartProcessingResult', { prevProcessingRefSlot: '0' }) + }) + + it('no next report, processing same slot again, state is not changed', async () => { + const tx = await baseOracle.startProcessing() + assert.emits(tx, 'ProcessingStarted', { refSlot: initialRefSlot, hash: HASH_1 }) + assert.emits(tx, 'MockStartProcessingResult', { prevProcessingRefSlot: String(initialRefSlot) }) + const processingSlot = await baseOracle.getLastProcessingRefSlot() + assert.equals(processingSlot, initialRefSlot) + }) + + it('next report comes in, start processing, state advances', async () => { + await consensus.submitReportAsConsensus(HASH_2, initialRefSlot + 10, initialRefSlot + 20) + const tx = await baseOracle.startProcessing() + assert.emits(tx, 'ProcessingStarted', { refSlot: initialRefSlot + 10, hash: HASH_2 }) + assert.emits(tx, 'MockStartProcessingResult', { prevProcessingRefSlot: String(initialRefSlot) }) + const processingSlot = await baseOracle.getLastProcessingRefSlot() + assert.equals(processingSlot, initialRefSlot + 10) + }) + + it('another report but deadline is missed, reverts', async () => { + const nextSlot = initialRefSlot + 20 + await consensus.submitReportAsConsensus(HASH_3, nextSlot, nextSlot + 30) + await baseOracle.setTime(nextSlot + 40) + await assert.revertsWithCustomError(baseOracle.startProcessing(), `ProcessingDeadlineMissed(${nextSlot + 30})`) + }) + }) }) From 9ab92839d292aa917b69ffbd8f9ca6fac8bf7fac Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sun, 12 Feb 2023 16:09:09 +0300 Subject: [PATCH 38/82] fix: add instead of sub for simulated share rate --- contracts/0.4.24/Lido.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 177c74fc3..912f8dcc9 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -1259,13 +1259,13 @@ contract Lido is Versioned, StETHPermit, AragonApp { if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { uint256 noWithdrawalsPostTotalShares = postTotalShares; if (postponedSharesToBurn < reportContext.sharesToBurnFromWithdrawalQueue) { - noWithdrawalsPostTotalShares = noWithdrawalsPostTotalShares.sub( + noWithdrawalsPostTotalShares = noWithdrawalsPostTotalShares.add( reportContext.sharesToBurnFromWithdrawalQueue - postponedSharesToBurn ); } IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkSimulatedShareRate( - postTotalPooledEther.sub(reportContext.etherToLockOnWithdrawalQueue), + postTotalPooledEther.add(reportContext.etherToLockOnWithdrawalQueue), noWithdrawalsPostTotalShares, _reportedData.simulatedShareRate ); From d547911b60b4f96a075f29d38717d68acee5a824 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sun, 12 Feb 2023 20:17:54 +0700 Subject: [PATCH 39/82] fix: clean up helpers --- .../oracle/base-oracle-submit-report.test.js | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/test/0.8.9/oracle/base-oracle-submit-report.test.js b/test/0.8.9/oracle/base-oracle-submit-report.test.js index 1d454733f..39003637c 100644 --- a/test/0.8.9/oracle/base-oracle-submit-report.test.js +++ b/test/0.8.9/oracle/base-oracle-submit-report.test.js @@ -1,5 +1,4 @@ const { assert } = require('../../helpers/assert') -const { bn } = require('@aragon/contract-helpers-test') const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') @@ -31,14 +30,16 @@ contract('BaseOracle', ([admin]) => { it('initial report is submitted and _handleConsensusReport is called', async () => { assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 0) const tx = await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) - assertEvent(tx, 'ReportSubmitted', { - decodeForAbi: baseOracleAbi, - expectedArgs: { + assert.emits( + tx, + 'ReportSubmitted', + { refSlot: initialRefSlot, hash: HASH_1, processingDeadlineTime: initialRefSlot + SLOTS_PER_FRAME - } - }) + }, + { abi: baseOracleAbi } + ) const { report, callCount } = await baseOracle.getConsensusReportLastCall() assert.equal(+callCount, 1) assert.equal(report.hash, HASH_1) @@ -71,19 +72,23 @@ contract('BaseOracle', ([admin]) => { initialRefSlot + SLOTS_PER_FRAME ) assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 2) - assertEvent(tx1, 'ReportSubmitted', { decodeForAbi: baseOracleAbi }) + assert.emits(tx1, 'ReportSubmitted', {}, { abi: baseOracleAbi }) const tx2 = await consensus.submitReportAsConsensus( HASH_1, initialRefSlot + 20, initialRefSlot + SLOTS_PER_FRAME ) - assertEvent(tx2, 'WarnProcessingMissed', { - decodeForAbi: baseOracleAbi, - expectedArgs: { refSlot: initialRefSlot + 10 } - }) + assert.emits( + tx2, + 'WarnProcessingMissed', + { refSlot: initialRefSlot + 10 }, + { + abi: baseOracleAbi + } + ) assert.equal(+(await baseOracle.getConsensusReportLastCall()).callCount, 3) - assertEvent(tx2, 'ReportSubmitted', { decodeForAbi: baseOracleAbi }) + assert.emits(tx2, 'ReportSubmitted', {}, { abi: baseOracleAbi }) }) }) @@ -93,8 +98,8 @@ contract('BaseOracle', ([admin]) => { it('getConsensusReport at deploy returns empty state', async () => { const report = await baseOracle.getConsensusReport() assert.equal(report.hash, ZERO_HASH) - assertBn(report.refSlot, bn(0)) - assertBn(report.processingDeadlineTime, bn(0)) + assert.equals(report.refSlot, 0) + assert.equals(report.processingDeadlineTime, 0) assert(!report.processingStarted) }) @@ -102,36 +107,39 @@ contract('BaseOracle', ([admin]) => { await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_1) - assertBn(report.refSlot, bn(initialRefSlot)) - assertBn(report.processingDeadlineTime, bn(initialRefSlot + SLOTS_PER_FRAME)) + assert.equals(report.refSlot, initialRefSlot) + assert.equals(report.processingDeadlineTime, initialRefSlot + SLOTS_PER_FRAME) assert(!report.processingStarted) }) it('next report is submitted, initial report is missed, warning event fired', async () => { const nextRefSlot = initialRefSlot + 1 const tx = await consensus.submitReportAsConsensus(HASH_2, nextRefSlot, nextRefSlot + SLOTS_PER_FRAME) - assertEvent(tx, 'WarnProcessingMissed', { - decodeForAbi: baseOracleAbi, - expectedArgs: { refSlot: initialRefSlot } - }) + assert.emits( + tx, + 'WarnProcessingMissed', + { + refSlot: initialRefSlot + }, + { abi: baseOracleAbi } + ) const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_2) - assertBn(report.refSlot, bn(nextRefSlot)) - assertBn(report.processingDeadlineTime, bn(nextRefSlot + SLOTS_PER_FRAME)) + assert.equals(report.refSlot, nextRefSlot) + assert.equals(report.processingDeadlineTime, nextRefSlot + SLOTS_PER_FRAME) assert(!report.processingStarted) }) it('next report is re-agreed, no missed warning', async () => { const nextRefSlot = initialRefSlot + 1 const tx = await consensus.submitReportAsConsensus(HASH_3, nextRefSlot, nextRefSlot + SLOTS_PER_FRAME + 10) - assertAmountOfEvents(tx, 'WarnProcessingMissed', { - decodeForAbi: baseOracleAbi, - expectedAmount: 0 + assert.emitsNumberOfEvents(tx, 'WarnProcessingMissed', 0, { + abi: baseOracleAbi }) const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_3) - assertBn(report.refSlot, bn(nextRefSlot)) - assertBn(report.processingDeadlineTime, bn(nextRefSlot + SLOTS_PER_FRAME + 10)) + assert.equals(report.refSlot, nextRefSlot) + assert.equals(report.processingDeadlineTime, nextRefSlot + SLOTS_PER_FRAME + 10) assert(!report.processingStarted) }) @@ -140,8 +148,8 @@ contract('BaseOracle', ([admin]) => { await baseOracle.startProcessing() const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_3) - assertBn(report.refSlot, bn(nextRefSlot)) - assertBn(report.processingDeadlineTime, bn(nextRefSlot + SLOTS_PER_FRAME + 10)) + assert.equals(report.refSlot, nextRefSlot) + assert.equals(report.processingDeadlineTime, nextRefSlot + SLOTS_PER_FRAME + 10) assert(report.processingStarted) }) }) From 68d7fe4fd517b60951cc446c20f33ad2dace3588 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sun, 12 Feb 2023 20:47:28 +0700 Subject: [PATCH 40/82] feat: added missing functions tests --- .../oracle/BaseOracleTimeTravellable.sol | 8 +++++ .../oracle/base-oracle-set-consensus.test.js | 29 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol index 7eb59c2b2..82f7d7981 100644 --- a/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/BaseOracleTimeTravellable.sol @@ -72,6 +72,14 @@ contract BaseOracleTimeTravellable is BaseOracle { emit MockStartProcessingResult(_res); } + function isConsensusMember(address addr) external view returns (bool) { + return _isConsensusMember(addr); + } + + function getCurrentRefSlot() external view returns (uint256) { + return _getCurrentRefSlot(); + } + function checkConsensusData(uint256 refSlot, uint256 consensusVersion, bytes32 hash) external view { _checkConsensusData(refSlot, consensusVersion, hash); } diff --git a/test/0.8.9/oracle/base-oracle-set-consensus.test.js b/test/0.8.9/oracle/base-oracle-set-consensus.test.js index 222979936..1f9621615 100644 --- a/test/0.8.9/oracle/base-oracle-set-consensus.test.js +++ b/test/0.8.9/oracle/base-oracle-set-consensus.test.js @@ -31,14 +31,13 @@ const { deployBaseOracle } = require('./base-oracle-deploy.test') - -contract('BaseOracle', ([admin, member]) => { +contract('BaseOracle', ([admin, member, notMember]) => { let consensus let baseOracle let initialRefSlot const deployContract = async () => { - const deployed = await deployBaseOracle(admin, { initialEpoch: 1 }) + const deployed = await deployBaseOracle(admin, { initialEpoch: 1, mockMember: member }) consensus = deployed.consensusContract baseOracle = deployed.oracle await baseOracle.grantRole(web3.utils.keccak256('MANAGE_CONSENSUS_CONTRACT_ROLE'), admin, { from: admin }) @@ -175,4 +174,28 @@ contract('BaseOracle', ([admin, member]) => { await baseOracle.checkConsensusData(initialRefSlot, CONSENSUS_VERSION, HASH_1) }) }) + + describe('_isConsensusMember correctly check address for consensus membership trough consensus contract', () => { + before(deployContract) + + it('returns false on non member', async () => { + const r = await baseOracle.isConsensusMember(notMember) + assert(!r) + }) + + it('returns true on member', async () => { + const r = await baseOracle.isConsensusMember(member) + assert(r) + }) + }) + + describe('_getCurrentRefSlot correctly gets refSlot trough consensus contract', () => { + before(deployContract) + + it('refSlot matches', async () => { + const oracle_slot = await baseOracle.getCurrentRefSlot() + const consensus_slot = (await consensus.getCurrentFrame()).refSlot + assert.equals(oracle_slot, consensus_slot) + }) + }) }) From 87c3398595f12be9e148a05ff904918c1abedd10 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sun, 12 Feb 2023 20:55:45 +0700 Subject: [PATCH 41/82] chore: clean up, formatting, typos --- .../oracle/base-oracle-access-control.test.js | 4 ++-- test/0.8.9/oracle/base-oracle-deploy.test.js | 9 ++++----- .../oracle/base-oracle-set-consensus.test.js | 17 ----------------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/test/0.8.9/oracle/base-oracle-access-control.test.js b/test/0.8.9/oracle/base-oracle-access-control.test.js index f2ce4b30e..640093f26 100644 --- a/test/0.8.9/oracle/base-oracle-access-control.test.js +++ b/test/0.8.9/oracle/base-oracle-access-control.test.js @@ -6,7 +6,7 @@ const { SECONDS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME, - INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_FAST_LANE_LENGTH_SLOTS, INITIAL_EPOCH, CONSENSUS_VERSION, HASH_1, @@ -56,7 +56,7 @@ contract('BaseOracle', ([admin, account1, account2, member1, member2]) => { SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_FAST_LANE_LENGTH_SLOTS, INITIAL_EPOCH, admin, { from: admin } diff --git a/test/0.8.9/oracle/base-oracle-deploy.test.js b/test/0.8.9/oracle/base-oracle-deploy.test.js index a9cdda854..e4fadd4ed 100644 --- a/test/0.8.9/oracle/base-oracle-deploy.test.js +++ b/test/0.8.9/oracle/base-oracle-deploy.test.js @@ -1,4 +1,3 @@ -const { assert } = require('chai') const { bn } = require('@aragon/contract-helpers-test') const BaseOracle = artifacts.require('BaseOracleTimeTravellable') @@ -9,7 +8,7 @@ const SECONDS_PER_SLOT = 12 const GENESIS_TIME = 100 const EPOCHS_PER_FRAME = 225 // one day const INITIAL_EPOCH = 1 -const INITIAL_FAST_LANE_LENGHT_SLOTS = 0 +const INITIAL_FAST_LANE_LENGTH_SLOTS = 0 const SECONDS_PER_EPOCH = SLOTS_PER_EPOCH * SECONDS_PER_SLOT const SECONDS_PER_FRAME = SECONDS_PER_EPOCH * EPOCHS_PER_FRAME @@ -42,7 +41,7 @@ async function deployBaseOracle( slotsPerEpoch = SLOTS_PER_EPOCH, consensusContract = null, epochsPerFrame = EPOCHS_PER_FRAME, - fastLaneLengthSlots = INITIAL_FAST_LANE_LENGHT_SLOTS, + fastLaneLengthSlots = INITIAL_FAST_LANE_LENGTH_SLOTS, initialEpoch = INITIAL_EPOCH, mockMember = admin } = {} @@ -70,7 +69,7 @@ async function deployBaseOracle( } module.exports = { - INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_FAST_LANE_LENGTH_SLOTS, INITIAL_EPOCH, SLOTS_PER_EPOCH, SECONDS_PER_SLOT, @@ -100,7 +99,7 @@ contract('BaseOracle', ([admin, member1]) => { context('Deployment and initial configuration', () => { let oracle - it('deploying base oracle', async () => { + it('deploying base oracle ', async () => { const deployed = await deployBaseOracle(admin) oracle = deployed.oracle }) diff --git a/test/0.8.9/oracle/base-oracle-set-consensus.test.js b/test/0.8.9/oracle/base-oracle-set-consensus.test.js index 1f9621615..67edc3f00 100644 --- a/test/0.8.9/oracle/base-oracle-set-consensus.test.js +++ b/test/0.8.9/oracle/base-oracle-set-consensus.test.js @@ -2,32 +2,15 @@ const { assert } = require('../../helpers/assert') const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const MockConsensusContract = artifacts.require('MockConsensusContract') -const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') - const { - INITIAL_FAST_LANE_LENGHT_SLOTS, - INITIAL_EPOCH, SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - SECONDS_PER_EPOCH, - SECONDS_PER_FRAME, SLOTS_PER_FRAME, - computeSlotAt, - computeEpochAt, - computeEpochFirstSlot, - computeEpochFirstSlotAt, - computeTimestampAtSlot, - computeTimestampAtEpoch, - ZERO_HASH, HASH_1, HASH_2, - HASH_3, - HASH_4, - HASH_5, CONSENSUS_VERSION, - UNREACHABLE_QUORUM, deployBaseOracle } = require('./base-oracle-deploy.test') From b8274a9666b1a41fe361480c7500d21ff5f7629c Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sun, 12 Feb 2023 18:31:59 +0300 Subject: [PATCH 42/82] chore: NOR chores --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index d43f79781..7ef2d73a3 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -93,15 +93,15 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { uint8 internal constant DEPOSITED_KEYS_COUNT_OFFSET = 3; // TargetValidatorsStats - /// @dev DAO target limit, used to check how many keys shoud be go to exit - /// UINT64_MAX - unlim + /// @dev DAO target limit, used to check how many keys should go to exit + /// UINT64_MAX - unlimited /// 0 - all deposited keys - /// N < deposited keys - + /// N < deposited keys - (deposited-N) keys /// deposited < N < vetted - use (N-deposited) as available uint8 internal constant IS_TARGET_LIMIT_ACTIVE_OFFSET = 0; - /// @dev relative target active validators limit for operator, set by DAO, UINT64_MAX === no limit - /// @notice stores value +1 based, so 0 is means target coun is unlimited (i.e. = -1), - /// and 1 is means target count = 0 (i.e. all validaotrs should be exited) + /// @dev relative target active validators limit for operator, set by DAO, UINT64_MAX === 'no limit' + /// @notice stores value +1 based, so 0 is means target count is unlimited (i.e. = -1), + /// and 1 is means target count = 0 (i.e. all validators should be exited) uint8 internal constant TARGET_VALIDATORS_COUNT_OFFSET = 1; // StuckPenaltyStats @@ -109,6 +109,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { uint8 internal constant STUCK_VALIDATORS_COUNT_OFFSET = 0; /// @dev refunded keys count from dao uint8 internal constant REFUNDED_VALIDATORS_COUNT_OFFSET = 1; + /// @dev extra penalty time after stuck keys resolved (refunded and/or exited) uint8 internal constant STUCK_PENALTY_END_TIMESTAMP_OFFSET = 2; // @@ -149,7 +150,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { struct NodeOperator { /// @dev Flag indicating if the operator can participate in further staking and reward distribution bool active; - /// @dev Ethereum address on Execution Layer which receives steth rewards for this operator + /// @dev Ethereum address on Execution Layer which receives stETH rewards for this operator address rewardAddress; /// @dev Human-readable name string name; @@ -179,7 +180,6 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @dev Mapping of all node operators. Mapping is used to be able to extend the struct. mapping(uint256 => NodeOperator) internal _nodeOperators; - // NodeOperatorTotals internal _nodeOperatorTotals; // // METHODS @@ -234,7 +234,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { _setContractVersion(2); // set unlimited allowance for burner from staking router - // to burn finalized requests' shares + // to burn stuck keys penalized shares IStETH(getLocator().lido()).approve(getLocator().burner(), ~uint256(0)); emit ContractVersionSet(2); @@ -319,7 +319,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { function setNodeOperatorName(uint256 _nodeOperatorId, string _name) external { _onlyValidNodeOperatorName(_name); _onlyExistedNodeOperator(_nodeOperatorId); - _authP(MANAGE_NODE_OPERATOR_ROLE, arr(uint256(_nodeOperatorId))); + _auth(MANAGE_NODE_OPERATOR_ROLE); _requireNotSameValue(keccak256(bytes(_nodeOperators[_nodeOperatorId].name)) != keccak256(bytes(_name))); _nodeOperators[_nodeOperatorId].name = _name; @@ -332,7 +332,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { function setNodeOperatorRewardAddress(uint256 _nodeOperatorId, address _rewardAddress) external { _onlyNonZeroAddress(_rewardAddress); _onlyExistedNodeOperator(_nodeOperatorId); - _authP(MANAGE_NODE_OPERATOR_ROLE, arr(uint256(_nodeOperatorId), uint256(_rewardAddress))); + _auth(MANAGE_NODE_OPERATOR_ROLE); _requireNotSameValue(_nodeOperators[_nodeOperatorId].rewardAddress != _rewardAddress); _nodeOperators[_nodeOperatorId].rewardAddress = _rewardAddress; @@ -374,6 +374,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { _auth(STAKING_ROUTER_ROLE); // since we're pushing rewards to operators after exited validators counts are // updated (as opposed to pulling by node ops), we don't need any handling here + // see `onAllValidatorCountersUpdated()` } /// @notice Called by StakingRouter to update the number of the validators of the given node @@ -892,6 +893,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { } /// @notice Returns a monotonically increasing counter that gets incremented when any of the following happens: + /// @dev DEPRECATED: use getNonce() instead /// 1. a node operator's key(s) is added; /// 2. a node operator's key(s) is removed; /// 3. a node operator's vetted keys count is changed. From 1e643f08d77c410668730a0ab9935954103becc4 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sun, 12 Feb 2023 19:13:10 +0300 Subject: [PATCH 43/82] chore: use `Versioned` for LegacyOracle --- contracts/0.4.24/oracle/LegacyOracle.sol | 32 ++++++++++-------------- lib/abi/LegacyOracle.json | 2 +- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/contracts/0.4.24/oracle/LegacyOracle.sol b/contracts/0.4.24/oracle/LegacyOracle.sol index d76bd7e03..4893ba5a1 100644 --- a/contracts/0.4.24/oracle/LegacyOracle.sol +++ b/contracts/0.4.24/oracle/LegacyOracle.sol @@ -8,6 +8,8 @@ import "@aragon/os/contracts/apps/AragonApp.sol"; import "../../common/interfaces/ILidoLocator.sol"; +import "../utils/Versioned.sol"; + interface IAccountingOracle { function getConsensusContract() external view returns (address); @@ -43,7 +45,7 @@ interface IHashConsensus { * * See docs.lido.fi for more info. */ -contract LegacyOracle is AragonApp { +contract LegacyOracle is Versioned, AragonApp { struct ChainSpec { uint64 epochsPerFrame; @@ -79,8 +81,6 @@ contract LegacyOracle is AragonApp { uint256 totalShares ); - event ContractVersionSet(uint256 version); - /// Address of the Lido contract bytes32 internal constant LIDO_POSITION = 0xf6978a4f7e200f6d3a24d82d44c48bddabce399a3b8ec42a480ea8a2d5fe6ec5; // keccak256("lido.LidoOracle.lido") @@ -93,13 +93,8 @@ contract LegacyOracle is AragonApp { bytes32 internal constant BEACON_SPEC_POSITION = 0x805e82d53a51be3dfde7cfed901f1f96f5dad18e874708b082adb8841e8ca909; // keccak256("lido.LidoOracle.beaconSpec") - /// Version of the initialized contract data - /// NB: Contract versioning starts from 1. - /// The version stored in CONTRACT_VERSION_POSITION equals to - /// - 0 right after deployment when no initializer is invoked yet - /// - N after calling initialize() during deployment from scratch, where N is the current contract version - /// - N after upgrading contract from the previous version (after calling finalize_vN()) - bytes32 internal constant CONTRACT_VERSION_POSITION = + /// Version of the initialized contract data (DEPRECATED) + bytes32 internal constant CONTRACT_VERSION_POSITION_DEPRECATED = 0x75be19a3f314d89bd1f84d30a6c84e2f1cd7afc7b6ca21876564c265113bb7e4; // keccak256("lido.LidoOracle.contractVersion") /// Historic data about 2 last completed reports and their times @@ -126,17 +121,17 @@ contract LegacyOracle is AragonApp { return ACCOUNTING_ORACLE_POSITION.getStorageAddress(); } + /// + /// Compatibility interface (DEPRECATED) + /// + /** * @notice Returns the initialized version of this contract starting from 0. */ function getVersion() external view returns (uint256) { - return CONTRACT_VERSION_POSITION.getStorageUint256(); + return getContractVersion(); } - /// - /// Compatibility interface (DEPRECATED) - /// - /** * @notice DEPRECATED, kept for compatibility purposes only. * @@ -275,7 +270,7 @@ contract LegacyOracle is AragonApp { address _accountingOracleConsensusContract ) external onlyInit { // Initializations for v0 --> v3 - require(CONTRACT_VERSION_POSITION.getStorageUint256() == 0, "BASE_VERSION_MUST_BE_ZERO"); + _checkContractVersion(0); require(_lidoLocator != address(0), "ZERO_LOCATOR_ADDRESS"); ILidoLocator locator = ILidoLocator(_lidoLocator); @@ -297,7 +292,7 @@ contract LegacyOracle is AragonApp { * Can be called only once. */ function finalizeUpgrade_v4(address _accountingOracle) external { - require(CONTRACT_VERSION_POSITION.getStorageUint256() == 3, "WRONG_BASE_VERSION"); + require(CONTRACT_VERSION_POSITION_DEPRECATED.getStorageUint256() == 3, "WRONG_BASE_VERSION"); IHashConsensus consensus = IHashConsensus(IAccountingOracle(_accountingOracle).getConsensusContract()); _initialize_v4(_accountingOracle); @@ -316,8 +311,7 @@ contract LegacyOracle is AragonApp { function _initialize_v4(address _accountingOracle) internal { require(_accountingOracle != address(0), "ZERO_ACCOUNTING_ORACLE_ADDRESS"); ACCOUNTING_ORACLE_POSITION.setStorageAddress(_accountingOracle); - CONTRACT_VERSION_POSITION.setStorageUint256(4); - emit ContractVersionSet(4); + _setContractVersion(4); } function _getChainSpec() diff --git a/lib/abi/LegacyOracle.json b/lib/abi/LegacyOracle.json index 744200e4b..f43a2461f 100644 --- a/lib/abi/LegacyOracle.json +++ b/lib/abi/LegacyOracle.json @@ -1 +1 @@ -[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_accountingOracleConsensusContract","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_accountingOracle","type":"address"}],"name":"finalizeUpgrade_v4","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getLastCompletedReportDelta","outputs":[{"name":"postTotalPooledEther","type":"uint256"},{"name":"preTotalPooledEther","type":"uint256"},{"name":"timeElapsed","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLido","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentFrame","outputs":[{"name":"frameEpochId","type":"uint256"},{"name":"frameStartTime","type":"uint256"},{"name":"frameEndTime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"","type":"uint256"},{"name":"timeElapsed","type":"uint256"},{"name":"","type":"uint256"},{"name":"preTotalEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"postTotalEther","type":"uint256"},{"name":"","type":"uint256"}],"name":"handlePostTokenRebase","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getLastCompletedEpochId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_refSlot","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_clValidators","type":"uint256"}],"name":"handleConsensusLayerReport","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getAccountingOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentEpochId","outputs":[{"name":"epochId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconSpec","outputs":[{"name":"epochsPerFrame","type":"uint64"},{"name":"slotsPerEpoch","type":"uint64"},{"name":"secondsPerSlot","type":"uint64"},{"name":"genesisTime","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"epochId","type":"uint256"},{"indexed":false,"name":"beaconBalance","type":"uint128"},{"indexed":false,"name":"beaconValidators","type":"uint128"}],"name":"Completed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"postTotalPooledEther","type":"uint256"},{"indexed":false,"name":"preTotalPooledEther","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"totalShares","type":"uint256"}],"name":"PostTotalShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_accountingOracleConsensusContract","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_accountingOracle","type":"address"}],"name":"finalizeUpgrade_v4","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getLastCompletedReportDelta","outputs":[{"name":"postTotalPooledEther","type":"uint256"},{"name":"preTotalPooledEther","type":"uint256"},{"name":"timeElapsed","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLido","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentFrame","outputs":[{"name":"frameEpochId","type":"uint256"},{"name":"frameStartTime","type":"uint256"},{"name":"frameEndTime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"","type":"uint256"},{"name":"timeElapsed","type":"uint256"},{"name":"","type":"uint256"},{"name":"preTotalEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"postTotalEther","type":"uint256"},{"name":"","type":"uint256"}],"name":"handlePostTokenRebase","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getLastCompletedEpochId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_refSlot","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_clValidators","type":"uint256"}],"name":"handleConsensusLayerReport","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getAccountingOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentEpochId","outputs":[{"name":"epochId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconSpec","outputs":[{"name":"epochsPerFrame","type":"uint64"},{"name":"slotsPerEpoch","type":"uint64"},{"name":"secondsPerSlot","type":"uint64"},{"name":"genesisTime","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"epochId","type":"uint256"},{"indexed":false,"name":"beaconBalance","type":"uint128"},{"indexed":false,"name":"beaconValidators","type":"uint128"}],"name":"Completed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"postTotalPooledEther","type":"uint256"},{"indexed":false,"name":"preTotalPooledEther","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"totalShares","type":"uint256"}],"name":"PostTotalShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"}] \ No newline at end of file From fcbbb9ebc948d581ab278bf16b1e39279af2e312 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sun, 12 Feb 2023 19:27:42 +0300 Subject: [PATCH 44/82] fix: remove reduntant bunker check on deposit --- contracts/0.4.24/Lido.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 912f8dcc9..45e1b187d 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -642,7 +642,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { require(canDeposit(), "CAN_NOT_DEPOSIT"); IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(locator.withdrawalQueue()); - require(!withdrawalQueue.isBunkerModeActive(), "CANT_DEPOSIT_IN_BUNKER_MODE"); uint256 bufferedEth = _getBufferedEther(); // we dont deposit funds that will go to withdrawals From 41ea87a296328601e21002d16365bd563f9a321b Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sun, 12 Feb 2023 20:33:24 +0300 Subject: [PATCH 45/82] feat: sanity check on EL rewards vault balance --- contracts/0.4.24/Lido.sol | 33 ++++++++++++++----- .../OracleReportSanityChecker.sol | 23 ++++++++++--- .../OracleReportSanityCheckerMocks.sol | 9 ++++- lib/abi/OracleReportSanityChecker.json | 2 +- .../oracle-report-sanity-checker.test.js | 20 ++++++++--- 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 45e1b187d..8fd09efcc 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -35,6 +35,7 @@ interface IOracleReportSanityChecker { uint256 _preCLBalance, uint256 _postCLBalance, uint256 _withdrawalVaultBalance, + uint256 _elRewardsVaultBalance, uint256 _preCLValidators, uint256 _postCLValidators ) external view; @@ -1171,18 +1172,12 @@ contract Lido is Versioned, StETHPermit, AragonApp { reportContext.preTotalShares = _getTotalShares(); reportContext.preCLValidators = CL_VALIDATORS_POSITION.getStorageUint256(); reportContext.preCLBalance = _processClStateUpdate( - reportContext.preCLValidators, _reportedData.clValidators, _reportedData.postCLBalance); + reportContext.preCLValidators, _reportedData.clValidators, _reportedData.postCLBalance + ); // Step 2. // Pass the report data to sanity checker (reverts if malformed) - IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkAccountingOracleReport( - _reportedData.timeElapsed, - reportContext.preCLBalance, - _reportedData.postCLBalance, - _reportedData.withdrawalVaultBalance, - reportContext.preCLValidators, - _reportedData.clValidators - ); + _checkAccountingOracleReport(_contracts, _reportedData, reportContext); // Step 3. // Pre-calculate the ether to lock for withdrawal queue and shares to be burnt @@ -1271,6 +1266,26 @@ contract Lido is Versioned, StETHPermit, AragonApp { } } + /** + * @dev Pass the provided oracle data to the sanity checker contract + * Works with structures to overcome `stack too deep` + */ + function _checkAccountingOracleReport( + OracleReportContracts memory _contracts, + OracleReportedData memory _reportedData, + OracleReportContext memory _reportContext + ) internal view { + IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkAccountingOracleReport( + _reportedData.timeElapsed, + _reportContext.preCLBalance, + _reportedData.postCLBalance, + _reportedData.withdrawalVaultBalance, + _reportedData.elRewardsVaultBalance, + _reportContext.preCLValidators, + _reportedData.clValidators + ); + } + /** * @dev Notify observers about the completed token rebase. * Emit events and call external receivers. diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 7722fea1d..c3651df3c 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -338,6 +338,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { /// @param _postCLBalance sum of all Lido validators' balances on the Consensus Layer after the /// current oracle report /// @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer for report block + /// @param _elRewardsVaultBalance el rewards vault balance on Execution Layer for report block /// @param _preCLValidators Lido-participating validators on the CL side before the current oracle report /// @param _postCLValidators Lido-participating validators on the CL side after the current oracle report function checkAccountingOracleReport( @@ -345,22 +346,27 @@ contract OracleReportSanityChecker is AccessControlEnumerable { uint256 _preCLBalance, uint256 _postCLBalance, uint256 _withdrawalVaultBalance, + uint256 _elRewardsVaultBalance, uint256 _preCLValidators, uint256 _postCLValidators ) external view { LimitsList memory limitsList = _limits.unpack(); address withdrawalVault = LIDO_LOCATOR.withdrawalVault(); - // 1. Withdrawals vault one-off reported balance + // 1. Withdrawals vault reported balance _checkWithdrawalVaultBalance(withdrawalVault.balance, _withdrawalVaultBalance); - // 2. Consensus Layer one-off balance decrease + address elRewardsVault = LIDO_LOCATOR.elRewardsVault(); + // 2. EL rewards vault reported balance + _checkELRewardsVaultBalance(elRewardsVault.balance, _elRewardsVaultBalance); + + // 3. Consensus Layer one-off balance decrease _checkOneOffCLBalanceDecrease(limitsList, _preCLBalance, _postCLBalance + _withdrawalVaultBalance); - // 3. Consensus Layer annual balances increase + // 4. Consensus Layer annual balances increase _checkAnnualBalancesIncrease(limitsList, _preCLBalance, _postCLBalance, _timeElapsed); - // 4. Appeared validators increase + // 5. Appeared validators increase if (_postCLValidators > _preCLValidators) { _checkValidatorsChurnLimit(limitsList, (_postCLValidators - _preCLValidators), _timeElapsed); } @@ -453,6 +459,14 @@ contract OracleReportSanityChecker is AccessControlEnumerable { revert IncorrectWithdrawalsVaultBalance(_actualWithdrawalVaultBalance); } + function _checkELRewardsVaultBalance( + uint256 _actualELRewardsVaultBalance, + uint256 _reportedELRewardsVaultBalance + ) internal pure { + if (_reportedELRewardsVaultBalance > _actualELRewardsVaultBalance) + revert IncorrectELRewardsVaultBalance(_actualELRewardsVaultBalance); + } + function _checkOneOffCLBalanceDecrease( LimitsList memory _limitsList, uint256 _preCLBalance, @@ -585,6 +599,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { event MaxAccountingExtraDataListItemsCountSet(uint256 maxAccountingExtraDataListItemsCount); error IncorrectWithdrawalsVaultBalance(uint256 actualWithdrawalVaultBalance); + error IncorrectELRewardsVaultBalance(uint256 actualELRewardsVaultBalance); error IncorrectCLBalanceDecrease(uint256 oneOffCLBalanceDecreaseBP); error IncorrectCLBalanceIncrease(uint256 annualBalanceDiff); error IncorrectAppearedValidators(uint256 churnLimit); diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index 7c1eef4d5..d15c7796a 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -51,15 +51,18 @@ contract LidoLocatorStub is ILidoLocator { address private immutable LIDO; address private immutable WITHDRAWAL_VAULT; address private immutable WITHDRAWAL_QUEUE; + address private immutable EL_REWARDS_VAULT; constructor( address _lido, address _withdrawalVault, - address _withdrawalQueue + address _withdrawalQueue, + address _elRewardsVault ) { LIDO = _lido; WITHDRAWAL_VAULT = _withdrawalVault; WITHDRAWAL_QUEUE = _withdrawalQueue; + EL_REWARDS_VAULT = _elRewardsVault; } function lido() external view returns (address) { @@ -73,6 +76,10 @@ contract LidoLocatorStub is ILidoLocator { function withdrawalVault() external view returns (address) { return WITHDRAWAL_VAULT; } + + function elRewardsVault() external view returns (address) { + return EL_REWARDS_VAULT; + } } contract OracleReportSanityCheckerStub { diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index 3fdf5f2ee..fb15c9566 100644 --- a/lib/abi/OracleReportSanityChecker.json +++ b/lib/abi/OracleReportSanityChecker.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkAccountingOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_noWithdrawalsPostTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_noWithdrawalsPostTotalShares","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"checkSimulatedShareRate","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualELRewardsVaultBalance","type":"uint256"}],"name":"IncorrectELRewardsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkAccountingOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_noWithdrawalsPostTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_noWithdrawalsPostTotalShares","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"checkSimulatedShareRate","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/test/0.8.9/oracle-report-sanity-checker.test.js b/test/0.8.9/oracle-report-sanity-checker.test.js index fe9c1f26d..09b6948c5 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -19,7 +19,7 @@ function wei(number, units = 'wei') { throw new Error(`Unsupported units "${units}"`) } -contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...accounts]) => { +contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewardsVault, ...accounts]) => { let oracleReportSanityChecker, lidoLocatorMock, lidoMock, withdrawalQueueMock const managersRoster = { allLimitsManagers: accounts.slice(0, 2), @@ -47,6 +47,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc preCLBalance: ETH(100_000), postCLBalance: ETH(100_001), withdrawalVaultBalance: 0, + elRewardsVaultBalance: 0, preCLValidators: 0, postCLValidators: 0, } @@ -56,9 +57,10 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc await hre.ethers.provider.send('hardhat_mine', ['0x' + Number(1024).toString(16), '0x' + Number(12).toString(16)]) lidoMock = await LidoStub.new({ from: deployer }) withdrawalQueueMock = await WithdrawalQueueStub.new({ from: deployer }) - lidoLocatorMock = await LidoLocatorStub.new(lidoMock.address, withdrawalVault, withdrawalQueueMock.address, { - from: deployer - }) + lidoLocatorMock = await LidoLocatorStub.new( + lidoMock.address, withdrawalVault, withdrawalQueueMock.address, elRewardsVault, + { from: deployer } + ) oracleReportSanityChecker = await OracleReportSanityChecker.new( lidoLocatorMock.address, @@ -126,6 +128,16 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, ...acc ) }) + it('reverts with error IncorrectELRewardsVaultBalance() when actual el rewards vault balance is less than passed', async () => { + const currentELRewardsVaultBalance = await hre.ethers.provider.getBalance(elRewardsVault) + await assert.revertsWithCustomError( + oracleReportSanityChecker.checkAccountingOracleReport( + ...Object.values({ ...correctLidoOracleReport, elRewardsVaultBalance: currentELRewardsVaultBalance.add(1) }) + ), + `IncorrectELRewardsVaultBalance(${currentELRewardsVaultBalance.toString()})` + ) + }) + it('reverts with error IncorrectCLBalanceDecrease() when one off CL balance decrease more than limit', async () => { const maxBasisPoints = 10_000n const preCLBalance = wei(100_000, 'eth') From 718c3595f4e1c038c91585fd430e6fa61714b314 Mon Sep 17 00:00:00 2001 From: ujenjt Date: Sun, 12 Feb 2023 20:24:34 +0100 Subject: [PATCH 46/82] refactor: move sanity check out of while loop for optimizing gas usage --- contracts/0.8.9/oracle/AccountingOracle.sol | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index e7f5c97a1..048f40beb 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -683,6 +683,8 @@ contract AccountingOracle is BaseOracle { function _processExtraDataItems(bytes calldata data, ExtraDataIterState memory iter) internal { uint256 dataOffset = iter.dataOffset; + uint256 maxNodeOperatorsPerItem = 0; + uint256 maxNodeOperatorItemIndex = 0; /// @solidity memory-safe-assembly while (dataOffset < data.length) { @@ -714,7 +716,12 @@ contract AccountingOracle is BaseOracle { if (itemType == EXTRA_DATA_TYPE_EXITED_VALIDATORS || itemType == EXTRA_DATA_TYPE_STUCK_VALIDATORS ) { - _processExtraDataItem(data, iter); + uint256 nodeOpsProcessed = _processExtraDataItem(data, iter); + + if (nodeOpsProcessed > maxNodeOperatorsPerItem) { + maxNodeOperatorsPerItem = nodeOpsProcessed; + maxNodeOperatorItemIndex = index; + } } else { revert UnsupportedExtraDataType(index, itemType); } @@ -722,9 +729,14 @@ contract AccountingOracle is BaseOracle { assert(iter.dataOffset > dataOffset); dataOffset = iter.dataOffset; } + + if (maxNodeOperatorsPerItem > 0) { + IOracleReportSanityChecker(LOCATOR.oracleReportSanityChecker()) + .checkNodeOperatorsPerExtraDataItemCount(maxNodeOperatorItemIndex, maxNodeOperatorsPerItem); + } } - function _processExtraDataItem(bytes calldata data, ExtraDataIterState memory iter) internal { + function _processExtraDataItem(bytes calldata data, ExtraDataIterState memory iter) internal returns (uint256 nodeOpsProcessed) { uint256 dataOffset = iter.dataOffset; uint256 moduleId; uint256 nodeOpsCount; @@ -772,9 +784,6 @@ contract AccountingOracle is BaseOracle { revert InvalidExtraDataItem(iter.index); } - IOracleReportSanityChecker(LOCATOR.oracleReportSanityChecker()) - .checkNodeOperatorsPerExtraDataItemCount(iter.index, nodeOpsCount); - if (iter.itemType == EXTRA_DATA_TYPE_STUCK_VALIDATORS) { IStakingRouter(iter.stakingRouter) .reportStakingModuleStuckValidatorsCountByNodeOperator(moduleId, nodeOpIds, valsCounts); @@ -784,6 +793,7 @@ contract AccountingOracle is BaseOracle { } iter.dataOffset = dataOffset; + return nodeOpsCount; } /// From a0b636a84ba095d202c3ded3e42e6661d48e35c9 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sun, 12 Feb 2023 23:35:31 +0300 Subject: [PATCH 47/82] fix: OracleDaemonConfig empty value + tests --- contracts/0.8.9/OracleDaemonConfig.sol | 2 + lib/abi/OracleDaemonConfig.json | 2 +- test/0.8.9/oracle-daemon-config.test.js | 81 +++++++++++++++++++------ 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/contracts/0.8.9/OracleDaemonConfig.sol b/contracts/0.8.9/OracleDaemonConfig.sol index e2dc813f9..04aa7b88f 100644 --- a/contracts/0.8.9/OracleDaemonConfig.sol +++ b/contracts/0.8.9/OracleDaemonConfig.sol @@ -36,6 +36,7 @@ contract OracleDaemonConfig is AccessControlEnumerable { function update(string calldata _key, bytes calldata _value) external onlyRole(CONFIG_MANAGER_ROLE) { if (values[_key].length == 0) revert ErrorValueDoesntExist(_key); + if (_value.length == 0) revert ErrorEmptyValue(_key); values[_key] = _value; emit ConfigValueUpdated(_key, _value); @@ -71,6 +72,7 @@ contract OracleDaemonConfig is AccessControlEnumerable { } error ErrorValueExists(string key); + error ErrorEmptyValue(string key); error ErrorValueDoesntExist(string key); error ErrorZeroAddress(); diff --git a/lib/abi/OracleDaemonConfig.json b/lib/abi/OracleDaemonConfig.json index 2f95a3bbb..1bdff7035 100644 --- a/lib/abi/OracleDaemonConfig.json +++ b/lib/abi/OracleDaemonConfig.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address[]","name":"_configManagers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorValueDoesntExist","type":"error"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorValueExists","type":"error"},{"inputs":[],"name":"ErrorZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"ConfigValueUnset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"CONFIG_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"get","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"_keys","type":"string[]"}],"name":"getList","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"unset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address[]","name":"_configManagers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorEmptyValue","type":"error"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorValueDoesntExist","type":"error"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorValueExists","type":"error"},{"inputs":[],"name":"ErrorZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"ConfigValueUnset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"CONFIG_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"get","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"_keys","type":"string[]"}],"name":"getList","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"unset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/test/0.8.9/oracle-daemon-config.test.js b/test/0.8.9/oracle-daemon-config.test.js index 4025be7a6..0142972c9 100644 --- a/test/0.8.9/oracle-daemon-config.test.js +++ b/test/0.8.9/oracle-daemon-config.test.js @@ -1,5 +1,4 @@ const hre = require('hardhat') -const { keccak256 } = require('js-sha3') const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const { assert } = require('../helpers/assert') @@ -31,7 +30,7 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { it('gets a value', async () => { const value = await config.get(defaultKey) - + assert.equal(defaultValue, value) }) @@ -57,11 +56,11 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { it('removes a value', async () => { await config.unset(defaultKey, { from: manager }) - assert.reverts(config.get(defaultKey)) + await assert.reverts(config.get(defaultKey)) }) it('reverts while gets all values', async () => { - assert.reverts(config.getList([defaultKey]), `ErrorValueDoesntExist(${defaultKey})`) + await assert.revertsWithCustomError(config.getList([defaultKey]), `ErrorValueDoesntExist("${defaultKey}")`) }) }) @@ -71,24 +70,44 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { }) it("reverts when defaultValue for update doesn't exist", async () => { - assert.reverts(config.update(defaultKey, defaultValue, { from: manager }), `ErrorValueDoesntExist(${defaultKey})`) + await assert.revertsWithCustomError( + config.update(defaultKey, defaultValue, { from: manager }), + `ErrorValueDoesntExist("${defaultKey}")` + ) }) it("reverts when defaultValue for unset doen't exist", async () => { - assert.reverts(config.unset(defaultKey, { from: manager }), `ErrorValueDoesntExist(${defaultKey})`) + await assert.revertsWithCustomError( + config.unset(defaultKey, { from: manager }), + `ErrorValueDoesntExist("${defaultKey}")` + ) }) it('reverts when defaultValue for set already exists', async () => { await config.set(defaultKey, defaultValue, { from: manager }) - assert.reverts(config.set(defaultKey, updatedDefaultValue, { from: manager }), `ErrorValueExists(${defaultKey})`) + await assert.revertsWithCustomError( + config.set(defaultKey, updatedDefaultValue, { from: manager }), + `ErrorValueExists("${defaultKey}")` + ) }) it('reverts when admin is zero address', async () => { - assert.reverts(OracleDaemonConfig.new(ZERO_ADDRESS, [manager], { from: deployer }), 'ErrorZeroAddress()') + await assert.revertsWithCustomError( + OracleDaemonConfig.new(ZERO_ADDRESS, [manager], { from: deployer }), + 'ErrorZeroAddress()' + ) }) it('reverts when one of managers is zero address', async () => { - assert.reverts(OracleDaemonConfig.new(deployer, [manager, ZERO_ADDRESS], { from: deployer }), 'ErrorZeroAddress()') + await assert.revertsWithCustomError(OracleDaemonConfig.new(deployer, [manager, ZERO_ADDRESS], { from: deployer }), 'ErrorZeroAddress()') + }) + + it('revers when empty value passed to update', async () => { + await config.set(defaultKey, defaultValue, { from: manager }) + await assert.revertsWithCustomError( + config.update(defaultKey, '0x', { from: manager }), + `ErrorEmptyValue("${defaultKey}")` + ) }) }) @@ -98,31 +117,55 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { }) it('stranger cannot set a defaultValue', async () => { - assert.reverts(config.set(defaultKey, defaultValue, { from: stranger })) + await assert.revertsOZAccessControl( + config.set(defaultKey, defaultValue, { from: stranger }), + stranger, + `CONFIG_MANAGER_ROLE` + ) }) - it('admin cannot set a defaultValue', async () => { - assert.reverts(config.set(defaultKey, defaultValue, { from: deployer })) + it('deployer cannot set a defaultValue', async () => { + await assert.revertsOZAccessControl( + config.set(defaultKey, defaultValue, { from: deployer }), + deployer, + `CONFIG_MANAGER_ROLE` + ) }) it('stranger cannot update a defaultValue', async () => { await config.set(defaultKey, defaultValue, { from: manager }) - assert.reverts(config.update(defaultKey, updatedDefaultValue, { from: stranger })) + await assert.revertsOZAccessControl( + config.update(defaultKey, updatedDefaultValue, { from: stranger }), + stranger, + `CONFIG_MANAGER_ROLE` + ) }) - it('admin cannot update a defaultValue', async () => { + it('deployer cannot update a defaultValue', async () => { await config.set(defaultKey, defaultValue, { from: manager }) - assert.reverts(config.update(defaultKey, updatedDefaultValue, { from: deployer })) + await assert.revertsOZAccessControl( + config.update(defaultKey, updatedDefaultValue, { from: deployer }), + deployer, + `CONFIG_MANAGER_ROLE` + ) }) - it('stranger cannot unset a defaultValue', async () => { + it('deployer cannot unset a defaultValue', async () => { await config.set(defaultKey, defaultValue, { from: manager }) - assert.reverts(config.unset(defaultKey, { from: stranger })) + await assert.revertsOZAccessControl( + config.unset(defaultKey, { from: deployer }), + deployer, + `CONFIG_MANAGER_ROLE` + ) }) - it('stranger cannot unset a defaultValue', async () => { + it('deployer cannot unset a defaultValue', async () => { await config.set(defaultKey, defaultValue, { from: manager }) - assert.reverts(config.unset(defaultKey, { from: deployer })) + assert.revertsOZAccessControl( + config.unset(defaultKey, { from: deployer }), + deployer, + `CONFIG_MANAGER_ROLE` + ) }) }) }) From bdbe1d62fcc7d4c2ad1ad47a871e7923d205cb5d Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Mon, 13 Feb 2023 05:48:37 +0300 Subject: [PATCH 48/82] test fixes --- test/0.4.24/lido.rewards-distribution.test.js | 108 --------------- test/0.4.24/lido.test.js | 55 +------- .../node-operators-registry-penalty.test.js | 50 +++---- test/0.4.24/steth.test.js | 3 - test/0.8.9/oracle/hash-consensus-frames.js | 5 +- test/deposit.test.js | 14 +- test/helpers/blockchain.js | 1 + test/helpers/locator-deploy.js | 7 +- test/helpers/oracle.js | 2 +- test/scenario/deposit_distribution.js | 2 +- test/scenario/lido_happy_path.js | 34 +++-- test/scenario/lido_penalties_slashing.js | 18 ++- .../lido_rewards_distribution_math.js | 123 +++++++++++------- 13 files changed, 154 insertions(+), 268 deletions(-) delete mode 100644 test/0.4.24/lido.rewards-distribution.test.js diff --git a/test/0.4.24/lido.rewards-distribution.test.js b/test/0.4.24/lido.rewards-distribution.test.js deleted file mode 100644 index 959babeae..000000000 --- a/test/0.4.24/lido.rewards-distribution.test.js +++ /dev/null @@ -1,108 +0,0 @@ -const hre = require('hardhat') - -const { ZERO_ADDRESS, bn } = require('@aragon/contract-helpers-test') - -const { EvmSnapshot } = require('../helpers/blockchain') -const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') -const { deployProtocol } = require('../helpers/protocol') -const { assert } = require('../helpers/assert') -const { pushOracleReport } = require('../helpers/oracle') - -const ModuleSolo = artifacts.require('ModuleSolo.sol') - -const ETH = (value) => web3.utils.toWei(value + '', 'ether') -contract('Lido: staking router reward distribution', ([depositor, user2]) => { - let app, oracle, curatedModule, stakingRouter, soloModule, snapshot, appManager, consensus, treasury - - - before(async () => { - const deployed = await deployProtocol({ - stakingModulesFactory: async (protocol) => { - const curatedModule = await setupNodeOperatorsRegistry(protocol, true) - const soloModule = await ModuleSolo.new(protocol.pool.address, { from: protocol.appManager.address }) - return [ - { - module: curatedModule, - name: 'Curated', - targetShares: 10000, - moduleFee: 500, - treasuryFee: 500 - }, - { - module: soloModule, - name: 'Curated', - targetShares: 5000, - moduleFee: 566, - treasuryFee: 123 - } - ] - } - }) - - app = deployed.pool - stakingRouter = deployed.stakingRouter - curatedModule = deployed.stakingModules[0] - soloModule = deployed.stakingModules[1] - consensus = deployed.consensusContract - oracle = deployed.oracle - appManager = deployed.appManager.address - treasury = deployed.treasury.address - - await curatedModule.increaseTotalSigningKeysCount(500_000, { from: appManager }) - await curatedModule.increaseDepositedSigningKeysCount(499_950, { from: appManager }) - await curatedModule.increaseVettedSigningKeysCount(499_950, { from: appManager }) - - await soloModule.setTotalVettedValidators(100, { from: appManager }) - await soloModule.setTotalDepositedValidators(10, { from: appManager }) - await soloModule.setTotalExitedValidators(0, { from: appManager }) - - snapshot = new EvmSnapshot(hre.ethers.provider) - await snapshot.make() - }) - - afterEach(async () => { - await snapshot.rollback() - }) - - it('Rewards distribution fills treasury', async () => { - const beaconBalance = ETH(1) - const { stakingModuleFees, totalFee, precisionPoints } = await stakingRouter.getStakingRewardsDistribution() - const treasuryShare = stakingModuleFees.reduce((total, share) => total.sub(share), totalFee) - const treasuryRewards = bn(beaconBalance).mul(treasuryShare).div(precisionPoints) - await app.submit(ZERO_ADDRESS, { from: user2, value: ETH(32) }) - - const treasuryBalanceBefore = await app.balanceOf(treasury) - await pushOracleReport(consensus, oracle, 0, beaconBalance) - - const treasuryBalanceAfter = await app.balanceOf(treasury) - assert(treasuryBalanceAfter.gt(treasuryBalanceBefore)) - assert.equals(fixRound(treasuryBalanceBefore.add(treasuryRewards)), fixRound(treasuryBalanceAfter)) - }) - - it('Rewards distribution fills modules', async () => { - const beaconBalance = ETH(1) - const { recipients, stakingModuleFees, precisionPoints } = await stakingRouter.getStakingRewardsDistribution() - - await app.submit(ZERO_ADDRESS, { from: user2, value: ETH(32) }) - - const moduleBalanceBefore = [] - for (let i = 0; i < recipients.length; i++) { - moduleBalanceBefore.push(await app.balanceOf(recipients[i])) - } - - await pushOracleReport(consensus, oracle, 0, beaconBalance) - - for (let i = 0; i < recipients.length; i++) { - const moduleBalanceAfter = await app.balanceOf(recipients[i]) - const moduleRewards = bn(beaconBalance).mul(stakingModuleFees[i]).div(precisionPoints) - assert(moduleBalanceAfter.gt(moduleBalanceBefore[i])) - assert.equals(fixRound(moduleBalanceBefore[i].add(moduleRewards)), fixRound(moduleBalanceAfter)) - } - }) -}) - -function fixRound(n) { - const _fix = bn(5) // +/- 5wei - const _base = bn(10) - return n.add(_fix).div(_base).mul(_base) -} diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index ab6c348d6..d220c0d17 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -49,7 +49,7 @@ async function getTimestamp() { return block.timestamp; } -contract('Lido', ([appManager, user1, user2, user3, nobody, depositor, treasury]) => { +contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody, depositor, treasury]) => { let app, oracle, depositContract, operators let treasuryAddress let dao @@ -470,57 +470,6 @@ contract('Lido', ([appManager, user1, user2, user3, nobody, depositor, treasury] }) }) - // TODO: check if reverts are checked in Staking Router tests and remove this test from here - it.skip('setModulesFee works', async () => { - const [curated] = await stakingRouter.getStakingModules() - - let module1 = await stakingRouter.getStakingModule(curated.id) - assertBn(module1.targetShare, 10000) - assertBn(module1.stakingModuleFee, 500) - assertBn(module1.treasuryFee, 500) - - // stakingModuleId, targetShare, stakingModuleFee, treasuryFee - await stakingRouter.updateStakingModule(module1.id, module1.targetShare, 300, 700, { from: voting }) - - module1 = await stakingRouter.getStakingModule(curated.id) - - await assertRevert( - stakingRouter.updateStakingModule(module1.id, module1.targetShare, 300, 700, { from: user1 }), - `AccessControl: account ${user1.toLowerCase()} is missing role ${await stakingRouter.STAKING_MODULE_MANAGE_ROLE()}` - ) - - await assertRevert( - stakingRouter.updateStakingModule(module1.id, module1.targetShare, 300, 700, { from: nobody }), - `AccessControl: account ${nobody.toLowerCase()} is missing role ${await stakingRouter.STAKING_MODULE_MANAGE_ROLE()}` - ) - - await assert.revertsWithCustomError( - stakingRouter.updateStakingModule(module1.id, 10001, 300, 700, { from: voting }), - 'ErrorValueOver100Percent("_targetShare")' - ) - - await assert.revertsWithCustomError( - stakingRouter.updateStakingModule(module1.id, 10000, 10001, 700, { from: voting }), - 'ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee")' - ) - - await assert.revertsWithCustomError( - stakingRouter.updateStakingModule(module1.id, 10000, 300, 10001, { from: voting }), - 'ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee")' - ) - - // distribution fee calculates on active keys in modules - const depositAmount = 32 - await setupNodeOperatorsForELRewardsVaultTests(user2, ETH(depositAmount)) - - const {totalFee} = await app.getFee() - assertBn(totalFee, toPrecBP(1000)) - - const distribution = await app.getFeeDistribution({ from: nobody }) - assertBn(distribution.modulesFee, toPrecBP(300)) - assertBn(distribution.treasuryFee, toPrecBP(700)) - }) - it('setWithdrawalCredentials works', async () => { await stakingRouter.setWithdrawalCredentials(pad('0x0202', 32), { from: voting }) @@ -990,7 +939,7 @@ contract('Lido', ([appManager, user1, user2, user3, nobody, depositor, treasury] await web3.eth.sendTransaction({ to: app.address, from: user3, value: ETH(33) }) await app.methods['deposit(uint256,uint256,bytes)'](MAX_DEPOSITS, CURATED_MODULE_ID, CALLDATA, { from: depositor }) assertBn(await depositContract.totalCalls(), 1) - await assertRevert(operators.removeSigningKey(0, 0, { from: voting }), 'KEY_WAS_USED') + await assertRevert(operators.removeSigningKey(0, 0, { from: voting }), 'OUT_OF_RANGE') assertBn(await app.getBufferedEther(), ETH(1)) diff --git a/test/0.4.24/node-operators-registry-penalty.test.js b/test/0.4.24/node-operators-registry-penalty.test.js index 140b3ed7c..9e08c4e92 100644 --- a/test/0.4.24/node-operators-registry-penalty.test.js +++ b/test/0.4.24/node-operators-registry-penalty.test.js @@ -156,7 +156,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use ]) // calls distributeRewards() inside - await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + await app.testing__distributeRewards({ from: voting }) const recipientsSharesAfter = await Promise.all([ steth.sharesOf(user1), @@ -174,7 +174,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.mintShares(app.address, ETH(10)) // calls distributeRewards() inside - await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + await app.testing__distributeRewards({ from: voting }) assert.equals(await steth.sharesOf(user1), ETH(3)) assert.equals(await steth.sharesOf(user2), ETH(7)) @@ -186,7 +186,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.mintShares(app.address, ETH(10)) // calls distributeRewards() inside - receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + receipt = await app.testing__distributeRewards({ from: voting }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(3) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(7) }) @@ -210,8 +210,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use //perValidatorShare 10*10^18 / 10 = 10^18 //update [operator, exited, stuck] - await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 1, 0 , { from: voting }) - await app.unsafeUpdateValidatorsKeysCount(secondNodeOperator, 1, 0 , { from: voting }) + await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 0 , { from: voting }) + await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0 , { from: voting }) //after // operatorId | Total | Deposited | Exited | Stuck | Active (deposited-exited) @@ -224,7 +224,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use //perValidatorShare 10*10^18 / 8 = 1250000000000000000 == 1.25 * 10^18 // calls distributeRewards() inside - receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + receipt = await app.testing__distributeRewards({ from: voting }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(2*1.25) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(6*1.25) }) @@ -249,8 +249,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use //perValidatorShare 10*10^18 / 10 = 10^18 //update [operator, exited, stuck] - await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 1, 1 , { from: voting }) - await app.unsafeUpdateValidatorsKeysCount(secondNodeOperator, 1, 0 , { from: voting }) + await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 1 , { from: voting }) + await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0 , { from: voting }) //after // operatorId | Total | Deposited | Exited | Stuck | Active (deposited-exited) @@ -264,7 +264,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use // but half goes to burner // calls distributeRewards() inside - receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + receipt = await app.testing__distributeRewards({ from: voting }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(1.25) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(6*1.25) }) @@ -277,13 +277,13 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.mintShares(app.address, ETH(10)) //update [operator, exited, stuck] - await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 1, 1 , { from: voting }) - await app.unsafeUpdateValidatorsKeysCount(secondNodeOperator, 1, 0 , { from: voting }) + await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 1 , { from: voting }) + await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0 , { from: voting }) - await app.updateRefundedValidatorsKeysCount(firstNodeOperator, 1, { from: voting }) + await app.updateRefundedValidatorsCount(firstNodeOperator, 1, { from: voting }) // calls distributeRewards() inside - receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + receipt = await app.testing__distributeRewards({ from: voting }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(1.25) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(6*1.25) }) @@ -298,13 +298,13 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use //update [operator, exited, stuck] - await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 1, 1, { from: voting }) - await app.unsafeUpdateValidatorsKeysCount(secondNodeOperator, 1, 0, { from: voting }) + await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 1, { from: voting }) + await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0, { from: voting }) - await app.updateRefundedValidatorsKeysCount(firstNodeOperator, 1000, { from: voting }) + await app.updateRefundedValidatorsCount(firstNodeOperator, 1000, { from: voting }) // calls distributeRewards() inside - receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + receipt = await app.testing__distributeRewards({ from: voting }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(1.25) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(6*1.25) }) @@ -319,15 +319,15 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use //update [operator, exited, stuck] - await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 2, 2 , { from: voting }) - await app.unsafeUpdateValidatorsKeysCount(secondNodeOperator, 3, 0 , { from: voting }) + await app.unsafeUpdateValidatorsCount(firstNodeOperator, 2, 2 , { from: voting }) + await app.unsafeUpdateValidatorsCount(secondNodeOperator, 3, 0 , { from: voting }) // perValidator = ETH(10) / 5 = 2 eth - await app.updateRefundedValidatorsKeysCount(firstNodeOperator, 1, { from: voting }) + await app.updateRefundedValidatorsCount(firstNodeOperator, 1, { from: voting }) // calls distributeRewards() inside - receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + receipt = await app.testing__distributeRewards({ from: voting }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(1) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(4*2) }) @@ -344,11 +344,11 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use assert.isFalse(await app.testing_isNodeOperatorPenalized(firstNodeOperator)) //update [operator, exited, stuck] - await app.unsafeUpdateValidatorsKeysCount(firstNodeOperator, 1, 1 , { from: voting }) - await app.unsafeUpdateValidatorsKeysCount(secondNodeOperator, 1, 0 , { from: voting }) + await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 1 , { from: voting }) + await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0 , { from: voting }) assert.isTrue(await app.testing_isNodeOperatorPenalized(firstNodeOperator)) - await app.updateRefundedValidatorsKeysCount(firstNodeOperator, 1, { from: voting }) + await app.updateRefundedValidatorsCount(firstNodeOperator, 1, { from: voting }) assert.isTrue(await app.testing_isNodeOperatorPenalized(firstNodeOperator)) await hre.network.provider.send('evm_increaseTime', [2 * 24 * 60 * 60 + 10]) @@ -357,7 +357,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use assert.isFalse(await app.testing_isNodeOperatorPenalized(firstNodeOperator)) // calls distributeRewards() inside - receipt = await app.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + receipt = await app.testing__distributeRewards({ from: voting }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(2.5) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(7.5) }) diff --git a/test/0.4.24/steth.test.js b/test/0.4.24/steth.test.js index e3e3bf026..e0382776e 100644 --- a/test/0.4.24/steth.test.js +++ b/test/0.4.24/steth.test.js @@ -286,10 +286,7 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { assert(await stEth.isStopped()) await assertRevert(stEth.transfer(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') - await assertRevert(stEth.approve(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') await assertRevert(stEth.transferFrom(user2, user3, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') - await assertRevert(stEth.increaseAllowance(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') - await assertRevert(stEth.decreaseAllowance(user2, tokens(2), { from: user1 }), 'CONTRACT_IS_STOPPED') await stEth.resume({ from: user1 }) assert.equal(await stEth.isStopped(), false) diff --git a/test/0.8.9/oracle/hash-consensus-frames.js b/test/0.8.9/oracle/hash-consensus-frames.js index a7347f137..ec788d6e0 100644 --- a/test/0.8.9/oracle/hash-consensus-frames.js +++ b/test/0.8.9/oracle/hash-consensus-frames.js @@ -3,7 +3,7 @@ const { assertEvent } = require('@aragon/contract-helpers-test/src/asserts') const { assertRevert } = require('../../helpers/assertThrow') const { - INITIAL_FAST_LANE_LENGHT_SLOTS, + INITIAL_FAST_LANE_LENGTH_SLOTS, INITIAL_EPOCH, EPOCHS_PER_FRAME, SLOTS_PER_EPOCH, @@ -43,11 +43,10 @@ contract('HashConsensus', ([admin, member1, member2]) => { context('getFrameConfig', () => { before(deploy) - it('should return initial data', async () => { assert.equal(+(await consensus.getFrameConfig()).epochsPerFrame, EPOCHS_PER_FRAME) assert.equal(+(await consensus.getFrameConfig()).initialEpoch, INITIAL_EPOCH) - assert.equal(+(await consensus.getFrameConfig()).fastLaneLengthSlots, INITIAL_FAST_LANE_LENGHT_SLOTS) + assert.equal(+(await consensus.getFrameConfig()).fastLaneLengthSlots, INITIAL_FAST_LANE_LENGTH_SLOTS) }) it('should return new data', async () => { diff --git a/test/deposit.test.js b/test/deposit.test.js index e9b667f83..c5bbbc078 100644 --- a/test/deposit.test.js +++ b/test/deposit.test.js @@ -31,6 +31,13 @@ contract('Lido with official deposit contract', ([user1, user2, user3, nobody, d const deployed = await deployProtocol({ stakingModulesFactory: async (protocol) => { const curatedModule = await setupNodeOperatorsRegistry(protocol) + + await protocol.acl.grantPermission( + protocol.stakingRouter.address, + curatedModule.address, + await curatedModule.MANAGE_NODE_OPERATOR_ROLE() + ) + return [ { module: curatedModule, @@ -58,7 +65,6 @@ contract('Lido with official deposit contract', ([user1, user2, user3, nobody, d operators = deployed.stakingModules[0] voting = deployed.voting.address depositContract = deployed.depositContract - voting = deployed.voting.address snapshot = new EvmSnapshot(hre.ethers.provider) await snapshot.make() @@ -168,7 +174,7 @@ contract('Lido with official deposit contract', ([user1, user2, user3, nobody, d await app.methods[`deposit(uint256,uint256,bytes)`](MAX_DEPOSITS, CURATED_MODULE_ID, CALLDATA, { from: depositor }) assertBn(bn(changeEndianness(await depositContract.get_deposit_count())), 1) - await assert.reverts(operators.removeSigningKey(0, 0, { from: voting }), 'KEY_WAS_USED') + await assert.reverts(operators.removeSigningKey(0, 0, { from: voting }), 'OUT_OF_RANGE') await operators.removeSigningKey(0, 1, { from: voting }) @@ -176,8 +182,8 @@ contract('Lido with official deposit contract', ([user1, user2, user3, nobody, d await app.methods[`deposit(uint256,uint256,bytes)`](MAX_DEPOSITS, CURATED_MODULE_ID, CALLDATA, { from: depositor }) // deposit should go to second operator, as the first one got their key limits set to 1 - await assert.reverts(operators.removeSigningKey(1, 0, { from: voting }), 'KEY_WAS_USED') - await assert.reverts(operators.removeSigningKey(1, 1, { from: voting }), 'KEY_WAS_USED') + await assert.reverts(operators.removeSigningKey(1, 0, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts(operators.removeSigningKey(1, 1, { from: voting }), 'OUT_OF_RANGE') assertBn(bn(changeEndianness(await depositContract.get_deposit_count())), 4) assertBn(await app.getTotalPooledEther(), ETH(133)) assertBn(await app.getBufferedEther(), ETH(5)) diff --git a/test/helpers/blockchain.js b/test/helpers/blockchain.js index baf5ae570..78ab18770 100644 --- a/test/helpers/blockchain.js +++ b/test/helpers/blockchain.js @@ -3,6 +3,7 @@ async function waitBlocks(numBlocksToMine) { for (let i = 0; i < numBlocksToMine; ++i) { await network.provider.send('evm_mine') block = await web3.eth.getBlock('latest') + console.log(block) } return block } diff --git a/test/helpers/locator-deploy.js b/test/helpers/locator-deploy.js index 7f7ba28d7..c54ff12ce 100644 --- a/test/helpers/locator-deploy.js +++ b/test/helpers/locator-deploy.js @@ -1,3 +1,5 @@ +const LidoLocator = artifacts.require('LidoLocator') + const DUMMY_ADDRESS = '0x' + 'f'.repeat(40) const invalidButNonZeroLocatorConfig = { @@ -38,7 +40,7 @@ async function updateProxyImplementation(proxyAddress, artifactName, proxyOwner, } async function getLocatorConfig(locatorAddress) { - const LidoLocator = await artifacts.require('LidoLocator') + const locator = await LidoLocator.at(locatorAddress) const config = { accountingOracle: await locator.accountingOracle(), @@ -63,7 +65,8 @@ async function deployLocatorWithInvalidImplementation(admin) { } async function deployLocatorWithDummyAddressesImplementation(admin) { - return await deployBehindOssifiableProxy('LidoLocator', admin, [invalidButNonZeroLocatorConfig]) + const proxy = await deployBehindOssifiableProxy('LidoLocator', admin, [invalidButNonZeroLocatorConfig]) + return await LidoLocator.at(proxy.address) } ///! Not specified in configUpdate values are set to dummy non zero addresses diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index 114c96e61..45c839165 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -66,7 +66,7 @@ async function pushOracleReport(consensus, oracle, numValidators, clBalance, elR const oracleVersion = await oracle.getContractVersion() - await oracle.submitReportData(reportItems, oracleVersion, { from: members.addresses[0] }) + return await oracle.submitReportData(reportItems, oracleVersion, { from: members.addresses[0] }) } module.exports = { getReportDataItems, calcReportDataHash, pushOracleReport } diff --git a/test/scenario/deposit_distribution.js b/test/scenario/deposit_distribution.js index 6ab7314c3..7315fae02 100644 --- a/test/scenario/deposit_distribution.js +++ b/test/scenario/deposit_distribution.js @@ -75,7 +75,7 @@ contract('StakingRouter', ([depositor, stranger1, dsm, address1, address2]) => { await web3.eth.sendTransaction({ value: sendEthForKeys, to: lido.address, from: stranger1 }) assert.equals(await lido.getBufferedEther(), sendEthForKeys) - const keysAllocation = await stakingRouter.getKeysAllocation(200) + const keysAllocation = await stakingRouter.getDepositsAllocation(200) assert.equals(keysAllocation.allocated, 200) assert.equals(keysAllocation.allocations, [100, 100]) diff --git a/test/scenario/lido_happy_path.js b/test/scenario/lido_happy_path.js index c330261f0..e112cd687 100644 --- a/test/scenario/lido_happy_path.js +++ b/test/scenario/lido_happy_path.js @@ -389,51 +389,57 @@ contract('Lido: happy path', (addresses) => { const oldTotalPooledEther = await pool.getTotalPooledEther() assertBn(oldTotalPooledEther, ETH(33 + 64), 'total pooled ether') - // Reporting 1.5-fold balance increase (64 => 96) + // Reporting 1.005-fold balance increase (64 => 64.32) to stay in limits - pushOracleReport(consensus, oracle, 2, ETH(96)) + await pushOracleReport(consensus, oracle, 2, ETH(64.32)) // Total shares increased because fee minted (fee shares added) - // shares ~= oldTotalShares + reward * oldTotalShares / (newTotalPooledEther - reward) + // shares = oldTotalShares + reward * totalFee * oldTotalShares / (newTotalPooledEther - reward * totalFee) const newTotalShares = await token.getTotalShares() - assertBn(newTotalShares, new BN('99467408585055643879'), 'total shares') + assertBn(newTotalShares, '97031905270948112819', 'total shares') // Total pooled Ether increased const newTotalPooledEther = await pool.getTotalPooledEther() - assertBn(newTotalPooledEther, ETH(33 + 96), 'total pooled ether') + assertBn(newTotalPooledEther, ETH(33 + 64.32), 'total pooled ether') // Ether2 stat reported by the pool changed correspondingly const ether2Stat = await pool.getBeaconStat() assertBn(ether2Stat.depositedValidators, 2, 'deposited ether2') - assertBn(ether2Stat.beaconBalance, ETH(96), 'remote ether2') + assertBn(ether2Stat.beaconBalance, ETH(64.32), 'remote ether2') // Buffered Ether amount didn't change assertBn(await pool.getBufferedEther(), ETH(33), 'buffered ether') // New tokens was minted to distribute fee - assertBn(await token.totalSupply(), tokens(129), 'token total supply') + assertBn(await token.totalSupply(), tokens(97.32), 'token total supply') - const reward = toBN(ETH(96 - 64)) + const reward = toBN(ETH(64.32 - 64)) const mintedAmount = new BN(totalFeePoints).mul(reward).divn(10000) // Token user balances increased - assertBn(await token.balanceOf(user1), new BN('3890721649484536082'), 'user1 tokens') - assertBn(await token.balanceOf(user2), new BN('38907216494845360824'), 'user2 tokens') - assertBn(await token.balanceOf(user3), new BN('83002061855670103092'), 'user3 tokens') + + assertBn(await token.balanceOf(user1), new BN('3008907216494845360'), 'user1 tokens') + assertBn(await token.balanceOf(user2), new BN('30089072164948453608'), 'user2 tokens') + assertBn(await token.balanceOf(user3), new BN('64190020618556701031'), 'user3 tokens') // Fee, in the form of minted tokens, was distributed between treasury, insurance fund // and node operators // treasuryTokenBalance ~= mintedAmount * treasuryFeePoints / 10000 // insuranceTokenBalance ~= mintedAmount * insuranceFeePoints / 10000 - assertBn(await token.balanceOf(treasuryAddr), new BN('1600000000000000000'), 'treasury tokens') - assertBn(await token.balanceOf(nodeOperatorsRegistry.address), new BN('1599999999999999999'), 'insurance tokens') + assert.equalsDelta(await token.balanceOf(treasuryAddr), new BN('16000000000000000'), 1, 'treasury tokens') + assert.equalsDelta( + await token.balanceOf(nodeOperatorsRegistry.address), + new BN('16000000000000000'), + 1, + 'insurance tokens' + ) // The node operators' fee is distributed between all active node operators, - // proprotional to their effective stake (the amount of Ether staked by the operator's + // proportional to their effective stake (the amount of Ether staked by the operator's // used and non-stopped validators). // // In our case, both node operators received the same fee since they have the same diff --git a/test/scenario/lido_penalties_slashing.js b/test/scenario/lido_penalties_slashing.js index 8abe83a1d..8d0949f59 100644 --- a/test/scenario/lido_penalties_slashing.js +++ b/test/scenario/lido_penalties_slashing.js @@ -4,7 +4,7 @@ const { assertBn } = require('@aragon/contract-helpers-test/src/asserts') const { getEventArgument } = require('@aragon/contract-helpers-test') const { assertRevert } = require('../helpers/assertThrow') -const { pad, ETH, tokens } = require('../helpers/utils') +const { pad, ETH, tokens, toBN } = require('../helpers/utils') const { signDepositData } = require('../helpers/signatures') const { waitBlocks } = require('../helpers/blockchain') const { deployProtocol } = require('../helpers/protocol') @@ -13,6 +13,7 @@ const { SLOTS_PER_FRAME, SECONDS_PER_FRAME } = require('../helpers/constants') const { pushOracleReport } = require('../helpers/oracle') const { oracleReportSanityCheckerStubFactory } = require('../helpers/factories') + const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') contract('Lido: penalties, slashing, operator stops', (addresses) => { @@ -445,9 +446,9 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { const lossReported = ETH(1) awaitingUser1Balance = awaitingUser1Balance.sub(new BN(lossReported)) - // Reporting 1 ETH balance loss (61 => 60) + // Reporting 1 ETH balance loss ( total pooled 61 => 60) - await pushReport(1, ETH(60)) + await pushReport(1, ETH(28)) // Total shares stay the same because no fee shares are added @@ -463,7 +464,7 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { const ether2Stat = await pool.getBeaconStat() assertBn(ether2Stat.depositedValidators, 2, 'deposited ether2') - assertBn(ether2Stat.beaconBalance, ETH(60), 'remote ether2') + assertBn(ether2Stat.beaconBalance, ETH(28), 'remote ether2') // Buffered Ether amount didn't change @@ -493,7 +494,11 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { awaitingUser1Balance = awaitingUser1Balance.add(new BN(depositAmount)) await web3.eth.sendTransaction({ to: pool.address, from: user1, value: depositAmount }) + + console.log((await pool.balanceOf(user1)).toString()) const block = await waitBlocks(await depositSecurityModule.getMinDepositBlockDistance()) + console.log((await pool.balanceOf(user1)).toString()) + const keysOpIndex = await nodeOperatorsRegistry.getKeysOpIndex() const signatures = [ signDepositData( @@ -604,7 +609,7 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { assertBn(nodeOperatorsRegistrySharesAfter, nodeOperatorsRegistrySharesBefore, `NOR stakingModule hasn't got fees`) const tenKBN = new BN(10000) - const totalFeeToDistribute = new BN(ETH(beaconBalanceIncrement)).mul(new BN(totalFeePoints)).div(tenKBN) + const totalFeeToDistribute = new BN(beaconBalanceIncrement.toString()).mul(new BN(totalFeePoints)).div(tenKBN) const totalPooledEther = await pool.getTotalPooledEther() let sharesToMint = totalFeeToDistribute @@ -642,7 +647,7 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { await pushReport(2, ETH(96)) // kicks rewards distribution - await nodeOperatorsRegistry.finishUpdatingExitedValidatorsKeysCount({ from: voting }) + await nodeOperatorsRegistry.updateExitedValidatorsCount(0, 1, { from: voting }) const nodeOperator1TokenSharesAfter = await token.sharesOf(nodeOperator1.address) const nodeOperator2TokenSharesAfter = await token.sharesOf(nodeOperator2.address) @@ -658,5 +663,4 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { `second node operator gained shares under fee distribution` ) }) - }) diff --git a/test/scenario/lido_rewards_distribution_math.js b/test/scenario/lido_rewards_distribution_math.js index 0d29ca8c6..ab1756304 100644 --- a/test/scenario/lido_rewards_distribution_math.js +++ b/test/scenario/lido_rewards_distribution_math.js @@ -76,11 +76,11 @@ contract('Lido: rewards distribution math', (addresses) => { } async function reportBeacon(validatorsCount, balance) { + const tx = await pushOracleReport(consensus, oracle, validatorsCount, balance) await ethers.provider.send('evm_increaseTime', [SECONDS_PER_FRAME + 1000]) await ethers.provider.send('evm_mine') - await pushOracleReport(consensus, oracle, validatorsCount, balance) - await ethers.provider.send('evm_increaseTime', [SECONDS_PER_FRAME + 1000]) - await ethers.provider.send('evm_mine') + + return tx } before(async () => { @@ -127,8 +127,6 @@ contract('Lido: rewards distribution math', (addresses) => { const withdrawalCredentials = pad('0x0202', 32) - console.log(voting) - await stakingRouter.setWithdrawalCredentials(withdrawalCredentials, { from: voting }) }) @@ -244,15 +242,21 @@ contract('Lido: rewards distribution math', (addresses) => { const nodeOperator1TokenBefore = await token.balanceOf(operator_1) // for some reason there's nothing in this receipt's log, so we're not going to use it - const [{ receipt }, deltas] = await getSharesTokenDeltas( - () => reportBeacon(1, reportingValue), - treasuryAddr, - nodeOperatorsRegistry.address - ) - const [treasuryTokenDelta, treasurySharesDelta, nodeOperatorsRegistryTokenDelta, nodeOperatorsRegistrySharesDelta] = - deltas + const treasuryBalanceBefore = await pool.balanceOf(treasuryAddr) + const nodeOperatorsRegistryBalanceBefore = await pool.balanceOf(nodeOperatorsRegistry.address) + const treasurySharesBefore = await pool.sharesOf(treasuryAddr) + const nodeOperatorsRegistrySharesBefore = await pool.sharesOf(nodeOperatorsRegistry.address) + console.log((await pool.getTotalShares()).toString()) - const { reportedMintAmount, tos, values } = await readLastPoolEventLog() + const receipt = await reportBeacon(1, reportingValue) + + console.log((await pool.getTotalPooledEther()).toString()) + const treasuryTokenDelta = (await pool.balanceOf(treasuryAddr)) - treasuryBalanceBefore + const treasurySharesDelta = (await pool.sharesOf(treasuryAddr)) - treasurySharesBefore + const nodeOperatorsRegistryTokenDelta = + (await pool.balanceOf(nodeOperatorsRegistry.address)) - nodeOperatorsRegistryBalanceBefore + const nodeOperatorsRegistrySharesDelta = + (await pool.sharesOf(nodeOperatorsRegistry.address)) - nodeOperatorsRegistrySharesBefore const awaitedDeltas = await getAwaitedFeesSharesTokensDeltas(profitAmount, prevTotalShares, 1) const { @@ -263,15 +267,28 @@ contract('Lido: rewards distribution math', (addresses) => { treasuryFeeToMint } = awaitedDeltas - assertBn(nodeOperatorsRegistrySharesDelta, nodeOperatorsSharesToMint, 'nodeOperator1 shares are correct') - assertBn(treasurySharesDelta, treasurySharesToMint, 'treasury shares are correct') + assert.equals(nodeOperatorsRegistrySharesDelta, nodeOperatorsSharesToMint, 'nodeOperator1 shares are correct') + assert.equals(treasurySharesDelta, treasurySharesToMint, 'treasury shares are correct') + assert.equalsDelta(nodeOperatorsFeeToMint, treasuryTokenDelta, 1, 'reported the expected total fee') + assert.equalsDelta(nodeOperatorsRegistryTokenDelta, nodeOperatorsFeeToMint, 1, 'treasury shares are correct') - assertBn(treasuryFeeToMint.add(nodeOperatorsFeeToMint), reportedMintAmount, 'reported the expected total fee') + assert.emits(receipt, 'Transfer', { + to: nodeOperatorsRegistry.address, + value: nodeOperatorsFeeToMint + }) + assert.emits(receipt, 'Transfer', { + to: treasuryAddr, + value: nodeOperatorsFeeToMint + }) + assert.emits(receipt, 'TransferShares', { + to: nodeOperatorsRegistry.address, + sharesValue: nodeOperatorsSharesToMint + }) + assert.emits(receipt, 'TransferShares', { + to: treasuryAddr, + sharesValue: treasurySharesToMint + }) - assert.equal(tos[0], nodeOperatorsRegistry.address, 'second transfer to node operator') - assertBn(values[0], nodeOperatorsFeeToMint, 'operator transfer amount is correct') - assert.equal(tos[1], treasuryAddr, 'third transfer to treasury address') - assertBn(values[1], treasuryFeeToMint, 'treasury transfer amount is correct') assertBn( await token.balanceOf(user1), // 32 staked 2 buffered 1 profit @@ -435,37 +452,49 @@ contract('Lido: rewards distribution math', (addresses) => { const reportingValue = ETH(32 + 1 + 32 + profitAmountEth) const prevTotalShares = await pool.getTotalShares() - const [{ valuesBefore, valuesAfter }, deltas] = await getSharesTokenDeltas( - () => reportBeacon(2, reportingValue), - treasuryAddr, - user1, - user2 - ) - - const [ - treasuryTokenDelta, - treasurySharesDelta, - user1TokenDelta, - user1SharesDelta, - user2TokenDelta, - user2SharesDelta - ] = deltas - const { reportedMintAmount, tos, values } = await readLastPoolEventLog() + const treasuryBalanceBefore = await pool.balanceOf(treasuryAddr) + const nodeOperatorsRegistryBalanceBefore = await pool.balanceOf(nodeOperatorsRegistry.address) + const treasurySharesBefore = await pool.sharesOf(treasuryAddr) + const nodeOperatorsRegistrySharesBefore = await pool.sharesOf(nodeOperatorsRegistry.address) - const { sharesToMint, nodeOperatorsSharesToMint, treasurySharesToMint, nodeOperatorsFeeToMint, treasuryFeeToMint } = - await getAwaitedFeesSharesTokensDeltas(profitAmount, prevTotalShares, 2) + const receipt = await reportBeacon(2, reportingValue) + const treasuryTokenDelta = (await pool.balanceOf(treasuryAddr)) - treasuryBalanceBefore + const treasurySharesDelta = (await pool.sharesOf(treasuryAddr)) - treasurySharesBefore + const nodeOperatorsRegistryTokenDelta = + (await pool.balanceOf(nodeOperatorsRegistry.address)) - nodeOperatorsRegistryBalanceBefore + const nodeOperatorsRegistrySharesDelta = + (await pool.sharesOf(nodeOperatorsRegistry.address)) - nodeOperatorsRegistrySharesBefore - // events are ok - assert.equal(tos[0], nodeOperatorsRegistry.address, 'second transfer to staking router curated module') - assert.equal(tos[1], treasuryAddr, 'third transfer to treasury address') + const awaitedDeltas = await getAwaitedFeesSharesTokensDeltas(profitAmount, prevTotalShares, 2) + const { + totalFeeToDistribute, + nodeOperatorsSharesToMint, + treasurySharesToMint, + nodeOperatorsFeeToMint, + treasuryFeeToMint + } = awaitedDeltas - // TODO merge: 1 wei - // assertBn(values[0], nodeOperatorsFeeToMint, 'operator transfer amount is correct') - assertBn(values[1], treasuryFeeToMint, 'treasury transfer amount is correct') + assert.equals(nodeOperatorsRegistrySharesDelta, nodeOperatorsSharesToMint, 'nodeOperator1 shares are correct') + assert.equals(treasurySharesDelta, treasurySharesToMint, 'treasury shares are correct') + assert.equalsDelta(nodeOperatorsFeeToMint, treasuryTokenDelta, 1, 'reported the expected total fee') + assert.equalsDelta(nodeOperatorsRegistryTokenDelta, nodeOperatorsFeeToMint, 1, 'treasury shares are correct') - // TODO merge: 1 wei - // const totalFeeToMint = nodeOperatorsFeeToMint.add(treasuryFeeToMint) - // assertBn(totalFeeToMint, reportedMintAmount, 'reported the expected total fee') + assert.emits(receipt, 'Transfer', { + to: nodeOperatorsRegistry.address, + value: nodeOperatorsFeeToMint + }) + assert.emits(receipt, 'Transfer', { + to: treasuryAddr, + value: nodeOperatorsFeeToMint + }) + assert.emits(receipt, 'TransferShares', { + to: nodeOperatorsRegistry.address, + sharesValue: nodeOperatorsSharesToMint + }) + assert.emits(receipt, 'TransferShares', { + to: treasuryAddr, + sharesValue: treasurySharesToMint + }) // TODO merge: 1 wei // assertBn(await token.balanceOf(nodeOperatorsRegistry.address), nodeOperatorsFeeToMint, 'nodeOperatorsRegistry balance = fee') From 0d2e2cf3f237882417d8b8df83a862da7f1a7c5f Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 09:36:22 +0300 Subject: [PATCH 49/82] fix: empty value set for daemon config --- contracts/0.8.9/OracleDaemonConfig.sol | 1 + test/0.8.9/oracle-daemon-config.test.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/contracts/0.8.9/OracleDaemonConfig.sol b/contracts/0.8.9/OracleDaemonConfig.sol index 04aa7b88f..ee9143d5b 100644 --- a/contracts/0.8.9/OracleDaemonConfig.sol +++ b/contracts/0.8.9/OracleDaemonConfig.sol @@ -29,6 +29,7 @@ contract OracleDaemonConfig is AccessControlEnumerable { function set(string calldata _key, bytes calldata _value) external onlyRole(CONFIG_MANAGER_ROLE) { if (values[_key].length > 0) revert ErrorValueExists(_key); + if (_value.length == 0) revert ErrorEmptyValue(_key); values[_key] = _value; emit ConfigValueSet(_key, _value); diff --git a/test/0.8.9/oracle-daemon-config.test.js b/test/0.8.9/oracle-daemon-config.test.js index 0142972c9..19e4b563d 100644 --- a/test/0.8.9/oracle-daemon-config.test.js +++ b/test/0.8.9/oracle-daemon-config.test.js @@ -102,6 +102,13 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { await assert.revertsWithCustomError(OracleDaemonConfig.new(deployer, [manager, ZERO_ADDRESS], { from: deployer }), 'ErrorZeroAddress()') }) + it('revers when empty value passed to set', async () => { + await assert.revertsWithCustomError( + config.set(defaultKey, '0x', { from: manager }), + `ErrorEmptyValue("${defaultKey}")` + ) + }) + it('revers when empty value passed to update', async () => { await config.set(defaultKey, defaultValue, { from: manager }) await assert.revertsWithCustomError( From 5e880359b325a6fab9a9261df6eb5b6935e21fc5 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Sat, 11 Feb 2023 18:11:50 +0700 Subject: [PATCH 50/82] fix: handle report resubmit case --- contracts/0.8.9/oracle/BaseOracle.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/0.8.9/oracle/BaseOracle.sol b/contracts/0.8.9/oracle/BaseOracle.sol index 827b40f34..ce36c002e 100644 --- a/contracts/0.8.9/oracle/BaseOracle.sol +++ b/contracts/0.8.9/oracle/BaseOracle.sol @@ -173,7 +173,7 @@ abstract contract BaseOracle is IReportAsyncProcessor, AccessControlEnumerable, revert RefSlotMustBeGreaterThanProcessingOne(refSlot, prevProcessingRefSlot); } - if (prevProcessingRefSlot != prevSubmittedRefSlot) { + if (refSlot != prevSubmittedRefSlot && prevProcessingRefSlot != prevSubmittedRefSlot) { emit WarnProcessingMissed(prevSubmittedRefSlot); } From 1d9c0f6a42ba3d5bd7f77b63cd01801057a6fccc Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Mon, 13 Feb 2023 12:10:03 +0300 Subject: [PATCH 51/82] test fixes --- test/helpers/blockchain.js | 1 - test/scenario/lido_penalties_slashing.js | 54 +++++++++---------- .../lido_rewards_distribution_math.js | 15 ++++-- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/test/helpers/blockchain.js b/test/helpers/blockchain.js index 78ab18770..baf5ae570 100644 --- a/test/helpers/blockchain.js +++ b/test/helpers/blockchain.js @@ -3,7 +3,6 @@ async function waitBlocks(numBlocksToMine) { for (let i = 0; i < numBlocksToMine; ++i) { await network.provider.send('evm_mine') block = await web3.eth.getBlock('latest') - console.log(block) } return block } diff --git a/test/scenario/lido_penalties_slashing.js b/test/scenario/lido_penalties_slashing.js index 8d0949f59..ffb5b6b0b 100644 --- a/test/scenario/lido_penalties_slashing.js +++ b/test/scenario/lido_penalties_slashing.js @@ -1,18 +1,17 @@ -const { assert } = require('chai') +const hre = require('hardhat') const { BN } = require('bn.js') const { assertBn } = require('@aragon/contract-helpers-test/src/asserts') const { getEventArgument } = require('@aragon/contract-helpers-test') -const { assertRevert } = require('../helpers/assertThrow') +const { assert } = require('../helpers/assert') const { pad, ETH, tokens, toBN } = require('../helpers/utils') -const { signDepositData } = require('../helpers/signatures') const { waitBlocks } = require('../helpers/blockchain') const { deployProtocol } = require('../helpers/protocol') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') const { SLOTS_PER_FRAME, SECONDS_PER_FRAME } = require('../helpers/constants') const { pushOracleReport } = require('../helpers/oracle') const { oracleReportSanityCheckerStubFactory } = require('../helpers/factories') - +const { DSMAttestMessage, DSMPauseMessage, signDepositData } = require('../helpers/signatures') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') @@ -484,7 +483,7 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { }) it(`the oracle can't report less validators than previously`, () => { - assertRevert(pushReport(2, ETH(31))) + assert.reverts(pushReport(2, ETH(31))) }) it(`user deposits another 32 ETH to the pool`, async () => { @@ -492,38 +491,33 @@ contract('Lido: penalties, slashing, operator stops', (addresses) => { const depositAmount = ETH(32) awaitingTotalShares = awaitingTotalShares.add(new BN(depositAmount).mul(awaitingTotalShares).div(totalPooledEther)) awaitingUser1Balance = awaitingUser1Balance.add(new BN(depositAmount)) - await web3.eth.sendTransaction({ to: pool.address, from: user1, value: depositAmount }) - console.log((await pool.balanceOf(user1)).toString()) - const block = await waitBlocks(await depositSecurityModule.getMinDepositBlockDistance()) - console.log((await pool.balanceOf(user1)).toString()) + await hre.network.provider.send("hardhat_mine", ['0x100']) + const block = await web3.eth.getBlock('latest') const keysOpIndex = await nodeOperatorsRegistry.getKeysOpIndex() + + DSMAttestMessage.setMessagePrefix(await depositSecurityModule.ATTEST_MESSAGE_PREFIX()) + DSMPauseMessage.setMessagePrefix(await depositSecurityModule.PAUSE_MESSAGE_PREFIX()) + + const validAttestMessage = new DSMAttestMessage(block.number, block.hash, depositRoot, 1, keysOpIndex) + const signatures = [ - signDepositData( - await depositSecurityModule.ATTEST_MESSAGE_PREFIX(), - block.number, - block.hash, - depositRoot, - 1, - keysOpIndex, - '0x00', - guardians.privateKeys[guardians.addresses[0]] - ), - signDepositData( - await depositSecurityModule.ATTEST_MESSAGE_PREFIX(), - block.number, - block.hash, - depositRoot, - 1, - keysOpIndex, - '0x00', - guardians.privateKeys[guardians.addresses[1]] - ) + validAttestMessage.sign(guardians.privateKeys[guardians.addresses[0]]), + validAttestMessage.sign(guardians.privateKeys[guardians.addresses[1]]) ] - await depositSecurityModule.depositBufferedEther(block.number, block.hash, depositRoot, 1, keysOpIndex, '0x00', signatures) + await depositSecurityModule.depositBufferedEther( + block.number, + block.hash, + depositRoot, + 1, + keysOpIndex, + '0x', + signatures + ) + // TODO: check getBeaconStat call const ether2Stat = await pool.getBeaconStat() assertBn(ether2Stat.depositedValidators, 2, 'no validators have received the current deposit') diff --git a/test/scenario/lido_rewards_distribution_math.js b/test/scenario/lido_rewards_distribution_math.js index ab1756304..c226b8ede 100644 --- a/test/scenario/lido_rewards_distribution_math.js +++ b/test/scenario/lido_rewards_distribution_math.js @@ -194,7 +194,10 @@ contract('Lido: rewards distribution math', (addresses) => { it(`the first deposit gets deployed`, async () => { const [curated] = await stakingRouter.getStakingModules() - const block = await web3.eth.getBlock('latest') + await ethers.provider.send('evm_increaseTime', [SECONDS_PER_FRAME *2]) + await ethers.provider.send('evm_mine') + const block = await ethers.provider.getBlock('latest') + const keysOpIndex = await nodeOperatorsRegistry.getKeysOpIndex() DSMAttestMessage.setMessagePrefix(await depositSecurityModule.ATTEST_MESSAGE_PREFIX()) @@ -246,11 +249,9 @@ contract('Lido: rewards distribution math', (addresses) => { const nodeOperatorsRegistryBalanceBefore = await pool.balanceOf(nodeOperatorsRegistry.address) const treasurySharesBefore = await pool.sharesOf(treasuryAddr) const nodeOperatorsRegistrySharesBefore = await pool.sharesOf(nodeOperatorsRegistry.address) - console.log((await pool.getTotalShares()).toString()) const receipt = await reportBeacon(1, reportingValue) - console.log((await pool.getTotalPooledEther()).toString()) const treasuryTokenDelta = (await pool.balanceOf(treasuryAddr)) - treasuryBalanceBefore const treasurySharesDelta = (await pool.sharesOf(treasuryAddr)) - treasurySharesBefore const nodeOperatorsRegistryTokenDelta = @@ -752,7 +753,15 @@ contract('Lido: rewards distribution math', (addresses) => { const totalFeeToDistribute = new BN(profitAmount).mul(new BN(totalFeePoints)).div(tenKBN) + const sharesToMintSol = new BN(profitAmount) + .mul(new BN(totalFeePoints)) + .mul(prevTotalShares) + .div(totalPooledEther.mul(tenKBN).sub(new BN(profitAmount).mul(new BN(totalFeePoints)))) + const sharesToMint = totalFeeToDistribute.mul(prevTotalShares).div(totalPooledEther.sub(totalFeeToDistribute)) + + assert.equals(sharesToMintSol, sharesToMint) + const nodeOperatorsSharesToMint = sharesToMint.mul(new BN(nodeOperatorsFeePoints)).div(tenKBN) const treasurySharesToMint = sharesToMint.sub(nodeOperatorsSharesToMint) From 1c29a3cb98d6cfac3b3d9020d56cc7735b71f477 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 12:21:27 +0300 Subject: [PATCH 52/82] fix: +`CLValidatorsUpdated` event for Lido --- contracts/0.4.24/Lido.sol | 15 ++++++++++++++- lib/abi/Lido.json | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 8fd09efcc..5522d0ffc 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -181,6 +181,13 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Staking limit was removed event StakingLimitRemoved(); + // Emits when validators number delivered by the oracle + event CLValidatorsUpdated( + uint256 indexed reportTimestamp, + uint256 preCLValidators, + uint256 postCLValidators + ); + // Emits when oracle accounting report processed event ETHDistributed( uint256 indexed reportTimestamp, @@ -747,6 +754,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * i.e., exited Lido validators persist in the state, just with a different status */ function _processClStateUpdate( + uint256 _reportTimestamp, uint256 _preClValidators, uint256 _postClValidators, uint256 _postClBalance @@ -767,6 +775,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Save the current CL balance and validators to // calculate rewards on the next push CL_BALANCE_POSITION.setStorageUint256(_postClBalance); + + emit CLValidatorsUpdated(_reportTimestamp, _preClValidators, _postClValidators); } /** @@ -1172,7 +1182,10 @@ contract Lido is Versioned, StETHPermit, AragonApp { reportContext.preTotalShares = _getTotalShares(); reportContext.preCLValidators = CL_VALIDATORS_POSITION.getStorageUint256(); reportContext.preCLBalance = _processClStateUpdate( - reportContext.preCLValidators, _reportedData.clValidators, _reportedData.postCLBalance + _reportedData.reportTimestamp, + reportContext.preCLValidators, + _reportedData.clValidators, + _reportedData.postCLBalance ); // Step 2. diff --git a/lib/abi/Lido.json b/lib/abi/Lido.json index 9c3939399..a65ccdc22 100644 --- a/lib/abi/Lido.json +++ b/lib/abi/Lido.json @@ -1 +1 @@ -[{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_CONTROL_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ethAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStakingPaused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxStakeLimit","type":"uint256"},{"name":"_stakeLimitIncreasePerBlock","type":"uint256"}],"name":"setStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"RESUME_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalPooledEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTreasury","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBufferedEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveELRewards","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentStakeLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakeLimitFullInfo","outputs":[{"name":"isStakingPaused","type":"bool"},{"name":"isStakingLimitSet","type":"bool"},{"name":"currentStakeLimit","type":"uint256"},{"name":"maxStakeLimit","type":"uint256"},{"name":"maxStakeLimitGrowthBlocks","type":"uint256"},{"name":"prevStakeLimit","type":"uint256"},{"name":"prevStakeBlockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFeeDistribution","outputs":[{"name":"treasuryFeeBasisPoints","type":"uint16"},{"name":"insuranceFeeBasisPoints","type":"uint16"},{"name":"operatorsFeeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"receiveWithdrawals","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_sharesAmount","type":"uint256"}],"name":"getPooledEthByShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"nonces","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_referral","type":"address"}],"name":"submit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxDepositsCount","type":"uint256"},{"name":"_stakingModuleId","type":"uint256"},{"name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconStat","outputs":[{"name":"depositedValidators","type":"uint256"},{"name":"beaconValidators","type":"uint256"},{"name":"beaconBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_reportTimestamp","type":"uint256"},{"name":"_timeElapsed","type":"uint256"},{"name":"_clValidators","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_withdrawalVaultBalance","type":"uint256"},{"name":"_elRewardsVaultBalance","type":"uint256"},{"name":"_lastFinalizableRequestId","type":"uint256"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"postTotalPooledEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"withdrawals","type":"uint256"},{"name":"elRewards","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveStakingRouterDepositRemainder","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getFee","outputs":[{"name":"totalFee","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLidoLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canDeposit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalELRewardsCollected","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[],"name":"StakingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxStakeLimit","type":"uint256"},{"indexed":false,"name":"stakeLimitIncreasePerBlock","type":"uint256"}],"name":"StakingLimitSet","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingLimitRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLBalance","type":"uint256"},{"indexed":false,"name":"postCLBalance","type":"uint256"},{"indexed":false,"name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"name":"executionLayerRewardsWithdrawn","type":"uint256"},{"indexed":false,"name":"postBufferedEther","type":"uint256"}],"name":"ETHDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"preTotalShares","type":"uint256"},{"indexed":false,"name":"preTotalEther","type":"uint256"},{"indexed":false,"name":"postTotalShares","type":"uint256"},{"indexed":false,"name":"postTotalEther","type":"uint256"},{"indexed":false,"name":"sharesMintedAsFees","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"lidoLocator","type":"address"}],"name":"LidoLocatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"ELRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unbuffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"StakingRouterDepositRemainderReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"eip712StETH","type":"address"}],"name":"EIP712StETHInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_CONTROL_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ethAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStakingPaused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxStakeLimit","type":"uint256"},{"name":"_stakeLimitIncreasePerBlock","type":"uint256"}],"name":"setStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"RESUME_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalPooledEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTreasury","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBufferedEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveELRewards","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentStakeLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakeLimitFullInfo","outputs":[{"name":"isStakingPaused","type":"bool"},{"name":"isStakingLimitSet","type":"bool"},{"name":"currentStakeLimit","type":"uint256"},{"name":"maxStakeLimit","type":"uint256"},{"name":"maxStakeLimitGrowthBlocks","type":"uint256"},{"name":"prevStakeLimit","type":"uint256"},{"name":"prevStakeBlockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFeeDistribution","outputs":[{"name":"treasuryFeeBasisPoints","type":"uint16"},{"name":"insuranceFeeBasisPoints","type":"uint16"},{"name":"operatorsFeeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"receiveWithdrawals","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_sharesAmount","type":"uint256"}],"name":"getPooledEthByShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"nonces","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_referral","type":"address"}],"name":"submit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxDepositsCount","type":"uint256"},{"name":"_stakingModuleId","type":"uint256"},{"name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconStat","outputs":[{"name":"depositedValidators","type":"uint256"},{"name":"beaconValidators","type":"uint256"},{"name":"beaconBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_reportTimestamp","type":"uint256"},{"name":"_timeElapsed","type":"uint256"},{"name":"_clValidators","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_withdrawalVaultBalance","type":"uint256"},{"name":"_elRewardsVaultBalance","type":"uint256"},{"name":"_lastFinalizableRequestId","type":"uint256"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"postTotalPooledEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"withdrawals","type":"uint256"},{"name":"elRewards","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveStakingRouterDepositRemainder","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getFee","outputs":[{"name":"totalFee","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLidoLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canDeposit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalELRewardsCollected","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[],"name":"StakingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxStakeLimit","type":"uint256"},{"indexed":false,"name":"stakeLimitIncreasePerBlock","type":"uint256"}],"name":"StakingLimitSet","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingLimitRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLValidators","type":"uint256"},{"indexed":false,"name":"postCLValidators","type":"uint256"}],"name":"CLValidatorsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLBalance","type":"uint256"},{"indexed":false,"name":"postCLBalance","type":"uint256"},{"indexed":false,"name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"name":"executionLayerRewardsWithdrawn","type":"uint256"},{"indexed":false,"name":"postBufferedEther","type":"uint256"}],"name":"ETHDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"preTotalShares","type":"uint256"},{"indexed":false,"name":"preTotalEther","type":"uint256"},{"indexed":false,"name":"postTotalShares","type":"uint256"},{"indexed":false,"name":"postTotalEther","type":"uint256"},{"indexed":false,"name":"sharesMintedAsFees","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"lidoLocator","type":"address"}],"name":"LidoLocatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"ELRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unbuffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"StakingRouterDepositRemainderReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"eip712StETH","type":"address"}],"name":"EIP712StETHInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"}] \ No newline at end of file From db01adcfcab16ced3c5903c07dd303c77c22782d Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Mon, 13 Feb 2023 13:22:22 +0300 Subject: [PATCH 53/82] add handle report --- .../OracleReportSanityChecker.sol | 2 +- test/0.4.24/lido-handle-oracle-report.test.js | 104 +++++++++++++++++- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 4412fbc80..98e65e4cb 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -493,7 +493,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { uint256 churnLimit = (_limitsList.churnValidatorsPerDayLimit * _timeElapsed) / SECONDS_PER_DAY; - if (_appearedValidators > churnLimit) revert IncorrectAppearedValidators(churnLimit); + if (_appearedValidators > churnLimit) revert IncorrectAppearedValidators(_appearedValidators); } function _checkRequestIdToFinalizeUpTo( diff --git a/test/0.4.24/lido-handle-oracle-report.test.js b/test/0.4.24/lido-handle-oracle-report.test.js index 501dce80c..b22df4e4a 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -8,6 +8,7 @@ const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') const ETHForwarderMock = artifacts.require('ETHForwarderMock') const ONE_YEAR = 3600 * 24 * 365 +const ONE_DAY = 3600 * 24 contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, anotherStranger, depositor, operator]) => { let deployed, snapshot, lido, treasury, voting, oracle @@ -37,11 +38,11 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another } }) - ETHForwarderMock.new(deployed.oracle.address, { from: appManager }) + await ETHForwarderMock.new(deployed.oracle.address, { from: appManager, value: ETH(1) }) await hre.ethers.getImpersonatedSigner(deployed.oracle.address) await curatedModule.addNodeOperator('1', operator, { from: deployed.voting.address }) - const keysAmount = 50 + const keysAmount = 120 const keys1 = genKeys(keysAmount) await curatedModule.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: deployed.voting.address }) await curatedModule.setNodeOperatorStakingLimit(0, keysAmount, { from: deployed.voting.address }) @@ -371,5 +372,104 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another 'IncorrectCLBalanceIncrease(101)' ) }) + + it('does not revert on validators reported under limit', async () => { + await lido.submit(ZERO_ADDRESS, { from: stranger, value: ETH(3100), gasPrice: 1 }) + await lido.deposit(100, 1, '0x', { from: depositor }) + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 100, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + + await lido.handleOracleReport(0, ONE_DAY, 100, ETH(3200), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 100, beaconValidators: 100, beaconBalance: ETH(3200) }) + }) + + it('reverts on validators reported when over limit', async () => { + await lido.submit(ZERO_ADDRESS, { from: stranger, value: ETH(3200), gasPrice: 1 }) + await lido.deposit(101, 1, '0x', { from: depositor }) + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 100, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await assert.reverts( + lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }), + 'IncorrectAppearedValidators(101)' + ) + }) + + it('does not smooth if report in limits', async () => { + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(97) }) + }) + + it('does not smooth if cl balance report over limit', async () => { + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(100), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(100) }) + }) + + // it('smooths withdrawals if report in limits', async () => { + // await ETHForwarderMock.new(deployed.withdrawalVault.address, { from: appManager, value: ETH(1) }) + + // await oracleReportSanityChecker.setOracleReportLimits( + // { + // churnValidatorsPerDayLimit: 100, + // oneOffCLBalanceDecreaseBPLimit: 100, + // annualBalanceIncreaseBPLimit: 10000, + // shareRateDeviationBPLimit: 10000, + // maxValidatorExitRequestsPerReport: 10000, + // requestTimestampMargin: 0, + // maxPositiveTokenRebase: 10000000, + // maxAccountingExtraDataListItemsCount: 10000 + // }, + // { from: voting, gasPrice: 1 } + // ) + // await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + // await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(97) }) + // }) }) }) From a6865a633b067863d05a16041298b689ded08021 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 14:23:08 +0300 Subject: [PATCH 54/82] chore: NOR typo --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 2 +- test/0.4.24/node-operators-registry.test.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 7ef2d73a3..28e9c2f4f 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -1145,7 +1145,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { } function _onlyCorrectNodeOperatorState(bool _pass) internal pure { - require(_pass, "WORNG_OPERATOR_ACTIVE_STATE"); + require(_pass, "WRONG_OPERATOR_ACTIVE_STATE"); } function _auth(bytes32 _role) internal view { diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index ce13ebd81..a6d3c7cf8 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -503,7 +503,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await assert.reverts(app.activateNodeOperator(nodeOperatorId, { from: voting }), 'OUT_OF_RANGE') }) - it('reverts with WORNG_OPERATOR_ACTIVE_STATE when called on active node operator', async () => { + it('reverts with WRONG_OPERATOR_ACTIVE_STATE when called on active node operator', async () => { const activeNodeOperatorId = 0 const activeNodeOperator = await app.getNodeOperator(activeNodeOperatorId, false) @@ -511,7 +511,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await assert.reverts( app.activateNodeOperator(activeNodeOperatorId, { from: voting }), - 'WORNG_OPERATOR_ACTIVE_STATE' + 'WRONG_OPERATOR_ACTIVE_STATE' ) }) @@ -638,7 +638,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await assert.reverts(app.deactivateNodeOperator(nodeOperatorId, { from: voting }), 'OUT_OF_RANGE') }) - it('reverts with "WORNG_OPERATOR_ACTIVE_STATE" when called on not active node operator', async () => { + it('reverts with "WRONG_OPERATOR_ACTIVE_STATE" when called on not active node operator', async () => { const activeNodeOperatorId = await nodeOperators.findNodeOperatorId(app, (operator) => !operator.active) assert.notEqual(activeNodeOperatorId, -1, `Invariant: not active node operator not found`) @@ -647,7 +647,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await assert.reverts( app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }), - 'WORNG_OPERATOR_ACTIVE_STATE' + 'WRONG_OPERATOR_ACTIVE_STATE' ) }) @@ -951,14 +951,14 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ) }) - it('reverts with "WORNG_OPERATOR_ACTIVE_STATE" error when node operator deactivated', async () => { + it('reverts with "WRONG_OPERATOR_ACTIVE_STATE" error when node operator deactivated', async () => { const hasPermission = await dao.hasPermission(voting, app, 'SET_NODE_OPERATOR_LIMIT_ROLE') assert.isTrue(hasPermission) await app.deactivateNodeOperator(secondNodeOperatorId, { from: voting }) assert.isFalse(await app.getNodeOperatorIsActive(secondNodeOperatorId)) await assert.reverts( app.setNodeOperatorStakingLimit(secondNodeOperatorId, 40, { from: voting }), - 'WORNG_OPERATOR_ACTIVE_STATE' + 'WRONG_OPERATOR_ACTIVE_STATE' ) }) From f36fe3d8f5dfe5efbfe4c313b3662988bfeeb20d Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 14:24:00 +0300 Subject: [PATCH 55/82] refactor: don't use Error* prefix for errors --- contracts/0.8.9/BeaconChainDepositor.sol | 8 +-- contracts/0.8.9/Burner.sol | 32 ++++----- contracts/0.8.9/DepositSecurityModule.sol | 66 ++++++++++--------- contracts/0.8.9/LidoLocator.sol | 4 +- contracts/0.8.9/OracleDaemonConfig.sol | 26 ++++---- contracts/0.8.9/StakingRouter.sol | 66 +++++++++---------- contracts/0.8.9/proxy/OssifiableProxy.sol | 8 +-- .../OracleReportSanityChecker.sol | 12 ++-- lib/abi/BeaconChainDepositor.json | 2 +- lib/abi/Burner.json | 2 +- lib/abi/DepositSecurityModule.json | 2 +- lib/abi/LidoLocator.json | 2 +- lib/abi/OracleDaemonConfig.json | 2 +- lib/abi/OssifiableProxy.json | 2 +- lib/abi/StakingRouter.json | 2 +- test/0.4.24/lido.test.js | 8 +-- test/0.8.9/burner.test.js | 28 ++++---- test/0.8.9/deposit-security-module.test.js | 58 ++++++++-------- test/0.8.9/lido-locator.test.js | 2 +- test/0.8.9/oracle-daemon-config.test.js | 16 ++--- test/0.8.9/staking-router-deposits.test.js | 2 +- test/0.8.9/staking-router.test.js | 62 ++++++++--------- 22 files changed, 211 insertions(+), 201 deletions(-) diff --git a/contracts/0.8.9/BeaconChainDepositor.sol b/contracts/0.8.9/BeaconChainDepositor.sol index a0995af67..7ec67f755 100644 --- a/contracts/0.8.9/BeaconChainDepositor.sol +++ b/contracts/0.8.9/BeaconChainDepositor.sol @@ -29,7 +29,7 @@ contract BeaconChainDepositor { IDepositContract public immutable DEPOSIT_CONTRACT; constructor(address _depositContract) { - if (_depositContract == address(0)) revert ErrorDepositContractZeroAddress(); + if (_depositContract == address(0)) revert DepositContractZeroAddress(); DEPOSIT_CONTRACT = IDepositContract(_depositContract); } @@ -65,7 +65,7 @@ contract BeaconChainDepositor { } } - if (address(this).balance != targetBalance) revert ErrorNotExpectedBalance(); + if (address(this).balance != targetBalance) revert NotExpectedBalance(); } /// @dev computes the deposit_root_hash required by official Beacon Deposit contract @@ -93,6 +93,6 @@ contract BeaconChainDepositor { ); } - error ErrorDepositContractZeroAddress(); - error ErrorNotExpectedBalance(); + error DepositContractZeroAddress(); + error NotExpectedBalance(); } diff --git a/contracts/0.8.9/Burner.sol b/contracts/0.8.9/Burner.sol index 76fa34de2..5cfd927f4 100644 --- a/contracts/0.8.9/Burner.sol +++ b/contracts/0.8.9/Burner.sol @@ -52,13 +52,13 @@ interface IStETH is IERC20 { contract Burner is IBurner, AccessControlEnumerable { using SafeERC20 for IERC20; - error ErrorAppAuthLidoFailed(); - error ErrorDirectETHTransfer(); - error ErrorZeroRecoveryAmount(); - error ErrorStETHRecoveryWrongFunc(); - error ErrorZeroBurnAmount(); - error ErrorNotEnoughExcessStETH(); - error ErrorZeroAddress(string field); + error AppAuthLidoFailed(); + error DirectETHTransfer(); + error ZeroRecoveryAmount(); + error StETHRecoveryWrongFunc(); + error ZeroBurnAmount(); + error NotEnoughExcessStETH(); + error ZeroAddress(string field); bytes32 public constant REQUEST_BURN_MY_STETH_ROLE = keccak256("REQUEST_BURN_MY_STETH_ROLE"); bytes32 public constant RECOVER_ASSETS_ROLE = keccak256("RECOVER_ASSETS_ROLE"); @@ -138,9 +138,9 @@ contract Burner is IBurner, AccessControlEnumerable { uint256 _totalCoverSharesBurnt, uint256 _totalNonCoverSharesBurnt ) { - if (_admin == address(0)) revert ErrorZeroAddress("_admin"); - if (_treasury == address(0)) revert ErrorZeroAddress("_treasury"); - if (_stETH == address(0)) revert ErrorZeroAddress("_stETH"); + if (_admin == address(0)) revert ZeroAddress("_admin"); + if (_treasury == address(0)) revert ZeroAddress("_treasury"); + if (_stETH == address(0)) revert ZeroAddress("_stETH"); _setupRole(DEFAULT_ADMIN_ROLE, _admin); _setupRole(REQUEST_BURN_SHARES_ROLE, _stETH); @@ -239,7 +239,7 @@ contract Burner is IBurner, AccessControlEnumerable { * Intentionally deny incoming ether */ receive() external payable { - revert ErrorDirectETHTransfer(); + revert DirectETHTransfer(); } /** @@ -250,8 +250,8 @@ contract Burner is IBurner, AccessControlEnumerable { * @param _amount token amount */ function recoverERC20(address _token, uint256 _amount) external onlyRole(RECOVER_ASSETS_ROLE) { - if (_amount == 0) revert ErrorZeroRecoveryAmount(); - if (_token == STETH) revert ErrorStETHRecoveryWrongFunc(); + if (_amount == 0) revert ZeroRecoveryAmount(); + if (_token == STETH) revert StETHRecoveryWrongFunc(); emit ERC20Recovered(msg.sender, _token, _amount); @@ -266,7 +266,7 @@ contract Burner is IBurner, AccessControlEnumerable { * @param _tokenId minted token id */ function recoverERC721(address _token, uint256 _tokenId) external onlyRole(RECOVER_ASSETS_ROLE) { - if (_token == STETH) revert ErrorStETHRecoveryWrongFunc(); + if (_token == STETH) revert StETHRecoveryWrongFunc(); emit ERC721Recovered(msg.sender, _token, _tokenId); @@ -288,7 +288,7 @@ contract Burner is IBurner, AccessControlEnumerable { function commitSharesToBurn( uint256 _sharesToBurnLimit ) external virtual override returns (uint256 sharesToBurnNow) { - if (msg.sender != STETH) revert ErrorAppAuthLidoFailed(); + if (msg.sender != STETH) revert AppAuthLidoFailed(); if (_sharesToBurnLimit == 0) { return 0; @@ -372,7 +372,7 @@ contract Burner is IBurner, AccessControlEnumerable { } function _requestBurn(uint256 _sharesAmount, uint256 _stETHAmount, bool _isCover) private { - if (_sharesAmount == 0) revert ErrorZeroBurnAmount(); + if (_sharesAmount == 0) revert ZeroBurnAmount(); emit StETHBurnRequested(_isCover, msg.sender, _stETHAmount, _sharesAmount); diff --git a/contracts/0.8.9/DepositSecurityModule.sol b/contracts/0.8.9/DepositSecurityModule.sol index 3a5547cf4..8f8cba651 100644 --- a/contracts/0.8.9/DepositSecurityModule.sol +++ b/contracts/0.8.9/DepositSecurityModule.sol @@ -49,15 +49,21 @@ contract DepositSecurityModule { event DepositsPaused(address indexed guardian, uint24 indexed stakingModuleId); event DepositsUnpaused(uint24 indexed stakingModuleId); - error ErrorStakingModuleIdTooLarge(); - error ErrorZeroAddress(string field); - error ErrorDuplicateAddress(address addr); - error ErrorNotAnOwner(address caller); - error ErrorSignature(string reason); - error ErrorDeposit(string reason); - error ErrorPauseIntentExpired(); - error ErrorNotAGuardian(address addr); - error ErrorZeroParameter(string parameter); + error StakingModuleIdTooLarge(); + error ZeroAddress(string field); + error DuplicateAddress(address addr); + error NotAnOwner(address caller); + error InvalidSignature(); + error SignatureNotSorted(); + error DepositNoQuorum(); + error DepositRootChanged(); + error DepositInactiveModule(); + error DepositTooFrequent(); + error DepositUnexpectedBlockHash(); + error DepositNonceChanged(); + error PauseIntentExpired(); + error NotAGuardian(address addr); + error ZeroParameter(string parameter); bytes32 public immutable ATTEST_MESSAGE_PREFIX; bytes32 public immutable PAUSE_MESSAGE_PREFIX; @@ -84,9 +90,9 @@ contract DepositSecurityModule { uint256 _minDepositBlockDistance, uint256 _pauseIntentValidityPeriodBlocks ) { - if (_lido == address(0)) revert ErrorZeroAddress("_lido"); - if (_depositContract == address(0)) revert ErrorZeroAddress ("_depositContract"); - if (_stakingRouter == address(0)) revert ErrorZeroAddress ("_stakingRouter"); + if (_lido == address(0)) revert ZeroAddress("_lido"); + if (_depositContract == address(0)) revert ZeroAddress ("_depositContract"); + if (_stakingRouter == address(0)) revert ZeroAddress ("_stakingRouter"); LIDO = ILido(_lido); STAKING_ROUTER = IStakingRouter(_stakingRouter); @@ -124,12 +130,12 @@ contract DepositSecurityModule { } modifier onlyOwner() { - if (msg.sender != owner) revert ErrorNotAnOwner(msg.sender); + if (msg.sender != owner) revert NotAnOwner(msg.sender); _; } modifier validStakingModuleId(uint256 _stakingModuleId) { - if (_stakingModuleId > type(uint24).max) revert ErrorStakingModuleIdTooLarge(); + if (_stakingModuleId > type(uint24).max) revert StakingModuleIdTooLarge(); _; } @@ -141,7 +147,7 @@ contract DepositSecurityModule { } function _setOwner(address _newOwner) internal { - if (_newOwner == address(0)) revert ErrorZeroAddress("_newOwner"); + if (_newOwner == address(0)) revert ZeroAddress("_newOwner"); owner = _newOwner; emit OwnerChanged(_newOwner); } @@ -161,7 +167,7 @@ contract DepositSecurityModule { } function _setPauseIntentValidityPeriodBlocks(uint256 newValue) internal { - if (newValue == 0) revert ErrorZeroParameter("pauseIntentValidityPeriodBlocks"); + if (newValue == 0) revert ZeroParameter("pauseIntentValidityPeriodBlocks"); pauseIntentValidityPeriodBlocks = newValue; emit PauseIntentValidityPeriodBlocksChanged(newValue); } @@ -200,7 +206,7 @@ contract DepositSecurityModule { } function _setMinDepositBlockDistance(uint256 newValue) internal { - if (newValue == 0) revert ErrorZeroParameter("minDepositBlockDistance"); + if (newValue == 0) revert ZeroParameter("minDepositBlockDistance"); if (newValue != minDepositBlockDistance) { minDepositBlockDistance = newValue; emit MinDepositBlockDistanceChanged(newValue); @@ -280,8 +286,8 @@ contract DepositSecurityModule { } function _addGuardian(address _newGuardian) internal { - if (_newGuardian == address(0)) revert ErrorZeroAddress("_newGuardian"); - if (_isGuardian(_newGuardian)) revert ErrorDuplicateAddress(_newGuardian); + if (_newGuardian == address(0)) revert ZeroAddress("_newGuardian"); + if (_isGuardian(_newGuardian)) revert DuplicateAddress(_newGuardian); guardians.push(_newGuardian); guardianIndicesOneBased[_newGuardian] = guardians.length; emit GuardianAdded(_newGuardian); @@ -294,7 +300,7 @@ contract DepositSecurityModule { */ function removeGuardian(address addr, uint256 newQuorum) external onlyOwner { uint256 indexOneBased = guardianIndicesOneBased[addr]; - if (indexOneBased == 0) revert ErrorNotAGuardian(addr); + if (indexOneBased == 0) revert NotAGuardian(addr); uint256 totalGuardians = guardians.length; assert(indexOneBased <= totalGuardians); @@ -349,10 +355,10 @@ contract DepositSecurityModule { bytes32 msgHash = keccak256(abi.encodePacked(PAUSE_MESSAGE_PREFIX, blockNumber, stakingModuleId)); guardianAddr = ECDSA.recover(msgHash, sig.r, sig.vs); guardianIndex = _getGuardianIndex(guardianAddr); - if (guardianIndex == -1) revert ErrorSignature("invalid"); + if (guardianIndex == -1) revert InvalidSignature(); } - if (block.number - blockNumber > pauseIntentValidityPeriodBlocks) revert ErrorPauseIntentExpired(); + if (block.number - blockNumber > pauseIntentValidityPeriodBlocks) revert PauseIntentExpired(); STAKING_ROUTER.pauseStakingModule(stakingModuleId); emit DepositsPaused(guardianAddr, uint24(stakingModuleId)); @@ -413,19 +419,19 @@ contract DepositSecurityModule { bytes calldata depositCalldata, Signature[] calldata sortedGuardianSignatures ) external validStakingModuleId(stakingModuleId) { - if (quorum == 0 || sortedGuardianSignatures.length < quorum) revert ErrorDeposit("no quorum"); + if (quorum == 0 || sortedGuardianSignatures.length < quorum) revert DepositNoQuorum(); bytes32 onchainDepositRoot = IDepositContract(DEPOSIT_CONTRACT).get_deposit_root(); - if (depositRoot != onchainDepositRoot) revert ErrorDeposit("deposit root changed"); + if (depositRoot != onchainDepositRoot) revert DepositRootChanged(); - if (!STAKING_ROUTER.getStakingModuleIsActive(stakingModuleId)) revert ErrorDeposit("inactive module"); + if (!STAKING_ROUTER.getStakingModuleIsActive(stakingModuleId)) revert DepositInactiveModule(); uint256 lastDepositBlock = STAKING_ROUTER.getStakingModuleLastDepositBlock(stakingModuleId); - if (block.number - lastDepositBlock < minDepositBlockDistance) revert ErrorDeposit("too frequent"); - if (blockHash == bytes32(0) || blockhash(blockNumber) != blockHash) revert ErrorDeposit("unexpected block hash"); + if (block.number - lastDepositBlock < minDepositBlockDistance) revert DepositTooFrequent(); + if (blockHash == bytes32(0) || blockhash(blockNumber) != blockHash) revert DepositUnexpectedBlockHash(); uint256 onchainNonce = STAKING_ROUTER.getStakingModuleNonce(stakingModuleId); - if (nonce != onchainNonce) revert ErrorDeposit("nonce changed"); + if (nonce != onchainNonce) revert DepositNonceChanged(); _verifySignatures(depositRoot, blockNumber, blockHash, stakingModuleId, nonce, sortedGuardianSignatures); @@ -448,8 +454,8 @@ contract DepositSecurityModule { for (uint256 i = 0; i < sigs.length; ++i) { address signerAddr = ECDSA.recover(msgHash, sigs[i].r, sigs[i].vs); - if (!_isGuardian(signerAddr)) revert ErrorSignature("invalid"); - if (signerAddr <= prevSignerAddr) revert ErrorSignature("not sorted"); + if (!_isGuardian(signerAddr)) revert InvalidSignature(); + if (signerAddr <= prevSignerAddr) revert SignatureNotSorted(); prevSignerAddr = signerAddr; } } diff --git a/contracts/0.8.9/LidoLocator.sol b/contracts/0.8.9/LidoLocator.sol index f5b8c5b61..721875b00 100644 --- a/contracts/0.8.9/LidoLocator.sol +++ b/contracts/0.8.9/LidoLocator.sol @@ -29,7 +29,7 @@ contract LidoLocator is ILidoLocator { address withdrawalVault; } - error ErrorZeroAddress(); + error ZeroAddress(); address public immutable accountingOracle; address public immutable depositSecurityModule; @@ -105,7 +105,7 @@ contract LidoLocator is ILidoLocator { } function _assertNonZero(address _address) internal pure returns (address) { - if (_address == address(0)) revert ErrorZeroAddress(); + if (_address == address(0)) revert ZeroAddress(); return _address; } } diff --git a/contracts/0.8.9/OracleDaemonConfig.sol b/contracts/0.8.9/OracleDaemonConfig.sol index ee9143d5b..da5d4a4cf 100644 --- a/contracts/0.8.9/OracleDaemonConfig.sol +++ b/contracts/0.8.9/OracleDaemonConfig.sol @@ -13,12 +13,12 @@ contract OracleDaemonConfig is AccessControlEnumerable { mapping(string => bytes) private values; constructor(address _admin, address[] memory _configManagers) { - if (_admin == address(0)) revert ErrorZeroAddress(); + if (_admin == address(0)) revert ZeroAddress(); _grantRole(DEFAULT_ADMIN_ROLE, _admin); for (uint256 i = 0; i < _configManagers.length; ) { - if (_configManagers[i] == address(0)) revert ErrorZeroAddress(); + if (_configManagers[i] == address(0)) revert ZeroAddress(); _grantRole(CONFIG_MANAGER_ROLE, _configManagers[i]); unchecked { @@ -28,30 +28,30 @@ contract OracleDaemonConfig is AccessControlEnumerable { } function set(string calldata _key, bytes calldata _value) external onlyRole(CONFIG_MANAGER_ROLE) { - if (values[_key].length > 0) revert ErrorValueExists(_key); - if (_value.length == 0) revert ErrorEmptyValue(_key); + if (values[_key].length > 0) revert ValueExists(_key); + if (_value.length == 0) revert EmptyValue(_key); values[_key] = _value; emit ConfigValueSet(_key, _value); } function update(string calldata _key, bytes calldata _value) external onlyRole(CONFIG_MANAGER_ROLE) { - if (values[_key].length == 0) revert ErrorValueDoesntExist(_key); - if (_value.length == 0) revert ErrorEmptyValue(_key); + if (values[_key].length == 0) revert ValueDoesntExist(_key); + if (_value.length == 0) revert EmptyValue(_key); values[_key] = _value; emit ConfigValueUpdated(_key, _value); } function unset(string calldata _key) external onlyRole(CONFIG_MANAGER_ROLE) { - if (values[_key].length == 0) revert ErrorValueDoesntExist(_key); + if (values[_key].length == 0) revert ValueDoesntExist(_key); delete values[_key]; emit ConfigValueUnset(_key); } function get(string calldata _key) external view returns (bytes memory) { - if (values[_key].length == 0) revert ErrorValueDoesntExist(_key); + if (values[_key].length == 0) revert ValueDoesntExist(_key); return values[_key]; } @@ -60,7 +60,7 @@ contract OracleDaemonConfig is AccessControlEnumerable { bytes[] memory results = new bytes[](_keys.length); for (uint256 i = 0; i < _keys.length; ) { - if (values[_keys[i]].length == 0) revert ErrorValueDoesntExist(_keys[i]); + if (values[_keys[i]].length == 0) revert ValueDoesntExist(_keys[i]); results[i] = values[_keys[i]]; @@ -72,10 +72,10 @@ contract OracleDaemonConfig is AccessControlEnumerable { return results; } - error ErrorValueExists(string key); - error ErrorEmptyValue(string key); - error ErrorValueDoesntExist(string key); - error ErrorZeroAddress(); + error ValueExists(string key); + error EmptyValue(string key); + error ValueDoesntExist(string key); + error ZeroAddress(); event ConfigValueSet(string key, bytes value); event ConfigValueUpdated(string key, bytes value); diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 5615315ca..3ae1fd511 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -35,20 +35,20 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version event StakingRouterETHDeposited(uint256 indexed stakingModuleId, uint256 amount); /// @dev errors - error ErrorZeroAddress(string field); - error ErrorValueOver100Percent(string field); - error ErrorStakingModuleNotActive(); - error ErrorStakingModuleNotPaused(); - error ErrorEmptyWithdrawalsCredentials(); - error ErrorDirectETHTransfer(); + error ZeroAddress(string field); + error ValueOver100Percent(string field); + error StakingModuleNotActive(); + error StakingModuleNotPaused(); + error EmptyWithdrawalsCredentials(); + error DirectETHTransfer(); error InvalidReportData(); - error ErrorExitedValidatorsCountCannotDecrease(); - error ErrorStakingModulesLimitExceeded(); - error ErrorStakingModuleIdTooLarge(); - error ErrorStakingModuleUnregistered(); - error ErrorAppAuthLidoFailed(); - error ErrorStakingModuleStatusTheSame(); - error ErrorStakingModuleWrongName(); + error ExitedValidatorsCountCannotDecrease(); + error StakingModulesLimitExceeded(); + error StakingModuleIdTooLarge(); + error StakingModuleUnregistered(); + error AppAuthLidoFailed(); + error StakingModuleStatusTheSame(); + error StakingModuleWrongName(); error UnexpectedCurrentValidatorsCount( uint256 currentModuleExitedValidatorsCount, uint256 currentNodeOpExitedValidatorsCount, @@ -124,7 +124,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 internal constant UINT24_MAX = type(uint24).max; modifier validStakingModuleId(uint256 _stakingModuleId) { - if (_stakingModuleId > UINT24_MAX) revert ErrorStakingModuleIdTooLarge(); + if (_stakingModuleId > UINT24_MAX) revert StakingModuleIdTooLarge(); _; } @@ -137,8 +137,8 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version * @param _withdrawalCredentials Lido withdrawal vault contract address */ function initialize(address _admin, address _lido, bytes32 _withdrawalCredentials) external { - if (_admin == address(0)) revert ErrorZeroAddress("_admin"); - if (_lido == address(0)) revert ErrorZeroAddress("_lido"); + if (_admin == address(0)) revert ZeroAddress("_admin"); + if (_lido == address(0)) revert ZeroAddress("_lido"); _initializeContractVersionTo(1); @@ -151,7 +151,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version /// @dev prohibit direct transfer to contract receive() external payable { - revert ErrorDirectETHTransfer(); + revert DirectETHTransfer(); } /** @@ -176,14 +176,14 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 _stakingModuleFee, uint256 _treasuryFee ) external onlyRole(STAKING_MODULE_MANAGE_ROLE) { - if (_targetShare > TOTAL_BASIS_POINTS) revert ErrorValueOver100Percent("_targetShare"); - if (_stakingModuleFee + _treasuryFee > TOTAL_BASIS_POINTS) revert ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee"); - if (_stakingModuleAddress == address(0)) revert ErrorZeroAddress("_stakingModuleAddress"); - if (bytes(_name).length == 0 || bytes(_name).length > 32) revert ErrorStakingModuleWrongName(); + if (_targetShare > TOTAL_BASIS_POINTS) revert ValueOver100Percent("_targetShare"); + if (_stakingModuleFee + _treasuryFee > TOTAL_BASIS_POINTS) revert ValueOver100Percent("_stakingModuleFee + _treasuryFee"); + if (_stakingModuleAddress == address(0)) revert ZeroAddress("_stakingModuleAddress"); + if (bytes(_name).length == 0 || bytes(_name).length > 32) revert StakingModuleWrongName(); uint256 newStakingModuleIndex = getStakingModulesCount(); - if (newStakingModuleIndex >= 32) revert ErrorStakingModulesLimitExceeded(); + if (newStakingModuleIndex >= 32) revert StakingModulesLimitExceeded(); StakingModule storage newStakingModule = _getStakingModuleByIndex(newStakingModuleIndex); uint24 newStakingModuleId = uint24(LAST_STAKING_MODULE_ID_POSITION.getStorageUint256()) + 1; @@ -223,8 +223,8 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version validStakingModuleId(_stakingModuleId) onlyRole(STAKING_MODULE_MANAGE_ROLE) { - if (_targetShare > TOTAL_BASIS_POINTS) revert ErrorValueOver100Percent("_targetShare"); - if (_stakingModuleFee + _treasuryFee > TOTAL_BASIS_POINTS) revert ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee"); + if (_targetShare > TOTAL_BASIS_POINTS) revert ValueOver100Percent("_targetShare"); + if (_stakingModuleFee + _treasuryFee > TOTAL_BASIS_POINTS) revert ValueOver100Percent("_stakingModuleFee + _treasuryFee"); uint256 stakingModuleIndex = _getStakingModuleIndexById(_stakingModuleId); StakingModule storage stakingModule = _getStakingModuleByIndex(stakingModuleIndex); @@ -274,7 +274,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleIds[i]); uint256 prevReportedExitedValidatorsCount = stakingModule.exitedValidatorsCount; if (_exitedValidatorsCounts[i] < prevReportedExitedValidatorsCount) { - revert ErrorExitedValidatorsCountCannotDecrease(); + revert ExitedValidatorsCountCannotDecrease(); } ( @@ -663,7 +663,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); StakingModuleStatus _prevStatus = StakingModuleStatus(stakingModule.status); - if (_prevStatus == _status) revert ErrorStakingModuleStatusTheSame(); + if (_prevStatus == _status) revert StakingModuleStatusTheSame(); stakingModule.status = uint8(_status); emit StakingModuleStatusSet(_stakingModuleId, _status, msg.sender); } @@ -678,7 +678,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); StakingModuleStatus _prevStatus = StakingModuleStatus(stakingModule.status); - if (_prevStatus != StakingModuleStatus.Active) revert ErrorStakingModuleNotActive(); + if (_prevStatus != StakingModuleStatus.Active) revert StakingModuleNotActive(); stakingModule.status = uint8(StakingModuleStatus.DepositsPaused); emit StakingModuleStatusSet(_stakingModuleId, StakingModuleStatus.DepositsPaused, msg.sender); } @@ -693,7 +693,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); StakingModuleStatus _prevStatus = StakingModuleStatus(stakingModule.status); - if (_prevStatus != StakingModuleStatus.DepositsPaused) revert ErrorStakingModuleNotPaused(); + if (_prevStatus != StakingModuleStatus.DepositsPaused) revert StakingModuleNotPaused(); stakingModule.status = uint8(StakingModuleStatus.Active); emit StakingModuleStatusSet(_stakingModuleId, StakingModuleStatus.Active, msg.sender); } @@ -850,7 +850,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version } // sanity check - if (totalFee >= precisionPoints) revert ErrorValueOver100Percent("totalFee"); + if (totalFee >= precisionPoints) revert ValueOver100Percent("totalFee"); /// @dev shrink arrays if (rewardedStakingModulesCount < stakingModulesCount) { @@ -910,7 +910,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 _stakingModuleId, bytes calldata _depositCalldata ) external payable validStakingModuleId(_stakingModuleId) returns (uint256 depositsCount) { - if (msg.sender != LIDO_POSITION.getStorageAddress()) revert ErrorAppAuthLidoFailed(); + if (msg.sender != LIDO_POSITION.getStorageAddress()) revert AppAuthLidoFailed(); uint256 depositableEth = msg.value; if (depositableEth == 0) { @@ -919,11 +919,11 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version } bytes32 withdrawalCredentials = getWithdrawalCredentials(); - if (withdrawalCredentials == 0) revert ErrorEmptyWithdrawalsCredentials(); + if (withdrawalCredentials == 0) revert EmptyWithdrawalsCredentials(); uint256 stakingModuleIndex = _getStakingModuleIndexById(_stakingModuleId); StakingModule storage stakingModule = _getStakingModuleByIndex(stakingModuleIndex); - if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) revert ErrorStakingModuleNotActive(); + if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) revert StakingModuleNotActive(); uint256 maxDepositsCount = Math256.min( _maxDepositsCount, @@ -1066,7 +1066,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version function _getStakingModuleIndexById(uint256 _stakingModuleId) internal view returns (uint256) { mapping(uint256 => uint256) storage _stakingModuleIndicesOneBased = _getStorageStakingIndicesMapping(); uint256 indexOneBased = _stakingModuleIndicesOneBased[_stakingModuleId]; - if (indexOneBased == 0) revert ErrorStakingModuleUnregistered(); + if (indexOneBased == 0) revert StakingModuleUnregistered(); return indexOneBased - 1; } diff --git a/contracts/0.8.9/proxy/OssifiableProxy.sol b/contracts/0.8.9/proxy/OssifiableProxy.sol index dfd44c11b..d4ccec05c 100644 --- a/contracts/0.8.9/proxy/OssifiableProxy.sol +++ b/contracts/0.8.9/proxy/OssifiableProxy.sol @@ -79,16 +79,16 @@ contract OssifiableProxy is ERC1967Proxy { modifier onlyAdmin() { address admin = _getAdmin(); if (admin == address(0)) { - revert ErrorProxyIsOssified(); + revert ProxyIsOssified(); } if (admin != msg.sender) { - revert ErrorNotAdmin(); + revert NotAdmin(); } _; } event ProxyOssified(); - error ErrorNotAdmin(); - error ErrorProxyIsOssified(); + error NotAdmin(); + error ProxyIsOssified(); } diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index c3651df3c..04dccfc34 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -379,8 +379,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { view { uint256 limit = _limits.unpack().maxValidatorExitRequestsPerReport; - if (_exitRequestsCount > limit) + if (_exitRequestsCount > limit) { revert IncorrectNumberOfExitRequestsPerReport(limit); + } } /// @notice Check rate of exited validators per day @@ -390,8 +391,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { view { uint256 limit = _limits.unpack().churnValidatorsPerDayLimit; - if (_exitedValidatorsCount > limit) + if (_exitedValidatorsCount > limit) { revert ExitedValidatorsLimitExceeded(limit, _exitedValidatorsCount); + } } /// @notice Check number of node operators reported per extra data item in accounting oracle @@ -403,8 +405,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { view { uint256 limit = _limits.unpack().maxAccountingExtraDataListItemsCount; - if (_nodeOperatorsCount > limit) + if (_nodeOperatorsCount > limit) { revert TooManyNodeOpsPerExtraDataItem(_itemIndex, _nodeOperatorsCount); + } } /// @notice Check max accounting extra data list items count @@ -414,8 +417,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { view { uint256 limit = _limits.unpack().maxAccountingExtraDataListItemsCount; - if (_extraDataListItemsCount > limit) + if (_extraDataListItemsCount > limit) { revert MaxAccountingExtraDataItemsCountExceeded(limit, _extraDataListItemsCount); + } } /// @notice Applies sanity checks to the withdrawal requests finalization diff --git a/lib/abi/BeaconChainDepositor.json b/lib/abi/BeaconChainDepositor.json index 320f3e979..94e81c706 100644 --- a/lib/abi/BeaconChainDepositor.json +++ b/lib/abi/BeaconChainDepositor.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_depositContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorDepositContractZeroAddress","type":"error"},{"inputs":[],"name":"ErrorNotExpectedBalance","type":"error"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_depositContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DepositContractZeroAddress","type":"error"},{"inputs":[],"name":"NotExpectedBalance","type":"error"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/lib/abi/Burner.json b/lib/abi/Burner.json index 130d96e33..07d05ab96 100644 --- a/lib/abi/Burner.json +++ b/lib/abi/Burner.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_stETH","type":"address"},{"internalType":"uint256","name":"_totalCoverSharesBurnt","type":"uint256"},{"internalType":"uint256","name":"_totalNonCoverSharesBurnt","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorAppAuthLidoFailed","type":"error"},{"inputs":[],"name":"ErrorDirectETHTransfer","type":"error"},{"inputs":[],"name":"ErrorNotEnoughExcessStETH","type":"error"},{"inputs":[],"name":"ErrorStETHRecoveryWrongFunc","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ErrorZeroAddress","type":"error"},{"inputs":[],"name":"ErrorZeroBurnAmount","type":"error"},{"inputs":[],"name":"ErrorZeroRecoveryAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"ExcessStETHRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnt","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECOVER_ASSETS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_MY_STETH_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_SHARES_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesToBurnLimit","type":"uint256"}],"name":"commitSharesToBurn","outputs":[{"internalType":"uint256","name":"sharesToBurnNow","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExcessStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSharesRequestedToBurn","outputs":[{"internalType":"uint256","name":"coverShares","type":"uint256"},{"internalType":"uint256","name":"nonCoverShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverExcessStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETHForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnSharesForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_stETH","type":"address"},{"internalType":"uint256","name":"_totalCoverSharesBurnt","type":"uint256"},{"internalType":"uint256","name":"_totalNonCoverSharesBurnt","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AppAuthLidoFailed","type":"error"},{"inputs":[],"name":"DirectETHTransfer","type":"error"},{"inputs":[],"name":"NotEnoughExcessStETH","type":"error"},{"inputs":[],"name":"StETHRecoveryWrongFunc","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroBurnAmount","type":"error"},{"inputs":[],"name":"ZeroRecoveryAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"ExcessStETHRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":true,"internalType":"address","name":"requestedBy","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isCover","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"StETHBurnt","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RECOVER_ASSETS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_MY_STETH_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_BURN_SHARES_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesToBurnLimit","type":"uint256"}],"name":"commitSharesToBurn","outputs":[{"internalType":"uint256","name":"sharesToBurnNow","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExcessStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonCoverSharesBurnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSharesRequestedToBurn","outputs":[{"internalType":"uint256","name":"coverShares","type":"uint256"},{"internalType":"uint256","name":"nonCoverShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverExcessStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stETHAmountToBurn","type":"uint256"}],"name":"requestBurnMyStETHForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_sharesAmountToBurn","type":"uint256"}],"name":"requestBurnSharesForCover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/lib/abi/DepositSecurityModule.json b/lib/abi/DepositSecurityModule.json index 2e469d207..c4a2f7758 100644 --- a/lib/abi/DepositSecurityModule.json +++ b/lib/abi/DepositSecurityModule.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_lido","type":"address"},{"internalType":"address","name":"_depositContract","type":"address"},{"internalType":"address","name":"_stakingRouter","type":"address"},{"internalType":"uint256","name":"_maxDepositsPerBlock","type":"uint256"},{"internalType":"uint256","name":"_minDepositBlockDistance","type":"uint256"},{"internalType":"uint256","name":"_pauseIntentValidityPeriodBlocks","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"ErrorDeposit","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"ErrorDuplicateAddress","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"ErrorNotAGuardian","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"ErrorNotAnOwner","type":"error"},{"inputs":[],"name":"ErrorPauseIntentExpired","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"ErrorSignature","type":"error"},{"inputs":[],"name":"ErrorStakingModuleIdTooLarge","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ErrorZeroAddress","type":"error"},{"inputs":[{"internalType":"string","name":"parameter","type":"string"}],"name":"ErrorZeroParameter","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"GuardianQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MaxDepositsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MinDepositBlockDistanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"PauseIntentValidityPeriodBlocksChanged","type":"event"},{"inputs":[],"name":"ATTEST_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_ROUTER","outputs":[{"internalType":"contract IStakingRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardians","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"depositRoot","type":"bytes32"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"depositCalldata","type":"bytes"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature[]","name":"sortedGuardianSignatures","type":"tuple[]"}],"name":"depositBufferedEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getGuardianIndex","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardianQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardians","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinDepositBlockDistance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauseIntentValidityPeriodBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature","name":"sig","type":"tuple"}],"name":"pauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"removeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setGuardianQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMinDepositBlockDistance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setPauseIntentValidityPeriodBlocks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_lido","type":"address"},{"internalType":"address","name":"_depositContract","type":"address"},{"internalType":"address","name":"_stakingRouter","type":"address"},{"internalType":"uint256","name":"_maxDepositsPerBlock","type":"uint256"},{"internalType":"uint256","name":"_minDepositBlockDistance","type":"uint256"},{"internalType":"uint256","name":"_pauseIntentValidityPeriodBlocks","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DepositInactiveModule","type":"error"},{"inputs":[],"name":"DepositNoQuorum","type":"error"},{"inputs":[],"name":"DepositNonceChanged","type":"error"},{"inputs":[],"name":"DepositRootChanged","type":"error"},{"inputs":[],"name":"DepositTooFrequent","type":"error"},{"inputs":[],"name":"DepositUnexpectedBlockHash","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"DuplicateAddress","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"NotAGuardian","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"NotAnOwner","type":"error"},{"inputs":[],"name":"PauseIntentExpired","type":"error"},{"inputs":[],"name":"SignatureNotSorted","type":"error"},{"inputs":[],"name":"StakingModuleIdTooLarge","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ZeroAddress","type":"error"},{"inputs":[{"internalType":"string","name":"parameter","type":"string"}],"name":"ZeroParameter","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint24","name":"stakingModuleId","type":"uint24"}],"name":"DepositsUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"GuardianQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MaxDepositsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"MinDepositBlockDistanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newValue","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"PauseIntentValidityPeriodBlocksChanged","type":"event"},{"inputs":[],"name":"ATTEST_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIDO","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_MESSAGE_PREFIX","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_ROUTER","outputs":[{"internalType":"contract IStakingRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"addGuardians","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"depositRoot","type":"bytes32"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"depositCalldata","type":"bytes"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature[]","name":"sortedGuardianSignatures","type":"tuple[]"}],"name":"depositBufferedEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getGuardianIndex","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardianQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGuardians","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinDepositBlockDistance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauseIntentValidityPeriodBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"internalType":"struct DepositSecurityModule.Signature","name":"sig","type":"tuple"}],"name":"pauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"removeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setGuardianQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMaxDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setMinDepositBlockDistance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newValue","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"setPauseIntentValidityPeriodBlocks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakingModuleId","type":"uint256"}],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/LidoLocator.json b/lib/abi/LidoLocator.json index 1bc5af26b..a75b6f4bc 100644 --- a/lib/abi/LidoLocator.json +++ b/lib/abi/LidoLocator.json @@ -1 +1 @@ -[{"inputs":[{"components":[{"internalType":"address","name":"accountingOracle","type":"address"},{"internalType":"address","name":"depositSecurityModule","type":"address"},{"internalType":"address","name":"elRewardsVault","type":"address"},{"internalType":"address","name":"legacyOracle","type":"address"},{"internalType":"address","name":"lido","type":"address"},{"internalType":"address","name":"oracleReportSanityChecker","type":"address"},{"internalType":"address","name":"postTokenRebaseReceiver","type":"address"},{"internalType":"address","name":"burner","type":"address"},{"internalType":"address","name":"stakingRouter","type":"address"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"validatorsExitBusOracle","type":"address"},{"internalType":"address","name":"withdrawalQueue","type":"address"},{"internalType":"address","name":"withdrawalVault","type":"address"}],"internalType":"struct LidoLocator.Config","name":"_config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorZeroAddress","type":"error"},{"inputs":[],"name":"accountingOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"coreComponents","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositSecurityModule","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"elRewardsVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legacyOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lido","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleReportComponentsForLido","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleReportSanityChecker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"postTokenRebaseReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validatorsExitBusOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalQueue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"components":[{"internalType":"address","name":"accountingOracle","type":"address"},{"internalType":"address","name":"depositSecurityModule","type":"address"},{"internalType":"address","name":"elRewardsVault","type":"address"},{"internalType":"address","name":"legacyOracle","type":"address"},{"internalType":"address","name":"lido","type":"address"},{"internalType":"address","name":"oracleReportSanityChecker","type":"address"},{"internalType":"address","name":"postTokenRebaseReceiver","type":"address"},{"internalType":"address","name":"burner","type":"address"},{"internalType":"address","name":"stakingRouter","type":"address"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"validatorsExitBusOracle","type":"address"},{"internalType":"address","name":"withdrawalQueue","type":"address"},{"internalType":"address","name":"withdrawalVault","type":"address"}],"internalType":"struct LidoLocator.Config","name":"_config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"accountingOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"coreComponents","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositSecurityModule","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"elRewardsVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legacyOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lido","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleReportComponentsForLido","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleReportSanityChecker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"postTokenRebaseReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validatorsExitBusOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalQueue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/lib/abi/OracleDaemonConfig.json b/lib/abi/OracleDaemonConfig.json index 1bdff7035..431f79df1 100644 --- a/lib/abi/OracleDaemonConfig.json +++ b/lib/abi/OracleDaemonConfig.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address[]","name":"_configManagers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorEmptyValue","type":"error"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorValueDoesntExist","type":"error"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ErrorValueExists","type":"error"},{"inputs":[],"name":"ErrorZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"ConfigValueUnset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"CONFIG_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"get","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"_keys","type":"string[]"}],"name":"getList","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"unset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address[]","name":"_configManagers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"EmptyValue","type":"error"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ValueDoesntExist","type":"error"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"ValueExists","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"ConfigValueUnset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"ConfigValueUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"CONFIG_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"get","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"_keys","type":"string[]"}],"name":"getList","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"unset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/OssifiableProxy.json b/lib/abi/OssifiableProxy.json index 4e931a704..731606988 100644 --- a/lib/abi/OssifiableProxy.json +++ b/lib/abi/OssifiableProxy.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"implementation_","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"data_","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorNotAdmin","type":"error"},{"inputs":[],"name":"ErrorProxyIsOssified","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[],"name":"ProxyOssified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"newAdmin_","type":"address"}],"name":"proxy__changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxy__getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy__getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy__getIsOssified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy__ossify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation_","type":"address"}],"name":"proxy__upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation_","type":"address"},{"internalType":"bytes","name":"setupCalldata_","type":"bytes"},{"internalType":"bool","name":"forceCall_","type":"bool"}],"name":"proxy__upgradeToAndCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"implementation_","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"data_","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"ProxyIsOssified","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[],"name":"ProxyOssified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"newAdmin_","type":"address"}],"name":"proxy__changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxy__getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy__getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy__getIsOssified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxy__ossify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation_","type":"address"}],"name":"proxy__upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation_","type":"address"},{"internalType":"bytes","name":"setupCalldata_","type":"bytes"},{"internalType":"bool","name":"forceCall_","type":"bool"}],"name":"proxy__upgradeToAndCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index f8e864d94..217b9bcb2 100644 --- a/lib/abi/StakingRouter.json +++ b/lib/abi/StakingRouter.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_depositContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrorAppAuthLidoFailed","type":"error"},{"inputs":[],"name":"ErrorDepositContractZeroAddress","type":"error"},{"inputs":[],"name":"ErrorDirectETHTransfer","type":"error"},{"inputs":[],"name":"ErrorEmptyWithdrawalsCredentials","type":"error"},{"inputs":[],"name":"ErrorExitedValidatorsCountCannotDecrease","type":"error"},{"inputs":[],"name":"ErrorNotExpectedBalance","type":"error"},{"inputs":[],"name":"ErrorStakingModuleIdTooLarge","type":"error"},{"inputs":[],"name":"ErrorStakingModuleNotActive","type":"error"},{"inputs":[],"name":"ErrorStakingModuleNotPaused","type":"error"},{"inputs":[],"name":"ErrorStakingModuleStatusTheSame","type":"error"},{"inputs":[],"name":"ErrorStakingModuleUnregistered","type":"error"},{"inputs":[],"name":"ErrorStakingModuleWrongName","type":"error"},{"inputs":[],"name":"ErrorStakingModulesLimitExceeded","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ErrorValueOver100Percent","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ErrorZeroAddress","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidReportData","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpStuckValidatorsCount","type":"uint256"}],"name":"UnexpectedCurrentValidatorsCount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"stakingModule","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"createdBy","type":"address"}],"name":"StakingModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unreportedExitedValidatorsCount","type":"uint256"}],"name":"StakingModuleExitedValidatorsIncompleteReporting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingModuleFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"treasuryFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"enum StakingRouter.StakingModuleStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetShare","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleTargetShareSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakingRouterETHDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"WithdrawalCredentialsSet","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_PRECISION_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_WITHDRAWAL_CREDENTIALS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_REWARDS_MINTED_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_MANAGE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNSAFE_SET_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_stakingModuleAddress","type":"address"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"addStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDepositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getAllNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllStakingModuleReports","outputs":[{"components":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositsCount","type":"uint256"}],"name":"getDepositsAllocation","outputs":[{"internalType":"uint256","name":"allocated","type":"uint256"},{"internalType":"uint256[]","name":"allocations","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExitedValidatorsCountAcrossAllModules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLido","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256[]","name":"_nodeOperatorIds","type":"uint256[]"}],"name":"getNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"summaries","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"getNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"summaries","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistribution","outputs":[{"internalType":"uint96","name":"modulesFee","type":"uint96"},{"internalType":"uint96","name":"treasuryFee","type":"uint96"},{"internalType":"uint256","name":"basePrecision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistributionE4Precision","outputs":[{"internalType":"uint16","name":"modulesFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModule","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleActiveValidatorsCount","outputs":[{"internalType":"uint256","name":"activeValidatorsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModuleIds","outputs":[{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsDepositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleLastDepositBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleMaxDepositsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"}],"name":"getStakingModuleReports","outputs":[{"components":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleReport[]","name":"reports","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleStatus","outputs":[{"internalType":"enum StakingRouter.StakingModuleStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModules","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule[]","name":"res","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingRewardsDistribution","outputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"},{"internalType":"uint96[]","name":"stakingModuleFees","type":"uint96[]"},{"internalType":"uint96","name":"totalFee","type":"uint96"},{"internalType":"uint256","name":"precisionPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFeeE4Precision","outputs":[{"internalType":"uint16","name":"totalFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_lido","type":"address"},{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"pauseStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_totalShares","type":"uint256[]"}],"name":"reportRewardsMinted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_exitedValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleExitedValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_stuckValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleStuckValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"resumeStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"enum StakingRouter.StakingModuleStatus","name":"_status","type":"uint8"}],"name":"setStakingModuleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"setWithdrawalCredentials","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_triggerUpdateFinish","type":"bool"},{"components":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorStuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorStuckValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsCountCorrection","name":"_correction","type":"tuple"}],"name":"unsafeSetExitedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_exitedValidatorsCounts","type":"uint256[]"}],"name":"updateExitedValidatorsCountByStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"updateStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_depositContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AppAuthLidoFailed","type":"error"},{"inputs":[],"name":"DepositContractZeroAddress","type":"error"},{"inputs":[],"name":"DirectETHTransfer","type":"error"},{"inputs":[],"name":"EmptyWithdrawalsCredentials","type":"error"},{"inputs":[],"name":"ExitedValidatorsCountCannotDecrease","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidReportData","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NotExpectedBalance","type":"error"},{"inputs":[],"name":"StakingModuleIdTooLarge","type":"error"},{"inputs":[],"name":"StakingModuleNotActive","type":"error"},{"inputs":[],"name":"StakingModuleNotPaused","type":"error"},{"inputs":[],"name":"StakingModuleStatusTheSame","type":"error"},{"inputs":[],"name":"StakingModuleUnregistered","type":"error"},{"inputs":[],"name":"StakingModuleWrongName","type":"error"},{"inputs":[],"name":"StakingModulesLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpStuckValidatorsCount","type":"uint256"}],"name":"UnexpectedCurrentValidatorsCount","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ValueOver100Percent","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"stakingModule","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"createdBy","type":"address"}],"name":"StakingModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unreportedExitedValidatorsCount","type":"uint256"}],"name":"StakingModuleExitedValidatorsIncompleteReporting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingModuleFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"treasuryFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"enum StakingRouter.StakingModuleStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetShare","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleTargetShareSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakingRouterETHDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"WithdrawalCredentialsSet","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_PRECISION_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_WITHDRAWAL_CREDENTIALS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_REWARDS_MINTED_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_MANAGE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNSAFE_SET_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_stakingModuleAddress","type":"address"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"addStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDepositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getAllNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllStakingModuleReports","outputs":[{"components":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositsCount","type":"uint256"}],"name":"getDepositsAllocation","outputs":[{"internalType":"uint256","name":"allocated","type":"uint256"},{"internalType":"uint256[]","name":"allocations","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExitedValidatorsCountAcrossAllModules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLido","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256[]","name":"_nodeOperatorIds","type":"uint256[]"}],"name":"getNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"summaries","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"getNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"summaries","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistribution","outputs":[{"internalType":"uint96","name":"modulesFee","type":"uint96"},{"internalType":"uint96","name":"treasuryFee","type":"uint96"},{"internalType":"uint256","name":"basePrecision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistributionE4Precision","outputs":[{"internalType":"uint16","name":"modulesFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModule","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleActiveValidatorsCount","outputs":[{"internalType":"uint256","name":"activeValidatorsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModuleIds","outputs":[{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsDepositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleLastDepositBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleMaxDepositsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"}],"name":"getStakingModuleReports","outputs":[{"components":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleReport[]","name":"reports","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleStatus","outputs":[{"internalType":"enum StakingRouter.StakingModuleStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModules","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule[]","name":"res","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingRewardsDistribution","outputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"},{"internalType":"uint96[]","name":"stakingModuleFees","type":"uint96[]"},{"internalType":"uint96","name":"totalFee","type":"uint96"},{"internalType":"uint256","name":"precisionPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFeeE4Precision","outputs":[{"internalType":"uint16","name":"totalFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_lido","type":"address"},{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"pauseStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_totalShares","type":"uint256[]"}],"name":"reportRewardsMinted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_exitedValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleExitedValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_stuckValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleStuckValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"resumeStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"enum StakingRouter.StakingModuleStatus","name":"_status","type":"uint8"}],"name":"setStakingModuleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"setWithdrawalCredentials","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_triggerUpdateFinish","type":"bool"},{"components":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorStuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorStuckValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsCountCorrection","name":"_correction","type":"tuple"}],"name":"unsafeSetExitedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_exitedValidatorsCounts","type":"uint256[]"}],"name":"updateExitedValidatorsCountByStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"updateStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index ab6c348d6..23deb14f9 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -496,17 +496,17 @@ contract('Lido', ([appManager, user1, user2, user3, nobody, depositor, treasury] await assert.revertsWithCustomError( stakingRouter.updateStakingModule(module1.id, 10001, 300, 700, { from: voting }), - 'ErrorValueOver100Percent("_targetShare")' + 'ValueOver100Percent("_targetShare")' ) await assert.revertsWithCustomError( stakingRouter.updateStakingModule(module1.id, 10000, 10001, 700, { from: voting }), - 'ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee")' + 'ValueOver100Percent("_stakingModuleFee + _treasuryFee")' ) await assert.revertsWithCustomError( stakingRouter.updateStakingModule(module1.id, 10000, 300, 10001, { from: voting }), - 'ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee")' + 'ValueOver100Percent("_stakingModuleFee + _treasuryFee")' ) // distribution fee calculates on active keys in modules @@ -622,7 +622,7 @@ contract('Lido', ([appManager, user1, user2, user3, nobody, depositor, treasury] // can not deposit with unset withdrawalCredentials await assert.revertsWithCustomError( app.methods['deposit(uint256,uint256,bytes)'](MAX_DEPOSITS, CURATED_MODULE_ID, CALLDATA, { from: depositor }), - 'ErrorEmptyWithdrawalsCredentials()' + 'EmptyWithdrawalsCredentials()' ) // set withdrawalCredentials with keys, because they were trimmed await stakingRouter.setWithdrawalCredentials(pad('0x0202', 32), { from: voting }) diff --git a/test/0.8.9/burner.test.js b/test/0.8.9/burner.test.js index 285830845..54e89d588 100644 --- a/test/0.8.9/burner.test.js +++ b/test/0.8.9/burner.test.js @@ -77,17 +77,17 @@ contract('Burner', ([deployer, _, anotherAccount]) => { it(`can't use zero init addresses`, async () => { await assert.revertsWithCustomError( Burner.new(ZERO_ADDRESS, treasury, lido.address, bn(0), bn(0), { from: deployer }), - `ErrorZeroAddress("_admin")` + `ZeroAddress("_admin")` ) await assert.revertsWithCustomError( Burner.new(voting, ZERO_ADDRESS, lido.address, bn(0), bn(0), { from: deployer }), - `ErrorZeroAddress("_treasury")` + `ZeroAddress("_treasury")` ) await assert.revertsWithCustomError( Burner.new(voting, treasury, ZERO_ADDRESS, bn(0), bn(0), { from: deployer }), - `ErrorZeroAddress("_stETH")` + `ZeroAddress("_stETH")` ) }) @@ -98,13 +98,13 @@ contract('Burner', ([deployer, _, anotherAccount]) => { // but zero request on cover await assert.revertsWithCustomError( burner.requestBurnMyStETHForCover(StETH(0), { from: voting }), - `ErrorZeroBurnAmount()` + `ZeroBurnAmount()` ) // and zero request on non-cover await assert.revertsWithCustomError( burner.requestBurnMyStETH(StETH(0), { from: voting }), - `ErrorZeroBurnAmount()` + `ZeroBurnAmount()` ) }) @@ -189,7 +189,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await assert.revertsWithCustomError( burner.commitSharesToBurn(ETH(10)), - `ErrorAppAuthLidoFailed()` + `AppAuthLidoFailed()` ) // mimic the Lido for the callback invocation @@ -219,12 +219,12 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await assert.revertsWithCustomError( // should revert burner.commitSharesToBurn(ETH(10), { from: deployer }), - `ErrorAppAuthLidoFailed()` + `AppAuthLidoFailed()` ) await assert.revertsWithCustomError( burner.commitSharesToBurn(ETH(10), { from: anotherAccount }), - `ErrorAppAuthLidoFailed()` + `AppAuthLidoFailed()` ) const receipt = await burner.commitSharesToBurn(ETH(10), { from: lido.address }) @@ -273,13 +273,13 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await assert.revertsWithCustomError( burner.commitSharesToBurn(bn(500), { from: deployer }), - `ErrorAppAuthLidoFailed()` + `AppAuthLidoFailed()` ) await assert.revertsWithCustomError( // even burner.commitSharesToBurn(ETH(6), { from: appManager }), - `ErrorAppAuthLidoFailed()` + `AppAuthLidoFailed()` ) const receipt = await burner.commitSharesToBurn(ETH(3), { from: lido.address }) @@ -643,7 +643,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { it(`can't recover zero ERC20 amount`, async () => { await assert.revertsWithCustomError( - burner.recoverERC20(mockERC20Token.address, bn(0), { from: voting }), `ErrorZeroRecoveryAmount()` + burner.recoverERC20(mockERC20Token.address, bn(0), { from: voting }), `ZeroRecoveryAmount()` ) }) @@ -670,7 +670,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { // need to use recoverExcessStETH await assert.revertsWithCustomError( burner.recoverERC20(lido.address, StETH(1), { from: voting }), - `ErrorStETHRecoveryWrongFunc()` + `StETHRecoveryWrongFunc()` ) // revert from deployer @@ -755,7 +755,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { ) await assert.revertsWithCustomError( burner.recoverERC721(lido.address, StETH(1), { from: voting }), - `ErrorStETHRecoveryWrongFunc()` + `StETHRecoveryWrongFunc()` ) const receipt = await burner.recoverExcessStETH({ from: voting }) @@ -814,7 +814,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { // try to send 1 ETH, should be reverted with fallback defined reason await assert.revertsWithCustomError( - web3.eth.sendTransaction({ from: anotherAccount, to: burner_addr, value: ETH(1) }), `ErrorDirectETHTransfer()` + web3.eth.sendTransaction({ from: anotherAccount, to: burner_addr, value: ETH(1) }), `DirectETHTransfer()` ) }) }) diff --git a/test/0.8.9/deposit-security-module.test.js b/test/0.8.9/deposit-security-module.test.js index 900dd5ec4..c02f999ee 100644 --- a/test/0.8.9/deposit-security-module.test.js +++ b/test/0.8.9/deposit-security-module.test.js @@ -130,7 +130,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { from: stranger } ), - 'ErrorDeposit("no quorum")' + 'DepositNoQuorum()' ) }) }) @@ -174,7 +174,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN2])] ), - 'ErrorSignature("invalid")' + 'InvalidSignature()' ) }) @@ -189,7 +189,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [] ), - 'ErrorDeposit("no quorum")' + 'DepositNoQuorum()' ) }) @@ -209,7 +209,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'ErrorDeposit("deposit root changed")' + 'DepositRootChanged()' ) }) @@ -228,7 +228,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'ErrorDeposit("nonce changed")' + 'DepositNonceChanged()' ) }) @@ -249,7 +249,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'ErrorDeposit("too frequent")' + 'DepositTooFrequent()' ) }) @@ -270,7 +270,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'ErrorDeposit("inactive module")' + 'DepositInactiveModule()' ) }) @@ -288,7 +288,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { DEPOSIT_CALLDATA, [validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1])] ), - 'ErrorDeposit("unexpected block hash")' + 'DepositUnexpectedBlockHash()' ) }) @@ -298,7 +298,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { depositSecurityModule.depositBufferedEther(block.number, '0x', DEPOSIT_ROOT, STAKING_MODULE, DEPOSIT_NONCE, DEPOSIT_CALLDATA, [ validAttestMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN1]) ]), - 'ErrorDeposit("unexpected block hash")' + 'DepositUnexpectedBlockHash()' ) }) }) @@ -419,7 +419,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { [], { from: stranger } ), - 'ErrorDeposit("no quorum")' + 'DepositNoQuorum()' ) }) it("cannot deposit with guardian's sigs (1,0)", async () => { @@ -439,7 +439,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { signatures, { from: stranger } ), - 'ErrorSignature("not sorted")' + 'SignatureNotSorted()' ) }) @@ -460,7 +460,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { signatures, { from: stranger } ), - 'ErrorSignature("not sorted")' + 'SignatureNotSorted()' ) }) @@ -481,7 +481,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { signatures, { from: stranger } ), - 'ErrorSignature("invalid")' + 'InvalidSignature()' ) }) }) @@ -548,7 +548,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { validPauseMessage.sign(UNRELATED_SIGNER_PRIVATE_KEYS[UNRELATED_SIGNER1]), { from: guardian } ), - 'ErrorPauseIntentExpired()' + 'PauseIntentExpired()' ) }) @@ -560,7 +560,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { stalePauseMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN2]), { from: stranger } ), - 'ErrorPauseIntentExpired()' + 'PauseIntentExpired()' ) }) @@ -572,7 +572,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { stalePauseMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN2]), { from: stranger } ), - 'ErrorStakingModuleIdTooLarge()' + 'StakingModuleIdTooLarge()' ) }) @@ -647,7 +647,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it('cannot be called by non-admin', async () => { await assertRevert( depositSecurityModule.unpauseDeposits(STAKING_MODULE, { from: stranger }), - `ErrorNotAnOwner("${stranger}")` + `NotAnOwner("${stranger}")` ) }) }) @@ -659,7 +659,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it(`addGuardian can't be called by non-admin`, async () => { await assertRevert( depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: stranger }), - `ErrorNotAnOwner("${stranger}")` + `NotAnOwner("${stranger}")` ) }) it(`addGuardian adds a guardian`, async () => { @@ -695,13 +695,13 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { await depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: owner }) await assertRevert( depositSecurityModule.addGuardian(GUARDIAN1, 0, { from: owner }), - `ErrorDuplicateAddress("${GUARDIAN1}")` + `DuplicateAddress("${GUARDIAN1}")` ) }) it(`addGuardians can't be called by non-admin`, async () => { await assertRevert( depositSecurityModule.addGuardians([GUARDIAN1], 0, { from: stranger }), - `ErrorNotAnOwner("${stranger}")` + `NotAnOwner("${stranger}")` ) }) it(`addGuardians adds set of guardians`, async () => { @@ -715,24 +715,24 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it(`addGuardians doesn't add a set with duplicate`, async () => { await assertRevert( depositSecurityModule.addGuardians([GUARDIAN1, GUARDIAN1], 0, { from: owner }), - `ErrorDuplicateAddress("${GUARDIAN1}")` + `DuplicateAddress("${GUARDIAN1}")` ) await depositSecurityModule.addGuardians([GUARDIAN1], 0, { from: owner }) await assertRevert( depositSecurityModule.addGuardians([GUARDIAN1, GUARDIAN2], 0, { from: owner }), - `ErrorDuplicateAddress("${GUARDIAN1}")` + `DuplicateAddress("${GUARDIAN1}")` ) }) it(`removeGuardian can't be called by non-admin`, async () => { await assertRevert( depositSecurityModule.removeGuardian(GUARDIAN1, 0, { from: stranger }), - `ErrorNotAnOwner("${stranger}")` + `NotAnOwner("${stranger}")` ) }) it(`removeGuardian reverts on incorrect address`, async () => { await assertRevert( depositSecurityModule.removeGuardian(GUARDIAN1, 0, { from: owner }), - `ErrorNotAGuardian("${GUARDIAN1}")` + `NotAGuardian("${GUARDIAN1}")` ) }) it(`removeGuardian removes guardian and sets new quorum`, async () => { @@ -821,7 +821,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it(`setGuardianQuorum can't be called by non-admin`, async () => { await assertRevert( depositSecurityModule.setGuardianQuorum(1, { from: stranger }), - `ErrorNotAnOwner("${stranger}")` + `NotAnOwner("${stranger}")` ) }) it(`setGuardianQuorum sets the quorum`, async () => { @@ -866,13 +866,13 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it('not owner cannot change', async () => { await assertRevert( depositSecurityModule.setOwner(stranger, { from: stranger }), - `ErrorNotAnOwner("${stranger}")` + `NotAnOwner("${stranger}")` ) }) it('set new owner to zero address should reverts', async () => { await assertRevert( depositSecurityModule.setOwner(ZERO_ADDRESS, { from: owner }), - 'ErrorZeroAddress("_newOwner")' + 'ZeroAddress("_newOwner")' ) }) it('set new owner by owner', async () => { @@ -886,7 +886,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it('pauseIntentValidityPeriodBlocks should be gt 0', async () => { await assertRevert( depositSecurityModule.setPauseIntentValidityPeriodBlocks(0, { from: owner }), - 'ErrorZeroParameter("pauseIntentValidityPeriodBlocks")' + 'ZeroParameter("pauseIntentValidityPeriodBlocks")' ) }) it('setPauseIntentValidityPeriodBlocks sets new value for pauseIntentValidityPeriodBlocks if called by owner', async () => { @@ -926,7 +926,7 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { it('minDepositBlockDistance should be gt 0', async () => { await assertRevert( depositSecurityModule.setMinDepositBlockDistance(0, { from: owner }), - 'ErrorZeroParameter("minDepositBlockDistance")' + 'ZeroParameter("minDepositBlockDistance")' ) }) it('setMinDepositBlockDistance sets new value for minDepositBlockDistance if called by owner', async () => { diff --git a/test/0.8.9/lido-locator.test.js b/test/0.8.9/lido-locator.test.js index 26c663fd9..030dbd55f 100644 --- a/test/0.8.9/lido-locator.test.js +++ b/test/0.8.9/lido-locator.test.js @@ -64,7 +64,7 @@ contract('LidoLocator', ([deployer, agent]) => { } for (const config of configsWithZeroAddress) { - await assert.reverts(LidoLocator.new(config), 'ErrorZeroAddress()') + await assert.reverts(LidoLocator.new(config), 'ZeroAddress()') } }) }) diff --git a/test/0.8.9/oracle-daemon-config.test.js b/test/0.8.9/oracle-daemon-config.test.js index 19e4b563d..cbe587c46 100644 --- a/test/0.8.9/oracle-daemon-config.test.js +++ b/test/0.8.9/oracle-daemon-config.test.js @@ -60,7 +60,7 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { }) it('reverts while gets all values', async () => { - await assert.revertsWithCustomError(config.getList([defaultKey]), `ErrorValueDoesntExist("${defaultKey}")`) + await assert.revertsWithCustomError(config.getList([defaultKey]), `ValueDoesntExist("${defaultKey}")`) }) }) @@ -72,14 +72,14 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { it("reverts when defaultValue for update doesn't exist", async () => { await assert.revertsWithCustomError( config.update(defaultKey, defaultValue, { from: manager }), - `ErrorValueDoesntExist("${defaultKey}")` + `ValueDoesntExist("${defaultKey}")` ) }) it("reverts when defaultValue for unset doen't exist", async () => { await assert.revertsWithCustomError( config.unset(defaultKey, { from: manager }), - `ErrorValueDoesntExist("${defaultKey}")` + `ValueDoesntExist("${defaultKey}")` ) }) @@ -87,25 +87,25 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { await config.set(defaultKey, defaultValue, { from: manager }) await assert.revertsWithCustomError( config.set(defaultKey, updatedDefaultValue, { from: manager }), - `ErrorValueExists("${defaultKey}")` + `ValueExists("${defaultKey}")` ) }) it('reverts when admin is zero address', async () => { await assert.revertsWithCustomError( OracleDaemonConfig.new(ZERO_ADDRESS, [manager], { from: deployer }), - 'ErrorZeroAddress()' + 'ZeroAddress()' ) }) it('reverts when one of managers is zero address', async () => { - await assert.revertsWithCustomError(OracleDaemonConfig.new(deployer, [manager, ZERO_ADDRESS], { from: deployer }), 'ErrorZeroAddress()') + await assert.revertsWithCustomError(OracleDaemonConfig.new(deployer, [manager, ZERO_ADDRESS], { from: deployer }), 'ZeroAddress()') }) it('revers when empty value passed to set', async () => { await assert.revertsWithCustomError( config.set(defaultKey, '0x', { from: manager }), - `ErrorEmptyValue("${defaultKey}")` + `EmptyValue("${defaultKey}")` ) }) @@ -113,7 +113,7 @@ contract('OracleDaemonConfig', async ([deployer, manager, stranger]) => { await config.set(defaultKey, defaultValue, { from: manager }) await assert.revertsWithCustomError( config.update(defaultKey, '0x', { from: manager }), - `ErrorEmptyValue("${defaultKey}")` + `EmptyValue("${defaultKey}")` ) }) }) diff --git a/test/0.8.9/staking-router-deposits.test.js b/test/0.8.9/staking-router-deposits.test.js index 79eedf986..92e46c004 100644 --- a/test/0.8.9/staking-router-deposits.test.js +++ b/test/0.8.9/staking-router-deposits.test.js @@ -61,7 +61,7 @@ contract('StakingRouter', ([depositor, stranger]) => { await assert.revertsWithCustomError( stakingRouter.deposit(maxDepositsCount, curated.id, '0x', { from: voting }), - 'ErrorAppAuthLidoFailed()' + 'AppAuthLidoFailed()' ) }) diff --git a/test/0.8.9/staking-router.test.js b/test/0.8.9/staking-router.test.js index 6d80d6d67..883b5566e 100644 --- a/test/0.8.9/staking-router.test.js +++ b/test/0.8.9/staking-router.test.js @@ -43,8 +43,8 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('init fails on wrong input', async () => { - await assert.revertsWithCustomError(app.initialize(ZERO_ADDRESS, lido, wc, { from: deployer }), 'ErrorZeroAddress("_admin")') - await assert.revertsWithCustomError(app.initialize(admin, ZERO_ADDRESS, wc, { from: deployer }), 'ErrorZeroAddress("_lido")') + await assert.revertsWithCustomError(app.initialize(ZERO_ADDRESS, lido, wc, { from: deployer }), 'ZeroAddress("_admin")') + await assert.revertsWithCustomError(app.initialize(admin, ZERO_ADDRESS, wc, { from: deployer }), 'ZeroAddress("_lido")') }) it('initialized correctly', async () => { @@ -174,7 +174,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('deposit fails', async () => { await assert.revertsWithCustomError( stakingRouterImplementation.deposit(100, 0, '0x00', { from: stranger }), - `ErrorAppAuthLidoFailed()` + `AppAuthLidoFailed()` ) }) }) @@ -218,7 +218,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('direct transfer fails', async () => { const value = 100 - await assert.revertsWithCustomError(app.sendTransaction({ value, from: deployer }), `ErrorDirectETHTransfer()`) + await assert.revertsWithCustomError(app.sendTransaction({ value, from: deployer }), `DirectETHTransfer()`) }) it('getStakingModuleNonce', async () => { @@ -228,15 +228,15 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('getStakingModuleNonce reverts when staking module id too large', async () => { - await assert.revertsWithCustomError(app.getStakingModuleNonce(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModuleNonce(UINT24_MAX), 'StakingModuleIdTooLarge()') }) it('getStakingModuleLastDepositBlock reverts when staking module id too large', async () => { - await assert.revertsWithCustomError(app.getStakingModuleLastDepositBlock(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModuleLastDepositBlock(UINT24_MAX), 'StakingModuleIdTooLarge()') }) it('getStakingModuleActiveValidatorsCount reverts when staking module id too large', async () => { - await assert.revertsWithCustomError(app.getStakingModuleActiveValidatorsCount(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModuleActiveValidatorsCount(UINT24_MAX), 'StakingModuleIdTooLarge()') }) it('getStakingModuleActiveValidatorsCount', async () => { @@ -271,7 +271,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { } await assert.revertsWithCustomError( app.addStakingModule('Test module', stakingModule.address, 100, 100, 100, { from: appManager }), - `ErrorStakingModulesLimitExceeded()` + `StakingModulesLimitExceeded()` ) }) }) @@ -336,7 +336,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { stakingModulesParams[0].treasuryFee, { from: appManager } ), - `ErrorValueOver100Percent("_targetShare")` + `ValueOver100Percent("_targetShare")` ) }) @@ -345,7 +345,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.addStakingModule(stakingModulesParams[0].name, stakingModule1.address, stakingModulesParams[0].targetShare, 5000, 5001, { from: appManager }), - `ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee")` + `ValueOver100Percent("_stakingModuleFee + _treasuryFee")` ) }) @@ -361,7 +361,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { from: appManager } ), - `ErrorZeroAddress("_stakingModuleAddress")` + `ZeroAddress("_stakingModuleAddress")` ) }) @@ -378,7 +378,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { from: appManager } ), - `ErrorStakingModuleWrongName()` + `StakingModuleWrongName()` ) // check length > 32 symbols @@ -393,7 +393,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { from: appManager } ), - `ErrorStakingModuleWrongName()` + `StakingModuleWrongName()` ) }) @@ -433,11 +433,11 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await app.getStakingModuleIsDepositsPaused(stakingModulesParams[0].expectedModuleId), false) assert.equals(await app.getStakingModuleIsActive(stakingModulesParams[0].expectedModuleId), true) - await assert.revertsWithCustomError(app.getStakingModule(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') - await assert.revertsWithCustomError(app.getStakingModuleStatus(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') - await assert.revertsWithCustomError(app.getStakingModuleIsStopped(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') - await assert.revertsWithCustomError(app.getStakingModuleIsDepositsPaused(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') - await assert.revertsWithCustomError(app.getStakingModuleIsActive(UINT24_MAX), 'ErrorStakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModule(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModuleStatus(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModuleIsStopped(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModuleIsDepositsPaused(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError(app.getStakingModuleIsActive(UINT24_MAX), 'StakingModuleIdTooLarge()') const module = await app.getStakingModule(stakingModulesParams[0].expectedModuleId) @@ -550,7 +550,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { from: appManager } ), - `ErrorStakingModuleIdTooLarge()` + `StakingModuleIdTooLarge()` ) }) @@ -565,7 +565,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { from: appManager } ), - `ErrorValueOver100Percent("_targetShare")` + `ValueOver100Percent("_targetShare")` ) }) @@ -574,7 +574,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.updateStakingModule(stakingModulesParams[0].expectedModuleId, stakingModulesParams[0].targetShare + 1, 5000, 5001, { from: appManager }), - `ErrorValueOver100Percent("_stakingModuleFee + _treasuryFee")` + `ValueOver100Percent("_stakingModuleFee + _treasuryFee")` ) }) @@ -625,7 +625,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.setStakingModuleStatus(UINT24_MAX, StakingModuleStatus.Stopped, { from: appManager }), - `ErrorStakingModuleIdTooLarge()` + `StakingModuleIdTooLarge()` ) }) @@ -635,7 +635,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, module.status, { from: appManager }), - `ErrorStakingModuleStatusTheSame()` + `StakingModuleStatusTheSame()` ) }) @@ -665,7 +665,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.pauseStakingModule(UINT24_MAX, { from: appManager }), - `ErrorStakingModuleIdTooLarge()` + `StakingModuleIdTooLarge()` ) }) @@ -681,7 +681,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager }), - `ErrorStakingModuleNotActive()` + `StakingModuleNotActive()` ) await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.DepositsPaused, { from: appManager @@ -690,7 +690,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager }), - `ErrorStakingModuleNotActive()` + `StakingModuleNotActive()` ) }) @@ -712,14 +712,14 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('deposit fails', async () => { await assert.revertsWithCustomError( app.deposit(100, UINT24_MAX, '0x00', { value: 100, from: lido }), - 'ErrorStakingModuleIdTooLarge()' + 'StakingModuleIdTooLarge()' ) }) it('deposit fails', async () => { await assert.revertsWithCustomError( app.deposit(100, stakingModulesParams[0].expectedModuleId, '0x00', { value: 100, from: lido }), - 'ErrorStakingModuleNotActive()' + 'StakingModuleNotActive()' ) }) @@ -744,7 +744,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.resumeStakingModule(UINT24_MAX, { from: appManager }), - `ErrorStakingModuleIdTooLarge()` + `StakingModuleIdTooLarge()` ) }) @@ -756,7 +756,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager }), - `ErrorStakingModuleNotPaused()` + `StakingModuleNotPaused()` ) await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { from: appManager @@ -765,7 +765,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { app.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager }), - `ErrorStakingModuleNotPaused()` + `StakingModuleNotPaused()` ) }) From d593a0a46c325e9f603bff1354446fb2a5f491a1 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 15:39:35 +0300 Subject: [PATCH 56/82] fix: precalc Lido constants keccak256 --- contracts/0.4.24/Lido.sol | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 5522d0ffc..336f454d9 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -145,10 +145,16 @@ contract Lido is Versioned, StETHPermit, AragonApp { using StakeLimitUtils for StakeLimitState.Data; /// ACL - bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE"); - bytes32 public constant RESUME_ROLE = keccak256("RESUME_ROLE"); - bytes32 public constant STAKING_PAUSE_ROLE = keccak256("STAKING_PAUSE_ROLE"); - bytes32 public constant STAKING_CONTROL_ROLE = keccak256("STAKING_CONTROL_ROLE"); + bytes32 public constant PAUSE_ROLE = + 0x139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d; // keccak256("PAUSE_ROLE"); + bytes32 public constant RESUME_ROLE = + 0x2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c7; // keccak256("RESUME_ROLE"); + bytes32 public constant STAKING_PAUSE_ROLE = + 0x84ea57490227bc2be925c684e2a367071d69890b629590198f4125a018eb1de8; // keccak256("STAKING_PAUSE_ROLE") + bytes32 public constant STAKING_CONTROL_ROLE = + 0xa42eee1333c0758ba72be38e728b6dadb32ea767de5b4ddbaea1dae85b1b051f; // keccak256("STAKING_CONTROL_ROLE") + bytes32 public constant UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE = + 0xe6dc5d79630c61871e99d341ad72c5a052bed2fc8c79e5a4480a7cd31117576c; // keccak256("UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE") uint256 private constant DEPOSIT_SIZE = 32 ether; uint256 public constant TOTAL_BASIS_POINTS = 10000; @@ -156,21 +162,28 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 private constant DONT_FINALIZE_WITHDRAWALS = 0; /// @dev storage slot position for the Lido protocol contracts locator - bytes32 internal constant LIDO_LOCATOR_POSITION = keccak256("lido.Lido.lidoLocator"); + bytes32 internal constant LIDO_LOCATOR_POSITION = + 0x9ef78dff90f100ea94042bd00ccb978430524befc391d3e510b5f55ff3166df7; // keccak256("lido.Lido.lidoLocator") /// @dev storage slot position of the staking rate limit structure - bytes32 internal constant STAKING_STATE_POSITION = keccak256("lido.Lido.stakeLimit"); + bytes32 internal constant STAKING_STATE_POSITION = + 0xa3678de4a579be090bed1177e0a24f77cc29d181ac22fd7688aca344d8938015; // keccak256("lido.Lido.stakeLimit"); /// @dev amount of Ether (on the current Ethereum side) buffered on this smart contract balance - bytes32 internal constant BUFFERED_ETHER_POSITION = keccak256("lido.Lido.bufferedEther"); + bytes32 internal constant BUFFERED_ETHER_POSITION = + 0xed310af23f61f96daefbcd140b306c0bdbf8c178398299741687b90e794772b0; // keccak256("lido.Lido.bufferedEther"); /// @dev number of deposited validators (incrementing counter of deposit operations). - bytes32 internal constant DEPOSITED_VALIDATORS_POSITION = keccak256("lido.Lido.depositedValidators"); + bytes32 internal constant DEPOSITED_VALIDATORS_POSITION = + 0xe6e35175eb53fc006520a2a9c3e9711a7c00de6ff2c32dd31df8c5a24cac1b5c; // keccak256("lido.Lido.depositedValidators"); /// @dev total amount of ether on Consensus Layer (sum of all the balances of Lido validators) // "beacon" in the `keccak256()` parameter is staying here for compatibility reason - bytes32 internal constant CL_BALANCE_POSITION = keccak256("lido.Lido.beaconBalance"); + bytes32 internal constant CL_BALANCE_POSITION = + 0xa66d35f054e68143c18f32c990ed5cb972bb68a68f500cd2dd3a16bbf3686483; // keccak256("lido.Lido.beaconBalance"); /// @dev number of Lido's validators available in the Consensus Layer state // "beacon" in the `keccak256()` parameter is staying here for compatibility reason - bytes32 internal constant CL_VALIDATORS_POSITION = keccak256("lido.Lido.beaconValidators"); + bytes32 internal constant CL_VALIDATORS_POSITION = + 0x9f70001d82b6ef54e9d3725b46581c3eb9ee3aa02b941b6aa54d678a9ca35b10; // keccak256("lido.Lido.beaconValidators"); /// @dev Just a counter of total amount of execution layer rewards received by Lido contract. Not used in the logic. - bytes32 internal constant TOTAL_EL_REWARDS_COLLECTED_POSITION = keccak256("lido.Lido.totalELRewardsCollected"); + bytes32 internal constant TOTAL_EL_REWARDS_COLLECTED_POSITION = + 0xafe016039542d12eec0183bb0b1ffc2ca45b027126a494672fba4154ee77facb; // keccak256("lido.Lido.totalELRewardsCollected"); // Staking was paused (don't accept user's ether submits) event StakingPaused(); From 0cf616c2a790f83c295fc6b2a25d7de98766451d Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 15:41:50 +0300 Subject: [PATCH 57/82] feat: add unsafeModifyDepositedValidators --- contracts/0.4.24/Lido.sol | 30 ++++++++++++++++++++++++++---- lib/abi/Lido.json | 2 +- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 336f454d9..dd2960f2d 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -201,6 +201,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 postCLValidators ); + // Emits when var at `DEPOSITED_VALIDATORS_POSITION` changed + event DepositedValidatorsChanged( + uint256 depositedValidators + ); + // Emits when oracle accounting report processed event ETHDistributed( uint256 indexed reportTimestamp, @@ -592,6 +597,23 @@ contract Lido is Versioned, StETHPermit, AragonApp { ); } + /** + * @notice Unsafely change deposited validators + * + * The method unsafely changes deposited validator counter. + * Can be required when onboarding external validators to Lido + * (i.e., had deposited before and rotated their type-0x00 withdrawal credentials to Lido) + * + * @param _newDepositedValidators new value + */ + function unsafeChangeDepositedValidators(uint256 _newDepositedValidators) { + _auth(UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE); + + DEPOSITED_VALIDATORS_POSITION.setStorageUint256(_newDepositedValidators); + + emit DepositedValidatorsChanged(_newDepositedValidators); + } + /** * @notice Overrides default AragonApp behaviour to disallow recovery. */ @@ -662,11 +684,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { require(_stakingModuleId <= uint24(-1), "STAKING_MODULE_ID_TOO_LARGE"); require(canDeposit(), "CAN_NOT_DEPOSIT"); - IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(locator.withdrawalQueue()); - uint256 bufferedEth = _getBufferedEther(); // we dont deposit funds that will go to withdrawals - uint256 withdrawalReserve = withdrawalQueue.unfinalizedStETH(); + uint256 withdrawalReserve = IWithdrawalQueue(locator.withdrawalQueue()).unfinalizedStETH(); if (bufferedEth > withdrawalReserve) { bufferedEth = bufferedEth.sub(withdrawalReserve); @@ -686,7 +706,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { assert(depositedAmount <= depositableEth); if (depositsCount > 0) { - DEPOSITED_VALIDATORS_POSITION.setStorageUint256(DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(depositsCount)); + uint256 newDepositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(depositsCount); + DEPOSITED_VALIDATORS_POSITION.setStorageUint256(newDepositedValidators); + emit DepositedValidatorsChanged(newDepositedValidators); _markAsUnbuffered(depositedAmount); assert(_getUnaccountedEther() == unaccountedEth); diff --git a/lib/abi/Lido.json b/lib/abi/Lido.json index a65ccdc22..137b0ca7c 100644 --- a/lib/abi/Lido.json +++ b/lib/abi/Lido.json @@ -1 +1 @@ -[{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_CONTROL_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ethAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStakingPaused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxStakeLimit","type":"uint256"},{"name":"_stakeLimitIncreasePerBlock","type":"uint256"}],"name":"setStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"RESUME_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalPooledEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTreasury","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBufferedEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveELRewards","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentStakeLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakeLimitFullInfo","outputs":[{"name":"isStakingPaused","type":"bool"},{"name":"isStakingLimitSet","type":"bool"},{"name":"currentStakeLimit","type":"uint256"},{"name":"maxStakeLimit","type":"uint256"},{"name":"maxStakeLimitGrowthBlocks","type":"uint256"},{"name":"prevStakeLimit","type":"uint256"},{"name":"prevStakeBlockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFeeDistribution","outputs":[{"name":"treasuryFeeBasisPoints","type":"uint16"},{"name":"insuranceFeeBasisPoints","type":"uint16"},{"name":"operatorsFeeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"receiveWithdrawals","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_sharesAmount","type":"uint256"}],"name":"getPooledEthByShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"nonces","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_referral","type":"address"}],"name":"submit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxDepositsCount","type":"uint256"},{"name":"_stakingModuleId","type":"uint256"},{"name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconStat","outputs":[{"name":"depositedValidators","type":"uint256"},{"name":"beaconValidators","type":"uint256"},{"name":"beaconBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_reportTimestamp","type":"uint256"},{"name":"_timeElapsed","type":"uint256"},{"name":"_clValidators","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_withdrawalVaultBalance","type":"uint256"},{"name":"_elRewardsVaultBalance","type":"uint256"},{"name":"_lastFinalizableRequestId","type":"uint256"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"postTotalPooledEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"withdrawals","type":"uint256"},{"name":"elRewards","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveStakingRouterDepositRemainder","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getFee","outputs":[{"name":"totalFee","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLidoLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canDeposit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalELRewardsCollected","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[],"name":"StakingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxStakeLimit","type":"uint256"},{"indexed":false,"name":"stakeLimitIncreasePerBlock","type":"uint256"}],"name":"StakingLimitSet","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingLimitRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLValidators","type":"uint256"},{"indexed":false,"name":"postCLValidators","type":"uint256"}],"name":"CLValidatorsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLBalance","type":"uint256"},{"indexed":false,"name":"postCLBalance","type":"uint256"},{"indexed":false,"name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"name":"executionLayerRewardsWithdrawn","type":"uint256"},{"indexed":false,"name":"postBufferedEther","type":"uint256"}],"name":"ETHDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"preTotalShares","type":"uint256"},{"indexed":false,"name":"preTotalEther","type":"uint256"},{"indexed":false,"name":"postTotalShares","type":"uint256"},{"indexed":false,"name":"postTotalEther","type":"uint256"},{"indexed":false,"name":"sharesMintedAsFees","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"lidoLocator","type":"address"}],"name":"LidoLocatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"ELRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unbuffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"StakingRouterDepositRemainderReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"eip712StETH","type":"address"}],"name":"EIP712StETHInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[],"name":"resume","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_CONTROL_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_ethAmount","type":"uint256"}],"name":"getSharesByPooledEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStakingPaused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxStakeLimit","type":"uint256"},{"name":"_stakeLimitIncreasePerBlock","type":"uint256"}],"name":"setStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"RESUME_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalPooledEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newDepositedValidators","type":"uint256"}],"name":"unsafeChangeDepositedValidators","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTreasury","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isStopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBufferedEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lidoLocator","type":"address"},{"name":"_eip712StETH","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveELRewards","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentStakeLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakeLimitFullInfo","outputs":[{"name":"isStakingPaused","type":"bool"},{"name":"isStakingLimitSet","type":"bool"},{"name":"currentStakeLimit","type":"uint256"},{"name":"maxStakeLimit","type":"uint256"},{"name":"maxStakeLimitGrowthBlocks","type":"uint256"},{"name":"prevStakeLimit","type":"uint256"},{"name":"prevStakeBlockNumber","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferSharesFrom","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFeeDistribution","outputs":[{"name":"treasuryFeeBasisPoints","type":"uint16"},{"name":"insuranceFeeBasisPoints","type":"uint16"},{"name":"operatorsFeeBasisPoints","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"receiveWithdrawals","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_sharesAmount","type":"uint256"}],"name":"getPooledEthByShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"nonces","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOracle","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_sharesAmount","type":"uint256"}],"name":"transferShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_referral","type":"address"}],"name":"submit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_recipient","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxDepositsCount","type":"uint256"},{"name":"_stakingModuleId","type":"uint256"},{"name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBeaconStat","outputs":[{"name":"depositedValidators","type":"uint256"},{"name":"beaconValidators","type":"uint256"},{"name":"beaconBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_reportTimestamp","type":"uint256"},{"name":"_timeElapsed","type":"uint256"},{"name":"_clValidators","type":"uint256"},{"name":"_clBalance","type":"uint256"},{"name":"_withdrawalVaultBalance","type":"uint256"},{"name":"_elRewardsVaultBalance","type":"uint256"},{"name":"_lastFinalizableRequestId","type":"uint256"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"postTotalPooledEther","type":"uint256"},{"name":"postTotalShares","type":"uint256"},{"name":"withdrawals","type":"uint256"},{"name":"elRewards","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"receiveStakingRouterDepositRemainder","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getFee","outputs":[{"name":"totalFee","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTotalShares","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLidoLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canDeposit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_PAUSE_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pauseStaking","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getTotalELRewardsCollected","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[],"name":"StakingPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"maxStakeLimit","type":"uint256"},{"indexed":false,"name":"stakeLimitIncreasePerBlock","type":"uint256"}],"name":"StakingLimitSet","type":"event"},{"anonymous":false,"inputs":[],"name":"StakingLimitRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLValidators","type":"uint256"},{"indexed":false,"name":"postCLValidators","type":"uint256"}],"name":"CLValidatorsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"depositedValidators","type":"uint256"}],"name":"DepositedValidatorsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"preCLBalance","type":"uint256"},{"indexed":false,"name":"postCLBalance","type":"uint256"},{"indexed":false,"name":"withdrawalsWithdrawn","type":"uint256"},{"indexed":false,"name":"executionLayerRewardsWithdrawn","type":"uint256"},{"indexed":false,"name":"postBufferedEther","type":"uint256"}],"name":"ETHDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"reportTimestamp","type":"uint256"},{"indexed":false,"name":"timeElapsed","type":"uint256"},{"indexed":false,"name":"preTotalShares","type":"uint256"},{"indexed":false,"name":"preTotalEther","type":"uint256"},{"indexed":false,"name":"postTotalShares","type":"uint256"},{"indexed":false,"name":"postTotalEther","type":"uint256"},{"indexed":false,"name":"sharesMintedAsFees","type":"uint256"}],"name":"TokenRebased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"lidoLocator","type":"address"}],"name":"LidoLocatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"ELRewardsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"WithdrawalsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"referral","type":"address"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unbuffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"StakingRouterDepositRemainderReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"eip712StETH","type":"address"}],"name":"EIP712StETHInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"sharesValue","type":"uint256"}],"name":"TransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"preRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"postRebaseTokenAmount","type":"uint256"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"SharesBurnt","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"}] \ No newline at end of file From 4d81784617c93700936b8a8e7e137739025a4847 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 13 Feb 2023 16:55:58 +0400 Subject: [PATCH 58/82] Add methods for a summary of module and node operator. Rename batch methods --- contracts/0.8.9/StakingRouter.sol | 208 +++++++++++++++++++++--------- lib/abi/StakingRouter.json | 2 +- 2 files changed, 145 insertions(+), 65 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 3ae1fd511..c68854a32 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -535,121 +535,201 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version return StakingModuleStatus(_getStakingModuleById(_stakingModuleId).status); } - struct ValidatorsReport { - uint256 totalExited; - uint256 totalDeposited; - uint256 depositable; + /// @notice A summary of the staking module's validators + struct StakingModuleSummary { + /// @notice The total number of validators in the EXITED state on the Consensus Layer + /// @dev This value can't decrease in normal conditions + uint256 totalExitedValidators; + + /// @notice The total number of validators deposited via the official Deposit Contract + /// @dev This value is a cumulative counter: even when the validator goes into EXITED state this + /// counter is not decreasing + uint256 totalDepositedValidators; + + /// @notice The number of validators in the set available for deposit + uint256 depositableValidatorsCount; } - struct StakingModuleReport { - StakingModule state; + /// @notice A summary of node operator and its validators + struct NodeOperatorSummary { + /// @notice Shows whether the current target limit applied to the node operator + bool isTargetLimitActive; + + /// @notice Relative target active validators limit for operator + uint256 targetValidatorsCount; + + /// @notice The number of validators with an expired request to exit time + uint256 stuckValidatorsCount; + + /// @notice The number of validators that can't be withdrawn, but deposit costs were + /// compensated to the Lido by the node operator + uint256 refundedValidatorsCount; + + /// @notice A time when the penalty for stuck validators stops applying to node operator rewards + uint256 stuckPenaltyEndTimestamp; + + /// @notice The total number of validators in the EXITED state on the Consensus Layer + /// @dev This value can't decrease in normal conditions + uint256 totalExitedValidators; + + /// @notice The total number of validators deposited via the official Deposit Contract + /// @dev This value is a cumulative counter: even when the validator goes into EXITED state this + /// counter is not decreasing + uint256 totalDepositedValidators; + + /// @notice The number of validators in the set available for deposit + uint256 depositableValidatorsCount; + } + + /// @notice Returns all-validators summary in the staking module + /// @param _stakingModuleId id of the staking module to return summary for + function getStakingModuleSummary(uint256 _stakingModuleId) + public + view + returns (StakingModuleSummary memory summary) + { + StakingModule memory stakingModuleState = getStakingModule(_stakingModuleId); + IStakingModule stakingModule = IStakingModule(stakingModuleState.stakingModuleAddress); + ( + summary.totalExitedValidators, + summary.totalDepositedValidators, + summary.depositableValidatorsCount + ) = stakingModule.getStakingModuleSummary(); + } + + + /// @notice Returns node operator summary from the staking module + /// @param _stakingModuleId id of the staking module where node operator is onboarded + /// @param _nodeOperatorId id of the node operator to return summary for + function getNodeOperatorSummary(uint256 _stakingModuleId, uint256 _nodeOperatorId) + public + view + returns (NodeOperatorSummary memory summary) + { + StakingModule memory stakingModuleState = getStakingModule(_stakingModuleId); + IStakingModule stakingModule = IStakingModule(stakingModuleState.stakingModuleAddress); + /// @dev using intermediate variables below due to "Stack too deep" error in case of + /// assigning directly into the NodeOperatorSummary struct + ( + bool isTargetLimitActive, + uint256 targetValidatorsCount, + uint256 stuckValidatorsCount, + uint256 refundedValidatorsCount, + uint256 stuckPenaltyEndTimestamp, + uint256 totalExitedValidators, + uint256 totalDepositedValidators, + uint256 depositableValidatorsCount + ) = stakingModule.getNodeOperatorSummary(_nodeOperatorId); + summary.isTargetLimitActive = isTargetLimitActive; + summary.targetValidatorsCount = targetValidatorsCount; + summary.stuckValidatorsCount = stuckValidatorsCount; + summary.refundedValidatorsCount = refundedValidatorsCount; + summary.stuckPenaltyEndTimestamp = stuckPenaltyEndTimestamp; + summary.totalExitedValidators = totalExitedValidators; + summary.totalDepositedValidators = totalDepositedValidators; + summary.depositableValidatorsCount = depositableValidatorsCount; + } + + /// @notice A collection of the staking module data stored across the StakingRouter and the + /// staking module contract + /// @dev This data, first of all, is designed for off-chain usage and might be redundant for + /// on-chain calls. Give preference for dedicated methods for gas-efficient on-chain calls + struct StakingModuleDigest { + /// @notice The number of node operators registered in the staking module uint256 nodeOperatorsCount; + /// @notice The number of node operators registered in the staking module in active state uint256 activeNodeOperatorsCount; - ValidatorsReport validatorsReport; + /// @notice The current state of the staking module taken from the StakingRouter + StakingModule state; + /// @notice A summary of the staking module's validators + StakingModuleSummary summary; } - - struct NodeOperatorReport { + /// @notice A collection of the node operator data stored in the staking module + /// @dev This data, first of all, is designed for off-chain usage and might be redundant for + /// on-chain calls. Give preference for dedicated methods for gas-efficient on-chain calls + struct NodeOperatorDigest { + /// @notice id of the node operator uint256 id; + /// @notice Shows whether the node operator is active or not bool isActive; - bool isTargetLimitActive; - uint256 targetValidatorsCount; - uint256 stuckValidatorsCount; - uint256 refundedValidatorsCount; - uint256 stuckPenaltyEndTimestamp; - ValidatorsReport validatorsReport; + /// @notice A summary of node operator and its validators + NodeOperatorSummary summary; } + /// @notice Returns staking module digest for each staking module registered in the staking router /// @dev WARNING: This method is not supposed to be used for onchain calls due to high gas costs /// for data aggregation - function getAllStakingModuleReports() external view returns (StakingModuleReport[] memory) { - return getStakingModuleReports(getStakingModuleIds()); + function getAllStakingModuleDigests() external view returns (StakingModuleDigest[] memory) { + return getStakingModuleDigests(getStakingModuleIds()); } + /// @notice Returns staking module digest for passed staking module ids + /// @param _stakingModuleIds ids of the staking modules to return data for /// @dev WARNING: This method is not supposed to be used for onchain calls due to high gas costs /// for data aggregation - function getStakingModuleReports(uint256[] memory _stakingModuleIds) + function getStakingModuleDigests(uint256[] memory _stakingModuleIds) public view - returns (StakingModuleReport[] memory reports) + returns (StakingModuleDigest[] memory digests) { - reports = new StakingModuleReport[](_stakingModuleIds.length); + digests = new StakingModuleDigest[](_stakingModuleIds.length); for (uint256 i = 0; i < _stakingModuleIds.length; ++i) { StakingModule memory stakingModuleState = getStakingModule(_stakingModuleIds[i]); IStakingModule stakingModule = IStakingModule(stakingModuleState.stakingModuleAddress); - ( - uint256 totalExitedValidators, - uint256 totalDepositedValidators, - uint256 depositableValidatorsCount - ) = stakingModule.getStakingModuleSummary(); - reports[i] = StakingModuleReport({ - state: stakingModuleState, + digests[i] = StakingModuleDigest({ nodeOperatorsCount: stakingModule.getNodeOperatorsCount(), activeNodeOperatorsCount: stakingModule.getActiveNodeOperatorsCount(), - validatorsReport: ValidatorsReport({ - totalExited: totalExitedValidators, - totalDeposited: totalDepositedValidators, - depositable: depositableValidatorsCount - }) + state: stakingModuleState, + summary: getStakingModuleSummary(_stakingModuleIds[i]) }); } } + /// @notice Returns node operator digest for each node operator registered in the given staking module + /// @param _stakingModuleId id of the staking module to return data for /// @dev WARNING: This method is not supposed to be used for onchain calls due to high gas costs /// for data aggregation - function getAllNodeOperatorReports(uint256 _stakingModuleId) external view returns (NodeOperatorReport[] memory) { + function getAllNodeOperatorDigests(uint256 _stakingModuleId) external view returns (NodeOperatorDigest[] memory) { IStakingModule stakingModule = IStakingModule(_getStakingModuleAddressById(_stakingModuleId)); uint256 nodeOperatorsCount = stakingModule.getNodeOperatorsCount(); - return getNodeOperatorReports(_stakingModuleId, 0, nodeOperatorsCount); + return getNodeOperatorDigests(_stakingModuleId, 0, nodeOperatorsCount); } + /// @notice Returns node operator digest for passed node operator ids in the given staking module + /// @param _stakingModuleId id of the staking module where node operators registered + /// @param _offset node operators offset starting with 0 + /// @param _limit the max number of node operators to return /// @dev WARNING: This method is not supposed to be used for onchain calls due to high gas costs /// for data aggregation - function getNodeOperatorReports( + function getNodeOperatorDigests( uint256 _stakingModuleId, uint256 _offset, uint256 _limit - ) public view returns (NodeOperatorReport[] memory summaries) { + ) public view returns (NodeOperatorDigest[] memory) { IStakingModule stakingModule = IStakingModule(_getStakingModuleAddressById(_stakingModuleId)); uint256[] memory nodeOperatorIds = stakingModule.getNodeOperatorIds(_offset, _limit); - return getNodeOperatorReports(_stakingModuleId, nodeOperatorIds); + return getNodeOperatorDigests(_stakingModuleId, nodeOperatorIds); } + /// @notice Returns node operator digest for a slice of node operators registered in the given + /// staking module + /// @param _stakingModuleId id of the staking module where node operators registered + /// @param _nodeOperatorIds ids of the node operators to return data for /// @dev WARNING: This method is not supposed to be used for onchain calls due to high gas costs /// for data aggregation - function getNodeOperatorReports(uint256 _stakingModuleId, uint256[] memory _nodeOperatorIds) + function getNodeOperatorDigests(uint256 _stakingModuleId, uint256[] memory _nodeOperatorIds) public view - returns (NodeOperatorReport[] memory summaries) + returns (NodeOperatorDigest[] memory digests) { IStakingModule stakingModule = IStakingModule(_getStakingModuleAddressById(_stakingModuleId)); - summaries = new NodeOperatorReport[](_nodeOperatorIds.length); + digests = new NodeOperatorDigest[](_nodeOperatorIds.length); for (uint256 i = 0; i < _nodeOperatorIds.length; ++i) { - bool isActive = stakingModule.getNodeOperatorIsActive(_nodeOperatorIds[i]); - - ( - bool isTargetLimitActive, - uint256 targetValidatorsCount, - uint256 stuckValidatorsCount, - uint256 refundedValidatorsCount, - uint256 stuckPenaltyEndTimestamp, - uint256 totalExitedValidators, - uint256 totalDepositedValidators, - uint256 depositableValidatorsCount - ) = stakingModule.getNodeOperatorSummary(i); - summaries[i] = NodeOperatorReport({ - isActive: isActive, + digests[i] = NodeOperatorDigest({ id: _nodeOperatorIds[i], - isTargetLimitActive: isTargetLimitActive, - targetValidatorsCount: targetValidatorsCount, - stuckValidatorsCount: stuckValidatorsCount, - refundedValidatorsCount: refundedValidatorsCount, - stuckPenaltyEndTimestamp: stuckPenaltyEndTimestamp, - validatorsReport: ValidatorsReport({ - totalExited: totalExitedValidators, - totalDeposited: totalDepositedValidators, - depositable: depositableValidatorsCount - }) + isActive: stakingModule.getNodeOperatorIsActive(_nodeOperatorIds[i]), + summary: getNodeOperatorSummary(_stakingModuleId, _nodeOperatorIds[i]) }); } } diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index 217b9bcb2..eadd0ae03 100644 --- a/lib/abi/StakingRouter.json +++ b/lib/abi/StakingRouter.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_depositContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AppAuthLidoFailed","type":"error"},{"inputs":[],"name":"DepositContractZeroAddress","type":"error"},{"inputs":[],"name":"DirectETHTransfer","type":"error"},{"inputs":[],"name":"EmptyWithdrawalsCredentials","type":"error"},{"inputs":[],"name":"ExitedValidatorsCountCannotDecrease","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidReportData","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NotExpectedBalance","type":"error"},{"inputs":[],"name":"StakingModuleIdTooLarge","type":"error"},{"inputs":[],"name":"StakingModuleNotActive","type":"error"},{"inputs":[],"name":"StakingModuleNotPaused","type":"error"},{"inputs":[],"name":"StakingModuleStatusTheSame","type":"error"},{"inputs":[],"name":"StakingModuleUnregistered","type":"error"},{"inputs":[],"name":"StakingModuleWrongName","type":"error"},{"inputs":[],"name":"StakingModulesLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpStuckValidatorsCount","type":"uint256"}],"name":"UnexpectedCurrentValidatorsCount","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ValueOver100Percent","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"stakingModule","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"createdBy","type":"address"}],"name":"StakingModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unreportedExitedValidatorsCount","type":"uint256"}],"name":"StakingModuleExitedValidatorsIncompleteReporting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingModuleFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"treasuryFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"enum StakingRouter.StakingModuleStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetShare","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleTargetShareSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakingRouterETHDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"WithdrawalCredentialsSet","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_PRECISION_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_WITHDRAWAL_CREDENTIALS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_REWARDS_MINTED_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_MANAGE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNSAFE_SET_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_stakingModuleAddress","type":"address"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"addStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDepositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getAllNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllStakingModuleReports","outputs":[{"components":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleReport[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositsCount","type":"uint256"}],"name":"getDepositsAllocation","outputs":[{"internalType":"uint256","name":"allocated","type":"uint256"},{"internalType":"uint256[]","name":"allocations","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExitedValidatorsCountAcrossAllModules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLido","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256[]","name":"_nodeOperatorIds","type":"uint256[]"}],"name":"getNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"summaries","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"getNodeOperatorReports","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorReport[]","name":"summaries","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistribution","outputs":[{"internalType":"uint96","name":"modulesFee","type":"uint96"},{"internalType":"uint96","name":"treasuryFee","type":"uint96"},{"internalType":"uint256","name":"basePrecision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistributionE4Precision","outputs":[{"internalType":"uint16","name":"modulesFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModule","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleActiveValidatorsCount","outputs":[{"internalType":"uint256","name":"activeValidatorsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModuleIds","outputs":[{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsDepositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleLastDepositBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleMaxDepositsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"}],"name":"getStakingModuleReports","outputs":[{"components":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint256","name":"totalExited","type":"uint256"},{"internalType":"uint256","name":"totalDeposited","type":"uint256"},{"internalType":"uint256","name":"depositable","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsReport","name":"validatorsReport","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleReport[]","name":"reports","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleStatus","outputs":[{"internalType":"enum StakingRouter.StakingModuleStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModules","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule[]","name":"res","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingRewardsDistribution","outputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"},{"internalType":"uint96[]","name":"stakingModuleFees","type":"uint96[]"},{"internalType":"uint96","name":"totalFee","type":"uint96"},{"internalType":"uint256","name":"precisionPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFeeE4Precision","outputs":[{"internalType":"uint16","name":"totalFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_lido","type":"address"},{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"pauseStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_totalShares","type":"uint256[]"}],"name":"reportRewardsMinted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_exitedValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleExitedValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_stuckValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleStuckValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"resumeStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"enum StakingRouter.StakingModuleStatus","name":"_status","type":"uint8"}],"name":"setStakingModuleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"setWithdrawalCredentials","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_triggerUpdateFinish","type":"bool"},{"components":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorStuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorStuckValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsCountCorrection","name":"_correction","type":"tuple"}],"name":"unsafeSetExitedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_exitedValidatorsCounts","type":"uint256[]"}],"name":"updateExitedValidatorsCountByStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"updateStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_depositContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AppAuthLidoFailed","type":"error"},{"inputs":[],"name":"DepositContractZeroAddress","type":"error"},{"inputs":[],"name":"DirectETHTransfer","type":"error"},{"inputs":[],"name":"EmptyWithdrawalsCredentials","type":"error"},{"inputs":[],"name":"ExitedValidatorsCountCannotDecrease","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidReportData","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NotExpectedBalance","type":"error"},{"inputs":[],"name":"StakingModuleIdTooLarge","type":"error"},{"inputs":[],"name":"StakingModuleNotActive","type":"error"},{"inputs":[],"name":"StakingModuleNotPaused","type":"error"},{"inputs":[],"name":"StakingModuleStatusTheSame","type":"error"},{"inputs":[],"name":"StakingModuleUnregistered","type":"error"},{"inputs":[],"name":"StakingModuleWrongName","type":"error"},{"inputs":[],"name":"StakingModulesLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOpStuckValidatorsCount","type":"uint256"}],"name":"UnexpectedCurrentValidatorsCount","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ValueOver100Percent","type":"error"},{"inputs":[{"internalType":"string","name":"field","type":"string"}],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"stakingModule","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"createdBy","type":"address"}],"name":"StakingModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unreportedExitedValidatorsCount","type":"uint256"}],"name":"StakingModuleExitedValidatorsIncompleteReporting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingModuleFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"treasuryFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"enum StakingRouter.StakingModuleStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetShare","type":"uint256"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"StakingModuleTargetShareSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakingRouterETHDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"},{"indexed":false,"internalType":"address","name":"setBy","type":"address"}],"name":"WithdrawalCredentialsSet","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPOSIT_CONTRACT","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_PRECISION_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_WITHDRAWAL_CREDENTIALS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REPORT_REWARDS_MINTED_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_MANAGE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_MODULE_RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_BASIS_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNSAFE_SET_EXITED_VALIDATORS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_stakingModuleAddress","type":"address"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"addStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxDepositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getAllNodeOperatorDigests","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"components":[{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.NodeOperatorSummary","name":"summary","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorDigest[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllStakingModuleDigests","outputs":[{"components":[{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"components":[{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModuleSummary","name":"summary","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleDigest[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositsCount","type":"uint256"}],"name":"getDepositsAllocation","outputs":[{"internalType":"uint256","name":"allocated","type":"uint256"},{"internalType":"uint256[]","name":"allocations","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExitedValidatorsCountAcrossAllModules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLido","outputs":[{"internalType":"contract ILido","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256[]","name":"_nodeOperatorIds","type":"uint256[]"}],"name":"getNodeOperatorDigests","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"components":[{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.NodeOperatorSummary","name":"summary","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorDigest[]","name":"digests","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"getNodeOperatorDigests","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"components":[{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.NodeOperatorSummary","name":"summary","type":"tuple"}],"internalType":"struct StakingRouter.NodeOperatorDigest[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"components":[{"internalType":"bool","name":"isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"targetValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"refundedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"stuckPenaltyEndTimestamp","type":"uint256"},{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.NodeOperatorSummary","name":"summary","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistribution","outputs":[{"internalType":"uint96","name":"modulesFee","type":"uint96"},{"internalType":"uint96","name":"treasuryFee","type":"uint96"},{"internalType":"uint256","name":"basePrecision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingFeeAggregateDistributionE4Precision","outputs":[{"internalType":"uint16","name":"modulesFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModule","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleActiveValidatorsCount","outputs":[{"internalType":"uint256","name":"activeValidatorsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"}],"name":"getStakingModuleDigests","outputs":[{"components":[{"internalType":"uint256","name":"nodeOperatorsCount","type":"uint256"},{"internalType":"uint256","name":"activeNodeOperatorsCount","type":"uint256"},{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule","name":"state","type":"tuple"},{"components":[{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModuleSummary","name":"summary","type":"tuple"}],"internalType":"struct StakingRouter.StakingModuleDigest[]","name":"digests","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModuleIds","outputs":[{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsDepositsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleIsStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleLastDepositBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleMaxDepositsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleStatus","outputs":[{"internalType":"enum StakingRouter.StakingModuleStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"getStakingModuleSummary","outputs":[{"components":[{"internalType":"uint256","name":"totalExitedValidators","type":"uint256"},{"internalType":"uint256","name":"totalDepositedValidators","type":"uint256"},{"internalType":"uint256","name":"depositableValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModuleSummary","name":"summary","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModules","outputs":[{"components":[{"internalType":"uint24","name":"id","type":"uint24"},{"internalType":"address","name":"stakingModuleAddress","type":"address"},{"internalType":"uint16","name":"stakingModuleFee","type":"uint16"},{"internalType":"uint16","name":"treasuryFee","type":"uint16"},{"internalType":"uint16","name":"targetShare","type":"uint16"},{"internalType":"uint8","name":"status","type":"uint8"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint64","name":"lastDepositAt","type":"uint64"},{"internalType":"uint256","name":"lastDepositBlock","type":"uint256"},{"internalType":"uint256","name":"exitedValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.StakingModule[]","name":"res","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingModulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingRewardsDistribution","outputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"stakingModuleIds","type":"uint256[]"},{"internalType":"uint96[]","name":"stakingModuleFees","type":"uint96[]"},{"internalType":"uint96","name":"totalFee","type":"uint96"},{"internalType":"uint256","name":"precisionPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFeeE4Precision","outputs":[{"internalType":"uint16","name":"totalFee","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_lido","type":"address"},{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"pauseStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_totalShares","type":"uint256[]"}],"name":"reportRewardsMinted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_exitedValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleExitedValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_nodeOperatorIds","type":"bytes"},{"internalType":"bytes","name":"_stuckValidatorsCounts","type":"bytes"}],"name":"reportStakingModuleStuckValidatorsCountByNodeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"}],"name":"resumeStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"enum StakingRouter.StakingModuleStatus","name":"_status","type":"uint8"}],"name":"setStakingModuleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"}],"name":"setWithdrawalCredentials","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_triggerUpdateFinish","type":"bool"},{"components":[{"internalType":"uint256","name":"currentModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"currentNodeOperatorStuckValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newModuleExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorExitedValidatorsCount","type":"uint256"},{"internalType":"uint256","name":"newNodeOperatorStuckValidatorsCount","type":"uint256"}],"internalType":"struct StakingRouter.ValidatorsCountCorrection","name":"_correction","type":"tuple"}],"name":"unsafeSetExitedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_stakingModuleIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_exitedValidatorsCounts","type":"uint256[]"}],"name":"updateExitedValidatorsCountByStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"uint256","name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_targetShare","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleFee","type":"uint256"},{"internalType":"uint256","name":"_treasuryFee","type":"uint256"}],"name":"updateStakingModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file From 382a8e2943000dda08564955a24cec9e555b5202 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 13 Feb 2023 17:11:58 +0400 Subject: [PATCH 59/82] Add missing doc comments to the IStakingModule --- contracts/0.8.9/interfaces/IStakingModule.sol | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/contracts/0.8.9/interfaces/IStakingModule.sol b/contracts/0.8.9/interfaces/IStakingModule.sol index 38a39d1c7..5ef430076 100644 --- a/contracts/0.8.9/interfaces/IStakingModule.sol +++ b/contracts/0.8.9/interfaces/IStakingModule.sol @@ -8,15 +8,34 @@ interface IStakingModule { /// @notice Returns the type of the staking module function getType() external view returns (bytes32); - /// @notice Returns validators summary about all validators in the staking module + /// @notice Returns all-validators summary in the staking module + /// @return totalExitedValidators total number of validators in the EXITED state + /// on the Consensus Layer. This value can't decrease in normal conditions + /// @return totalDepositedValidators total number of validators deposited via the + /// official Deposit Contract. This value is a cumulative counter: even when the validator + /// goes into EXITED state this counter is not decreasing + /// @return depositableValidatorsCount number of validators in the set available for deposit function getStakingModuleSummary() external view returns ( uint256 totalExitedValidators, uint256 totalDepositedValidators, - uint256 depositableValidators + uint256 depositableValidatorsCount ); - /// @notice Returns summary about all validators belonging to the node operator with the given id + /// @notice Returns all-validators summary belonging to the node operator with the given id /// @param _nodeOperatorId id of the operator to return report for + /// @return isTargetLimitActive shows whether the current target limit applied to the node operator + /// @return targetValidatorsCount relative target active validators limit for operator + /// @return stuckValidatorsCount number of validators with an expired request to exit time + /// @return refundedValidatorsCount number of validators that can't be withdrawn, but deposit + /// costs were compensated to the Lido by the node operator + /// @return stuckPenaltyEndTimestamp time when the penalty for stuck validators stops applying + /// to node operator rewards + /// @return totalExitedValidators total number of validators in the EXITED state + /// on the Consensus Layer. This value can't decrease in normal conditions + /// @return totalDepositedValidators total number of validators deposited via the official + /// Deposit Contract. This value is a cumulative counter: even when the validator goes into + /// EXITED state this counter is not decreasing + /// @return depositableValidatorsCount number of validators in the set available for deposit function getNodeOperatorSummary(uint256 _nodeOperatorId) external view returns ( bool isTargetLimitActive, uint256 targetValidatorsCount, From 2465ad7345d868a6bdb5dab52364945cee8c2540 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 16:31:57 +0300 Subject: [PATCH 60/82] fix: visibility --- contracts/0.4.24/Lido.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index dd2960f2d..b04df0f4b 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -606,7 +606,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * * @param _newDepositedValidators new value */ - function unsafeChangeDepositedValidators(uint256 _newDepositedValidators) { + function unsafeChangeDepositedValidators(uint256 _newDepositedValidators) external { _auth(UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE); DEPOSITED_VALIDATORS_POSITION.setStorageUint256(_newDepositedValidators); From 32510e0ef74670d781dc2eb3dbcfa4394188cd10 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 17:17:38 +0300 Subject: [PATCH 61/82] chore: _checkFinalizationShareRate view->pure --- contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 191fcde23..1fc9ae88c 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -540,7 +540,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { uint256 _noWithdrawalsPostTotalPooledEther, uint256 _noWithdrawalsPostTotalShares, uint256 _simulatedShareRate - ) internal view { + ) internal pure { uint256 actualShareRate = ( _noWithdrawalsPostTotalPooledEther * SHARE_RATE_PRECISION_E27 ) / _noWithdrawalsPostTotalShares; From 56363bb51ad715945f20835db3b2558c1a181f90 Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 13 Feb 2023 22:56:02 +0700 Subject: [PATCH 62/82] fix nor, update tests --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 10 +- .../node-operators-registry-penalty.test.js | 274 +++++++++--------- test/0.4.24/node-operators-registry.test.js | 2 +- 3 files changed, 141 insertions(+), 145 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 28e9c2f4f..e080490d5 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -44,8 +44,6 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { event NodeOperatorActiveSet(uint256 indexed nodeOperatorId, bool active); event NodeOperatorNameSet(uint256 indexed nodeOperatorId, string name); event NodeOperatorRewardAddressSet(uint256 indexed nodeOperatorId, address rewardAddress); - event NodeOperatorStakingLimitSet(uint256 indexed nodeOperatorId, uint64 stakingLimit); - event NodeOperatorTotalStoppedValidatorsReported(uint256 indexed nodeOperatorId, uint64 totalStopped); event NodeOperatorTotalKeysTrimmed(uint256 indexed nodeOperatorId, uint64 totalKeysTrimmed); event KeysOpIndexSet(uint256 keysOpIndex); event ContractVersionSet(uint256 version); @@ -437,7 +435,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { _onlyExistedNodeOperator(_nodeOperatorId); _auth(STAKING_ROUTER_ROLE); - _updateExitedValidatorsCount(_nodeOperatorId, uint64(_exitedValidatorsCount), true); + _updateExitedValidatorsCount(_nodeOperatorId, uint64(_exitedValidatorsCount), true /* _allowDecrease */); _updateStuckValidatorsCount(_nodeOperatorId, uint64(_stuckValidatorsCount)); } @@ -462,7 +460,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @notice Updates the limit of the validators that can be used for deposit by DAO /// @param _nodeOperatorId Id of the node operator - /// @param _targetLimit New number of EXITED validators of the node operator + /// @param _targetLimit Target limit of the node operator /// @param _isTargetLimitActive active flag function updateTargetValidatorsLimits(uint256 _nodeOperatorId, bool _isTargetLimitActive, uint64 _targetLimit) external { _onlyExistedNodeOperator(_nodeOperatorId); @@ -799,11 +797,11 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { Packed64x4.Packed memory signingKeysStats = _loadOperatorSigningKeysStats(_nodeOperatorId); uint256 totalSigningKeysCount = signingKeysStats.get(TOTAL_KEYS_COUNT_OFFSET); + _requireValidRange(totalSigningKeysCount.add(_keysCount) <= UINT64_MAX); + totalSigningKeysCount = SIGNING_KEYS_MAPPING_NAME.addKeysSigs(_nodeOperatorId, _keysCount, totalSigningKeysCount, _publicKeys, _signatures); - _requireValidRange(totalSigningKeysCount.add(_keysCount) <= UINT64_MAX); - emit TotalSigningKeysCountChanged(_nodeOperatorId, totalSigningKeysCount); signingKeysStats.set(TOTAL_KEYS_COUNT_OFFSET, uint64(totalSigningKeysCount)); diff --git a/test/0.4.24/node-operators-registry-penalty.test.js b/test/0.4.24/node-operators-registry-penalty.test.js index 9e08c4e92..7cfd6af26 100644 --- a/test/0.4.24/node-operators-registry-penalty.test.js +++ b/test/0.4.24/node-operators-registry-penalty.test.js @@ -5,7 +5,7 @@ const { toBN, padRight, printEvents } = require('../helpers/utils') const { BN } = require('bn.js') const { AragonDAO } = require('./helpers/dao') const { EvmSnapshot } = require('../helpers/blockchain') -const { ZERO_ADDRESS, getEventAt } = require('@aragon/contract-helpers-test') +const { ZERO_ADDRESS, getEventAt, bn } = require('@aragon/contract-helpers-test') const nodeOperators = require('../helpers/node-operators') const signingKeys = require('../helpers/signing-keys') const { web3 } = require('hardhat') @@ -14,6 +14,7 @@ const { getRandomLocatorConfig } = require('../helpers/locator') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistryMock') const LidoLocator = artifacts.require('LidoLocator') +const Burner = artifacts.require('Burner.sol') const ADDRESS_1 = '0x0000000000000000000000000000000000000001' const ADDRESS_2 = '0x0000000000000000000000000000000000000002' @@ -83,8 +84,8 @@ const hexConcat = (first, ...rest) => { const ETH = (value) => web3.utils.toWei(value + '', 'ether') const StETH = artifacts.require('StETHMock') -contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, user4, no1]) => { - let appBase, app, pool, steth, dao, locator +contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, user4, no1, treasury]) => { + let appBase, app, pool, steth, dao, locator, burner const snapshot = new EvmSnapshot(hre.ethers.provider) before('deploy base app', async () => { @@ -92,8 +93,13 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use appBase = await NodeOperatorsRegistry.new() steth = await StETH.new() + burner = await Burner.new( + voting, treasury, steth.address, bn(0), bn(0), { from: appManager } + ) + const locatorConfig = getRandomLocatorConfig({ - lido: steth.address + lido: steth.address, + burner: burner.address }) locator = await LidoLocator.new(locatorConfig) @@ -109,17 +115,23 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use } }) + //grant REQUEST_BURN_SHARES_ROLE to NOR + await burner.grantRole(web3.utils.keccak256(`REQUEST_BURN_SHARES_ROLE`), app.address, { from: voting }) + // grant role to app itself cause it uses solidity's call method to itself // inside the testing_requestValidatorsKeysForDeposits() method await dao.grantPermission(app.address, app, 'STAKING_ROUTER_ROLE') - // Instantiate a proxy for the app, using the base contract as its logic implementation. + // Instantiate a proxy for the app, using the base c ontract as its logic implementation. // const proxyAddress = await newApp(newDAO.dao, 'node-operators-registry', appBase.address, appManager) // app = await NodeOperatorsRegistry.at(proxyAddress) // Initialize the app's proxy. const tx = await app.initialize(locator.address, CURATED_TYPE) + //set stuck penalty voting + await app.setStuckPenaltyDelay(60*60*24*2, { from: voting }) + // Implementation initializer reverts because initialization block was set to max(uint256) // in the Autopetrified base contract // await assert.reverts(appBase.initialize(steth.address, CURATED_TYPE), 'INIT_ALREADY_INITIALIZED') @@ -291,33 +303,21 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use assert.emits(receipt, 'NodeOperatorPenalized', { recipientAddress: user1, sharesPenalizedAmount: ETH(1.25) }) }) - it('penalized firstOperator, add refund more than stuck validators', async () => { + it('reverts when refund more than DEPOSITED_KEYS_COUNT_OFFSET', async () => { await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - - //update [operator, exited, stuck] await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 1, { from: voting }) await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0, { from: voting }) - await app.updateRefundedValidatorsCount(firstNodeOperator, 1000, { from: voting }) - - // calls distributeRewards() inside - receipt = await app.testing__distributeRewards({ from: voting }) - - assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(1.25) }) - assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(6*1.25) }) - assert.notEmits(receipt, 'RewardsDistributed', { rewardAddress: user3, sharesAmount: 0 }) - assert.emits(receipt, 'NodeOperatorPenalized', { recipientAddress: user1, sharesPenalizedAmount: ETH(1.25) }) + assert.reverts(app.updateRefundedValidatorsCount(firstNodeOperator, 1000, { from: voting }), "test") }) it('penalized firstOperator, add refund less than stuck validators', async () => { await steth.setTotalPooledEther(ETH(100)) await steth.mintShares(app.address, ETH(10)) - - //update [operator, exited, stuck] await app.unsafeUpdateValidatorsCount(firstNodeOperator, 2, 2 , { from: voting }) await app.unsafeUpdateValidatorsCount(secondNodeOperator, 3, 0 , { from: voting }) @@ -366,8 +366,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use }) }) - describe('getValidatorsKeysStats()', () => { + describe('getNodeOperatorSummary()', () => { beforeEach(async () => { + //total vetted deposited exited await app.testing_addNodeOperator('0', user1, 20, 15, 10, 2) await app.testing_addNodeOperator('1', user2, 20, 10, 5, 0) await app.testing_addNodeOperator('2', user3, 15, 5, 0, 0) @@ -377,219 +378,216 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.mintShares(app.address, ETH(10)) // await app.testing_addNodeOperator('no', no1, 55, 30, 15, 2) - - // sum of (vetted[i] - exited[i]) - await app.increaseTargetValidatorsCount(28) }) - it('updateTargetValidatorsLimits()', async () => { - await app.updateTargetValidatorsLimits(3, 5, true, { from: voting }) + it('updateTargetValidatorsLimits() - target <= deposited', async () => { let keyStats = await app.getNodeOperatorSummary(3) + assert.equal(+keyStats.isTargetLimitActive, false) + assert.equal(+keyStats.targetValidatorsCount, 0) - assert.equal(+keyStats.excessValidatorsCount, 5) - - await app.updateExitedValidatorsKeysCount(3, 9, { from: voting }) + await app.updateTargetValidatorsLimits(3, true, 3, { from: voting }) + keyStats = await app.getNodeOperatorSummary(3) - keyStats1 = await app.getNodeOperatorSummary(3) - assert.equal(+keyStats1.excessValidatorsCount, 0) + assert.equal(+keyStats.isTargetLimitActive, true) + assert.equal(+keyStats.targetValidatorsCount, 3) }) - it('updateExitedValidatorsKeysCount() - check if appeared a new deposited keys and stopped, excess no changes ', async () => { - await app.updateTargetValidatorsLimits(3, 5, true, { from: voting }) + it('updateTargetValidatorsLimits() - deposited < target < vetted', async () => { let keyStats = await app.getNodeOperatorSummary(3) + assert.equal(+keyStats.isTargetLimitActive, false) + assert.equal(+keyStats.targetValidatorsCount, 0) + assert.equal(+keyStats.depositableValidatorsCount, 5) - //excess = deposited - stopped - targetLimit - assert.equal(+keyStats.targetValidatorsCount, 5) - assert.equal(+keyStats.excessValidatorsCount, 5) + await app.updateTargetValidatorsLimits(3, true, 11, { from: voting }) + keyStats = await app.getNodeOperatorSummary(3) - //increase _newActiveValidatorsCount by add new depositedKeys - await app.increaseNodeOperatorDepositedSigningKeysCount(3, 1) + assert.equal(+keyStats.isTargetLimitActive, true) + assert.equal(+keyStats.targetValidatorsCount, 11) + assert.equal(+keyStats.depositableValidatorsCount, 1) + }) + + it('updateTargetValidatorsLimits() - vetted <= target', async () => { + let keyStats = await app.getNodeOperatorSummary(3) + assert.equal(+keyStats.isTargetLimitActive, false) + assert.equal(+keyStats.targetValidatorsCount, 0) + assert.equal(+keyStats.depositableValidatorsCount, 5) - await app.updateExitedValidatorsKeysCount(3, 1, { from: voting }) + await app.updateTargetValidatorsLimits(3, true, 18, { from: voting }) + keyStats = await app.getNodeOperatorSummary(3) - keyStats1 = await app.getNodeOperatorSummary(3) - assert.equal(+keyStats1.excessValidatorsCount, 5) + assert.equal(+keyStats.isTargetLimitActive, true) + assert.equal(+keyStats.targetValidatorsCount, 18) + assert.equal(+keyStats.depositableValidatorsCount, 5) }) - it('updateExitedValidatorsKeysCount() - check if appeared a new deposited keys', async () => { - await app.updateTargetValidatorsLimits(3, 5, true, { from: voting }) + + it('updateExitedValidatorsCount() - check if appeared a new deposited keys', async () => { + await app.updateTargetValidatorsLimits(3, true, 5, { from: voting }) let keyStats = await app.getNodeOperatorSummary(3) //excess = deposited - stopped - targetLimit assert.equal(+keyStats.targetValidatorsCount, 5) - assert.equal(+keyStats.excessValidatorsCount, 5) //increase _newActiveValidatorsCount by add new depositedKeys await app.increaseNodeOperatorDepositedSigningKeysCount(3, 2) - await app.updateExitedValidatorsKeysCount(3, 1, { from: voting }) + await app.updateExitedValidatorsCount(3, 1, { from: voting }) - keyStats1 = await app.getNodeOperatorSummary(3) - assert.equal(+keyStats1.excessValidatorsCount, 6) }) it('updateTargetValidatorsLimits() - try to update to the same active flag', async () => { let keyStats = await app.getNodeOperatorSummary(0) targetValidatorsCountBefore = keyStats.targetValidatorsCount - assert.isFalse(keyStats.targetValidatorsActive) + assert.equal(keyStats.isTargetLimitActive, false) + assert.equal(+keyStats.targetValidatorsCount, 0) - await app.updateTargetValidatorsLimits(0, 10, false, { from: voting }) + await app.updateTargetValidatorsLimits(0, false, 10, { from: voting }) keyStats = await app.getNodeOperatorSummary(0) targetValidatorsCountAfter = keyStats.targetValidatorsCount - assert.isFalse(keyStats.targetValidatorsActive) + assert.equal(keyStats.isTargetLimitActive, false) assert.equal(+targetValidatorsCountBefore, +targetValidatorsCountAfter) targetValidatorsCountBefore = keyStats.targetValidatorsCount - await app.updateTargetValidatorsLimits(0, 20, true, { from: voting }) + await app.updateTargetValidatorsLimits(0, true, 20, { from: voting }) keyStats = await app.getNodeOperatorSummary(0) targetValidatorsCountAfter = keyStats.targetValidatorsCount - assert.isTrue(keyStats.targetValidatorsActive) + assert.equal(keyStats.isTargetLimitActive, true) assert.notEqual(+targetValidatorsCountBefore, +targetValidatorsCountAfter) - targetValidatorsCountBefore = keyStats.targetValidatorsCount - await app.updateTargetValidatorsLimits(0, 30, true, { from: voting }) + await app.updateTargetValidatorsLimits(0, true, 30, { from: voting }) keyStats = await app.getNodeOperatorSummary(0) targetValidatorsCountAfter = keyStats.targetValidatorsCount - assert.isTrue(keyStats.targetValidatorsActive) - assert.equal(+targetValidatorsCountBefore, +targetValidatorsCountAfter) + assert.equal(keyStats.isTargetLimitActive, true) + assert.equal(+targetValidatorsCountAfter, 30) }) it('updateTargetValidatorsLimits()', async () => { - await app.updateTargetValidatorsLimits(0, 10, true, { from: voting }) + await app.updateTargetValidatorsLimits(0, true, 10, { from: voting }) - let keysStatTotal = await app.getValidatorsKeysStats() - // console.log(o2n(keysStatTotal)) - assert.equal(keysStatTotal.exitedValidatorsCount, 2) - assert.equal(keysStatTotal.activeValidatorsKeysCount, 13) - assert.equal(keysStatTotal.readyToDepositValidatorsKeysCount, 12) + let keysStatTotal = await app.getStakingModuleSummary() + assert.equal(keysStatTotal.totalExitedValidators, 2) + assert.equal(keysStatTotal.totalDepositedValidators, 25) + assert.equal(keysStatTotal.depositableValidatorsCount, 17) let limitStatOp = await app.getNodeOperatorSummary(0) - assert.equal(limitStatOp.targetValidatorsActive, true) + assert.equal(limitStatOp.isTargetLimitActive, true) assert.equal(limitStatOp.targetValidatorsCount, 10) - assert.equal(limitStatOp.excessValidatorsCount, 0) - let keysStatOp = await app.getValidatorsKeysStats(0) - assert.equal(keysStatOp.exitedValidatorsCount, 2) - assert.equal(keysStatOp.activeValidatorsKeysCount, 8) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 2) - // console.log(stat12) + let keysStatOp = await app.getNodeOperatorSummary(0) + assert.equal(keysStatOp.totalExitedValidators, 2) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 8) + assert.equal(keysStatOp.depositableValidatorsCount, 2) - await app.updateTargetValidatorsLimits(0, 10, false, { from: voting }) + await app.updateTargetValidatorsLimits(0, false, 10, { from: voting }) - keysStatTotal = await app.getValidatorsKeysStats() - assert.equal(keysStatTotal.exitedValidatorsCount, 2) - assert.equal(keysStatTotal.activeValidatorsKeysCount, 13) - assert.equal(keysStatTotal.readyToDepositValidatorsKeysCount, 15) + keysStatTotal = await app.getStakingModuleSummary() + assert.equal(+keysStatTotal.totalExitedValidators, 2) + assert.equal(+keysStatTotal.totalDepositedValidators, 25) + assert.equal(+keysStatTotal.depositableValidatorsCount, 20) limitStatOp = await app.getNodeOperatorSummary(0) - assert.equal(limitStatOp.targetValidatorsActive, false) - assert.equal(limitStatOp.targetValidatorsCount, 0) - assert.equal(limitStatOp.excessValidatorsCount, 0) - - keysStatOp = await app.getValidatorsKeysStats(0) - assert.equal(keysStatOp.exitedValidatorsCount, 2) - assert.equal(keysStatOp.activeValidatorsKeysCount, 8) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 5) + assert.equal(limitStatOp.isTargetLimitActive, false) + assert.equal(+limitStatOp.targetValidatorsCount, 0) + + keysStatOp = await app.getNodeOperatorSummary(0) + assert.equal(+keysStatOp.totalExitedValidators, 2) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 8) + assert.equal(+keysStatOp.depositableValidatorsCount, 5) }) - it('updateExitedValidatorsKeysCount()', async () => { - await app.updateTargetValidatorsLimits(0, 5, true, { from: voting }) - await app.updateTargetValidatorsLimits(1, 5, true, { from: voting }) + it('updateExitedValidatorsCount()', async () => { + await app.updateTargetValidatorsLimits(0, true, 5, { from: voting }) + await app.updateTargetValidatorsLimits(1, true, 5, { from: voting }) - let keysStatTotal = await app.getValidatorsKeysStats() + let keysStatTotal = await app.getStakingModuleSummary() // console.log(o2n(keysStatTotal)) - assert.equal(keysStatTotal.exitedValidatorsCount, 2) - assert.equal(keysStatTotal.activeValidatorsKeysCount, 13) - assert.equal(keysStatTotal.readyToDepositValidatorsKeysCount, 5) + assert.equal(+keysStatTotal.totalExitedValidators, 2) + assert.equal(+keysStatTotal.totalDepositedValidators, 25) + assert.equal(+keysStatTotal.depositableValidatorsCount, 10) // op 0 let limitStatOp = await app.getNodeOperatorSummary(0) - assert.equal(limitStatOp.targetValidatorsActive, true) + assert.equal(limitStatOp.isTargetLimitActive, true) assert.equal(limitStatOp.targetValidatorsCount, 5) - assert.equal(limitStatOp.excessValidatorsCount, 3) // deposited - exited - target - let keysStatOp = await app.getValidatorsKeysStats(0) - assert.equal(keysStatOp.exitedValidatorsCount, 2) - assert.equal(keysStatOp.activeValidatorsKeysCount, 8) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 0) + let keysStatOp = await app.getNodeOperatorSummary(0) + assert.equal(keysStatOp.totalExitedValidators, 2) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 8) + assert.equal(keysStatOp.depositableValidatorsCount, 0) // op 1 limitStatOp = await app.getNodeOperatorSummary(1) - assert.equal(limitStatOp.targetValidatorsActive, true) + assert.equal(limitStatOp.isTargetLimitActive, true) assert.equal(limitStatOp.targetValidatorsCount, 5) - assert.equal(limitStatOp.excessValidatorsCount, 0) // deposited - exited - target - keysStatOp = await app.getValidatorsKeysStats(1) - assert.equal(keysStatOp.exitedValidatorsCount, 0) - assert.equal(keysStatOp.activeValidatorsKeysCount, 5) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 0) + keysStatOp = await app.getNodeOperatorSummary(1) + assert.equal(keysStatOp.totalExitedValidators, 0) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 5) + assert.equal(keysStatOp.depositableValidatorsCount, 0) - // // console.log(stat12) - await app.updateExitedValidatorsKeysCount(0, 3, { from: voting }) - await app.updateExitedValidatorsKeysCount(1, 1, { from: voting }) + // console.log(o2n(limitStatOp)) + await app.updateExitedValidatorsCount(0, 3, { from: voting }) + await app.updateExitedValidatorsCount(1, 1, { from: voting }) - keysStatTotal = await app.getValidatorsKeysStats() - assert.equal(keysStatTotal.exitedValidatorsCount, 4) - assert.equal(keysStatTotal.activeValidatorsKeysCount, 11) - assert.equal(keysStatTotal.readyToDepositValidatorsKeysCount, 6) + keysStatTotal = await app.getStakingModuleSummary() + // console.log(o2n(keysStatTotal)) + assert.equal(+keysStatTotal.totalExitedValidators, 4) + assert.equal(keysStatTotal.totalDepositedValidators.toNumber()-keysStatTotal.totalExitedValidators.toNumber(), 25-(3+1)) + assert.equal(+keysStatTotal.depositableValidatorsCount, 11) // op 0 limitStatOp = await app.getNodeOperatorSummary(0) - assert.equal(limitStatOp.targetValidatorsActive, true) + assert.equal(limitStatOp.isTargetLimitActive, true) assert.equal(limitStatOp.targetValidatorsCount, 5) - assert.equal(limitStatOp.excessValidatorsCount, 2) - keysStatOp = await app.getValidatorsKeysStats(0) - assert.equal(keysStatOp.exitedValidatorsCount, 3) - assert.equal(keysStatOp.activeValidatorsKeysCount, 7) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 0) + keysStatOp = await app.getNodeOperatorSummary(0) + assert.equal(keysStatOp.totalExitedValidators, 3) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 7) + assert.equal(keysStatOp.depositableValidatorsCount, 0) // op 1 limitStatOp = await app.getNodeOperatorSummary(1) - assert.equal(limitStatOp.targetValidatorsActive, true) + assert.equal(limitStatOp.isTargetLimitActive, true) assert.equal(limitStatOp.targetValidatorsCount, 5) - assert.equal(limitStatOp.excessValidatorsCount, 0) - keysStatOp = await app.getValidatorsKeysStats(1) - assert.equal(keysStatOp.exitedValidatorsCount, 1) - assert.equal(keysStatOp.activeValidatorsKeysCount, 4) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 1) + keysStatOp = await app.getNodeOperatorSummary(1) + assert.equal(keysStatOp.totalExitedValidators, 1) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 4) + assert.equal(keysStatOp.depositableValidatorsCount, 1) }) it('setNodeOperatorStakingLimit()', async () => { - await app.updateTargetValidatorsLimits(0, 10, true, { from: voting }) - await app.updateTargetValidatorsLimits(1, 15, true, { from: voting }) + await app.updateTargetValidatorsLimits(0, true, 10, { from: voting }) + await app.updateTargetValidatorsLimits(1, true, 15, { from: voting }) await app.setNodeOperatorStakingLimit(0, 10, { from: voting }) await app.setNodeOperatorStakingLimit(1, 15, { from: voting }) - let keysStatTotal = await app.getValidatorsKeysStats() + let keysStatTotal = await app.getStakingModuleSummary() // console.log(o2n(keysStatTotal)) - assert.equal(keysStatTotal.exitedValidatorsCount, 2) - assert.equal(keysStatTotal.activeValidatorsKeysCount, 13) - assert.equal(keysStatTotal.readyToDepositValidatorsKeysCount, 15) + assert.equal(+keysStatTotal.totalExitedValidators, 2) + assert.equal(+keysStatTotal.totalDepositedValidators, 25) + assert.equal(+keysStatTotal.depositableValidatorsCount, 20) // op 0 let limitStatOp = await app.getNodeOperatorSummary(0) - assert.equal(limitStatOp.targetValidatorsActive, true) - assert.equal(limitStatOp.targetValidatorsCount, 10) - assert.equal(limitStatOp.excessValidatorsCount, 0) // deposited - exited - target + assert.equal(limitStatOp.isTargetLimitActive, true) + assert.equal(+limitStatOp.targetValidatorsCount, 10) - let keysStatOp = await app.getValidatorsKeysStats(0) - assert.equal(keysStatOp.exitedValidatorsCount, 2) - assert.equal(keysStatOp.activeValidatorsKeysCount, 8) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 0) + let keysStatOp = await app.getNodeOperatorSummary(0) + assert.equal(+keysStatOp.totalExitedValidators, 2) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 8) + assert.equal(+keysStatOp.depositableValidatorsCount, 0) // op 1 limitStatOp = await app.getNodeOperatorSummary(1) - assert.equal(limitStatOp.targetValidatorsActive, true) + assert.equal(limitStatOp.isTargetLimitActive, true) assert.equal(limitStatOp.targetValidatorsCount, 15) - assert.equal(limitStatOp.excessValidatorsCount, 0) // deposited - exited - target - keysStatOp = await app.getValidatorsKeysStats(1) - assert.equal(keysStatOp.exitedValidatorsCount, 0) - assert.equal(keysStatOp.activeValidatorsKeysCount, 5) - assert.equal(keysStatOp.readyToDepositValidatorsKeysCount, 10) + keysStatOp = await app.getNodeOperatorSummary(1) + assert.equal(keysStatOp.totalExitedValidators, 0) + assert.equal(keysStatOp.totalDepositedValidators.toNumber()-keysStatOp.totalExitedValidators.toNumber(), 5) + assert.equal(keysStatOp.depositableValidatorsCount, 10) }) }) }) diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index a6d3c7cf8..6ff1b585b 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -1560,7 +1560,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob // it('respects staking limit', async () => { // const [firstNodeOperatorKeysStats, secondNodeOperatorKeysStats] = await Promise.all([ - // app.getValidatorsKeysStats(firstNodeOperatorId), + // app.getNodeOperatorSummary(firstNodeOperatorId), // app.getValidatorsKeysStats(secondNodeOperatorId) // ]) From 65260fc4678fa123365918a01dd336fa0a87b86f Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 13 Feb 2023 22:57:45 +0700 Subject: [PATCH 63/82] fix comments --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 2 +- lib/abi/NodeOperatorsRegistry.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index e080490d5..5f25796c8 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -507,7 +507,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { emit RefundedValidatorsCountChanged(_nodeOperatorId, _refundedValidatorsCount); } - /// @notice Invalidates all unused validators for all node operators + /// @notice Invalidates all unused deposit data for all node operators function onWithdrawalCredentialsChanged() external { uint256 operatorsCount = getNodeOperatorsCount(); if (operatorsCount > 0) { diff --git a/lib/abi/NodeOperatorsRegistry.json b/lib/abi/NodeOperatorsRegistry.json index c49590657..a5a7660a1 100644 --- a/lib/abi/NodeOperatorsRegistry.json +++ b/lib/abi/NodeOperatorsRegistry.json @@ -1 +1 @@ -[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getType","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getNodeOperatorIds","outputs":[{"name":"nodeOperatorIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getSigningKeys","outputs":[{"name":"pubkeys","type":"bytes"},{"name":"signatures","type":"bytes"},{"name":"used","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorIsActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_name","type":"string"}],"name":"setNodeOperatorName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_totalRewardShares","type":"uint256"}],"name":"getRewardsDistribution","outputs":[{"name":"recipients","type":"address[]"},{"name":"shares","type":"uint256[]"},{"name":"penalized","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_indexFrom","type":"uint256"},{"name":"_indexTo","type":"uint256"}],"name":"invalidateReadyToDepositKeysRange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint64"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_delay","type":"uint256"}],"name":"setStuckPenaltyDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStuckPenaltyDelay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"deactivateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_ROUTER_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onAllValidatorCountersUpdated","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getActiveNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_rewardAddress","type":"address"}],"name":"addNodeOperator","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getUnusedSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_NODE_OPERATOR_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onWithdrawalCredentialsChanged","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"activateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_rewardAddress","type":"address"}],"name":"setNodeOperatorRewardAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fullInfo","type":"bool"}],"name":"getNodeOperator","outputs":[{"name":"active","type":"bool"},{"name":"name","type":"string"},{"name":"rewardAddress","type":"address"},{"name":"stakingLimit","type":"uint64"},{"name":"stoppedValidators","type":"uint64"},{"name":"totalSigningKeys","type":"uint64"},{"name":"usedSigningKeys","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakingModuleSummary","outputs":[{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_vettedSigningKeysCount","type":"uint64"}],"name":"setNodeOperatorStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"name":"isTargetLimitActive","type":"bool"},{"name":"targetValidatorsCount","type":"uint256"},{"name":"stuckValidatorsCount","type":"uint256"},{"name":"refundedValidatorsCount","type":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256"},{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"getSigningKey","outputs":[{"name":"key","type":"bytes"},{"name":"depositSignature","type":"bytes"},{"name":"used","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATOR_NAME_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"name":"depositsCount","type":"uint256"},{"name":"publicKeys","type":"bytes"},{"name":"signatures","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getKeysOpIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SET_NODE_OPERATOR_LIMIT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getTotalSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"}],"name":"updateExitedValidatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"updateStuckValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATORS_COUNT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKeyOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"handleRewardsMinted","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"unsafeUpdateValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_SIGNING_KEYS","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"active","type":"bool"}],"name":"NodeOperatorActiveSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"}],"name":"NodeOperatorNameSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"rewardAddress","type":"address"}],"name":"NodeOperatorRewardAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorStakingLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalStopped","type":"uint64"}],"name":"NodeOperatorTotalStoppedValidatorsReported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalKeysTrimmed","type":"uint64"}],"name":"NodeOperatorTotalKeysTrimmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keysOpIndex","type":"uint256"}],"name":"KeysOpIndexSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"moduleType","type":"bytes32"}],"name":"StakingModuleTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"RewardsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"locatorAddress","type":"address"}],"name":"LocatorContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"approvedValidatorsCount","type":"uint256"}],"name":"VettedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"depositedValidatorsCount","type":"uint256"}],"name":"DepositedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"exitedValidatorsCount","type":"uint256"}],"name":"ExitedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalValidatorsCount","type":"uint256"}],"name":"TotalSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nonce","type":"uint256"}],"name":"NonceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"}],"name":"StuckValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"RefundedValidatorsCount","type":"uint256"}],"name":"RefundedValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"targetValidatorsCount","type":"uint256"}],"name":"TargetValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipientAddress","type":"address"},{"indexed":false,"name":"sharesPenalizedAmount","type":"uint256"}],"name":"NodeOperatorPenalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"}] \ No newline at end of file +[{"constant":true,"inputs":[],"name":"hasInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getType","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_script","type":"bytes"}],"name":"getEVMScriptExecutor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getRecoveryVault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getNodeOperatorIds","outputs":[{"name":"nodeOperatorIds","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_offset","type":"uint256"},{"name":"_limit","type":"uint256"}],"name":"getSigningKeys","outputs":[{"name":"pubkeys","type":"bytes"},{"name":"signatures","type":"bytes"},{"name":"used","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorIsActive","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_name","type":"string"}],"name":"setNodeOperatorName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_totalRewardShares","type":"uint256"}],"name":"getRewardsDistribution","outputs":[{"name":"recipients","type":"address[]"},{"name":"shares","type":"uint256[]"},{"name":"penalized","type":"bool[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_indexFrom","type":"uint256"},{"name":"_indexTo","type":"uint256"}],"name":"invalidateReadyToDepositKeysRange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint64"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_delay","type":"uint256"}],"name":"setStuckPenaltyDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStuckPenaltyDelay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fromIndex","type":"uint256"},{"name":"_keysCount","type":"uint256"}],"name":"removeSigningKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"deactivateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token","type":"address"}],"name":"allowRecoverability","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"STAKING_ROUTER_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_keysCount","type":"uint256"},{"name":"_publicKeys","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"addSigningKeysOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"appId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onAllValidatorCountersUpdated","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getActiveNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_rewardAddress","type":"address"}],"name":"addNodeOperator","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContractVersion","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getUnusedSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_NODE_OPERATOR_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onWithdrawalCredentialsChanged","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"activateNodeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_rewardAddress","type":"address"}],"name":"setNodeOperatorRewardAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_fullInfo","type":"bool"}],"name":"getNodeOperator","outputs":[{"name":"active","type":"bool"},{"name":"name","type":"string"},{"name":"rewardAddress","type":"address"},{"name":"stakingLimit","type":"uint64"},{"name":"stoppedValidators","type":"uint64"},{"name":"totalSigningKeys","type":"uint64"},{"name":"usedSigningKeys","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStakingModuleSummary","outputs":[{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"transferToVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sender","type":"address"},{"name":"_role","type":"bytes32"},{"name":"_params","type":"uint256[]"}],"name":"canPerform","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_refundedValidatorsCount","type":"uint256"}],"name":"updateRefundedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEVMScriptRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNodeOperatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_vettedSigningKeysCount","type":"uint64"}],"name":"setNodeOperatorStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getNodeOperatorSummary","outputs":[{"name":"isTargetLimitActive","type":"bool"},{"name":"targetValidatorsCount","type":"uint256"},{"name":"stuckValidatorsCount","type":"uint256"},{"name":"refundedValidatorsCount","type":"uint256"},{"name":"stuckPenaltyEndTimestamp","type":"uint256"},{"name":"totalExitedValidators","type":"uint256"},{"name":"totalDepositedValidators","type":"uint256"},{"name":"depositableValidatorsCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"getSigningKey","outputs":[{"name":"key","type":"bytes"},{"name":"depositSignature","type":"bytes"},{"name":"used","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATOR_NAME_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"name":"depositsCount","type":"uint256"},{"name":"publicKeys","type":"bytes"},{"name":"signatures","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getKeysOpIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNonce","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kernel","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLocator","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SET_NODE_OPERATOR_LIMIT_ROLE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"getTotalSigningKeyCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isPetrified","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"}],"name":"updateExitedValidatorsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"updateStuckValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_NODE_OPERATORS_COUNT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_index","type":"uint256"}],"name":"removeSigningKeyOperatorBH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"handleRewardsMinted","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorId","type":"uint256"},{"name":"_exitedValidatorsCount","type":"uint256"},{"name":"_stuckValidatorsCount","type":"uint256"}],"name":"unsafeUpdateValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MANAGE_SIGNING_KEYS","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"stakingLimit","type":"uint64"}],"name":"NodeOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"active","type":"bool"}],"name":"NodeOperatorActiveSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"name","type":"string"}],"name":"NodeOperatorNameSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"rewardAddress","type":"address"}],"name":"NodeOperatorRewardAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalKeysTrimmed","type":"uint64"}],"name":"NodeOperatorTotalKeysTrimmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keysOpIndex","type":"uint256"}],"name":"KeysOpIndexSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"moduleType","type":"bytes32"}],"name":"StakingModuleTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"rewardAddress","type":"address"},{"indexed":false,"name":"sharesAmount","type":"uint256"}],"name":"RewardsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"locatorAddress","type":"address"}],"name":"LocatorContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"approvedValidatorsCount","type":"uint256"}],"name":"VettedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"depositedValidatorsCount","type":"uint256"}],"name":"DepositedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"exitedValidatorsCount","type":"uint256"}],"name":"ExitedSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"totalValidatorsCount","type":"uint256"}],"name":"TotalSigningKeysCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"nonce","type":"uint256"}],"name":"NonceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"}],"name":"StuckValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"RefundedValidatorsCount","type":"uint256"}],"name":"RefundedValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"targetValidatorsCount","type":"uint256"}],"name":"TargetValidatorsCountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipientAddress","type":"address"},{"indexed":false,"name":"sharesPenalizedAmount","type":"uint256"}],"name":"NodeOperatorPenalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"executor","type":"address"},{"indexed":false,"name":"script","type":"bytes"},{"indexed":false,"name":"input","type":"bytes"},{"indexed":false,"name":"returnData","type":"bytes"}],"name":"ScriptResult","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"vault","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"RecoverToVault","type":"event"}] \ No newline at end of file From 3fcffd248060ac25f7e7d4701543eef9864aedd4 Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 13 Feb 2023 23:00:16 +0700 Subject: [PATCH 64/82] getKeysOpIndex deprecated --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 5f25796c8..95d25adf8 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -890,18 +890,6 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { return signingKeysStats.get(TOTAL_KEYS_COUNT_OFFSET) - signingKeysStats.get(DEPOSITED_KEYS_COUNT_OFFSET); } - /// @notice Returns a monotonically increasing counter that gets incremented when any of the following happens: - /// @dev DEPRECATED: use getNonce() instead - /// 1. a node operator's key(s) is added; - /// 2. a node operator's key(s) is removed; - /// 3. a node operator's vetted keys count is changed. - /// 4. a node operator was activated/deactivated. Activation or deactivation of node operator - /// might lead to usage of unvalidated keys in the assignNextSigningKeys method. - /// 5. a node operator's deposit data is used for the deposit - function getKeysOpIndex() external view returns (uint256) { - return KEYS_OP_INDEX_POSITION.getStorageUint256(); - } - /// @notice Returns n-th signing key of the node operator #`_nodeOperatorId` /// @param _nodeOperatorId Node Operator id /// @param _index Index of the key, starting with 0 @@ -1049,6 +1037,19 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { return KEYS_OP_INDEX_POSITION.getStorageUint256(); } + /// @notice Returns a counter that MUST change its value whenever the deposit data set changes. + /// Below is the typical list of actions that requires an update of the nonce: + /// 1. a node operator's deposit data is added + /// 2. a node operator's deposit data is removed + /// 3. a node operator's ready-to-deposit data size is changed + /// 4. a node operator was activated/deactivated + /// 5. a node operator's deposit data is used for the deposit + /// Note: Depending on the StakingModule implementation above list might be extended + /// @dev DEPRECATED use getNonce() instead + function getKeysOpIndex() external view returns (uint256) { + return KEYS_OP_INDEX_POSITION.getStorageUint256(); + } + /// @notice distributes rewards among node operators /// @return the amount of stETH shares distributed among node operators function _distributeRewards() internal returns (uint256 distributed) { From 6509e1adb4eeb0d9dc0974d7a0faacdc3508de64 Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 13 Feb 2023 23:06:26 +0700 Subject: [PATCH 65/82] move penalty delay to initialize --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 95d25adf8..c077181fc 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -153,6 +153,9 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @dev Human-readable name string name; /// @dev The below variables store the signing keys info of the node operator. + /// signingKeysStats - contains packed variables: uint64 exitedSigningKeysCount, uint64 depositedSigningKeysCount, + /// uint64 vettedSigningKeysCount, uint64 totalSigningKeysCount + /// /// These variables can take values in the following ranges: /// /// 0 <= exitedSigningKeysCount <= depositedSigningKeysCount @@ -195,8 +198,6 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { _checkContractVersion(0); _initialize_v2(_locator, _type); - _setStuckPenaltyDelay(2 days); - uint256 totalOperators = getNodeOperatorsCount(); Packed64x4.Packed memory signingKeysStats; for (uint256 operatorId; operatorId < totalOperators; ++operatorId) { @@ -231,6 +232,8 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { _setContractVersion(2); + _setStuckPenaltyDelay(2 days); + // set unlimited allowance for burner from staking router // to burn stuck keys penalized shares IStETH(getLocator().lido()).approve(getLocator().burner(), ~uint256(0)); From badd75c90b7484eaf92d52dfe0ed8313ec029db0 Mon Sep 17 00:00:00 2001 From: ujenjt Date: Mon, 13 Feb 2023 17:22:09 +0100 Subject: [PATCH 66/82] fix: polish naming and move comment for solidity compiler into the right place --- contracts/0.8.9/oracle/AccountingOracle.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index 048f40beb..4fd2a62f1 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -686,11 +686,11 @@ contract AccountingOracle is BaseOracle { uint256 maxNodeOperatorsPerItem = 0; uint256 maxNodeOperatorItemIndex = 0; - /// @solidity memory-safe-assembly while (dataOffset < data.length) { uint256 index; uint256 itemType; + /// @solidity memory-safe-assembly assembly { // layout at the dataOffset: // | 3 bytes | 2 bytes | X bytes | @@ -736,7 +736,7 @@ contract AccountingOracle is BaseOracle { } } - function _processExtraDataItem(bytes calldata data, ExtraDataIterState memory iter) internal returns (uint256 nodeOpsProcessed) { + function _processExtraDataItem(bytes calldata data, ExtraDataIterState memory iter) internal returns (uint256) { uint256 dataOffset = iter.dataOffset; uint256 moduleId; uint256 nodeOpsCount; From ce986392ea02e285f1f907604523fb53b0fc98ce Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Mon, 13 Feb 2023 19:33:06 +0300 Subject: [PATCH 67/82] handle oracle report more tests --- contracts/0.8.9/test_helpers/FunderMock.sol | 10 + test/0.4.24/lido-handle-oracle-report.test.js | 256 ++++++++++++++++-- 2 files changed, 244 insertions(+), 22 deletions(-) create mode 100644 contracts/0.8.9/test_helpers/FunderMock.sol diff --git a/contracts/0.8.9/test_helpers/FunderMock.sol b/contracts/0.8.9/test_helpers/FunderMock.sol new file mode 100644 index 000000000..7795b1b85 --- /dev/null +++ b/contracts/0.8.9/test_helpers/FunderMock.sol @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2023 Lido +//SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + +contract FunderMock { + function pay(address payable _target) external payable { + selfdestruct(_target); + } +} diff --git a/test/0.4.24/lido-handle-oracle-report.test.js b/test/0.4.24/lido-handle-oracle-report.test.js index b22df4e4a..b95a785d3 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -6,13 +6,15 @@ const { EvmSnapshot } = require('../helpers/blockchain') const { ZERO_ADDRESS } = require('../helpers/constants') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') -const ETHForwarderMock = artifacts.require('ETHForwarderMock') +const FunderMock = artifacts.require('FunderMock') +const RewardEmulatorMock = artifacts.require('RewardEmulatorMock') const ONE_YEAR = 3600 * 24 * 365 const ONE_DAY = 3600 * 24 contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, anotherStranger, depositor, operator]) => { let deployed, snapshot, lido, treasury, voting, oracle - let curatedModule, oracleReportSanityChecker + let curatedModule, oracleReportSanityChecker, elRewardsVault + let withdrawalRewarderMock, withdrawalVault, elRewarderMock let strangerBalanceBefore, anotherStrangerBalanceBefore, totalPooledEtherBefore, @@ -38,7 +40,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another } }) - await ETHForwarderMock.new(deployed.oracle.address, { from: appManager, value: ETH(1) }) + const funder = await FunderMock.new() + await funder.pay(deployed.oracle.address, { value: ETH(1) }) + withdrawalRewarderMock = await RewardEmulatorMock.new(deployed.withdrawalVault.address) + elRewarderMock = await RewardEmulatorMock.new(deployed.elRewardsVault.address) await hre.ethers.getImpersonatedSigner(deployed.oracle.address) await curatedModule.addNodeOperator('1', operator, { from: deployed.voting.address }) @@ -52,6 +57,8 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another voting = deployed.voting.address oracle = deployed.oracle.address oracleReportSanityChecker = deployed.oracleReportSanityChecker + withdrawalVault = deployed.withdrawalVault.address + elRewardsVault = deployed.elRewardsVault.address await lido.submit(ZERO_ADDRESS, { from: stranger, value: ETH(30) }) await lido.submit(ZERO_ADDRESS, { from: anotherStranger, value: ETH(70) }) @@ -415,6 +422,20 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another 'IncorrectAppearedValidators(101)' ) }) + }) + + describe('smooth report', async () => { + beforeEach(async () => { + await await lido.deposit(3, 1, '0x', { from: depositor }) + await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) + await checkBalanceDeltas({ + totalPooledEtherDiff: 0, + treasuryBalanceDiff: 0, + strangerBalanceDiff: 0, + anotherStrangerBalanceDiff: 0, + curatedModuleBalanceDiff: 0 + }) + }) it('does not smooth if report in limits', async () => { await oracleReportSanityChecker.setOracleReportLimits( @@ -450,26 +471,217 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another ) await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(100), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(100) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(4), + treasuryBalanceDiff: ETH(4 * 0.05), + strangerBalanceDiff: ETH(4 * 0.3 * 0.9), + anotherStrangerBalanceDiff: ETH(4 * 0.7 * 0.9), + curatedModuleBalanceDiff: ETH(4 * 0.05) + }) + }) + + it('does not smooth withdrawals if report in limits', async () => { + await withdrawalRewarderMock.reward({ value: ETH(1) }) + + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: ETH(0.05), + strangerBalanceDiff: ETH(0.3 * 0.9), + anotherStrangerBalanceDiff: ETH(0.7 * 0.9), + curatedModuleBalanceDiff: ETH(0.05) + }) + assert.equals(await ethers.provider.getBalance(withdrawalVault), 0) }) - // it('smooths withdrawals if report in limits', async () => { - // await ETHForwarderMock.new(deployed.withdrawalVault.address, { from: appManager, value: ETH(1) }) - - // await oracleReportSanityChecker.setOracleReportLimits( - // { - // churnValidatorsPerDayLimit: 100, - // oneOffCLBalanceDecreaseBPLimit: 100, - // annualBalanceIncreaseBPLimit: 10000, - // shareRateDeviationBPLimit: 10000, - // maxValidatorExitRequestsPerReport: 10000, - // requestTimestampMargin: 0, - // maxPositiveTokenRebase: 10000000, - // maxAccountingExtraDataListItemsCount: 10000 - // }, - // { from: voting, gasPrice: 1 } - // ) - // await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) - // await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(97) }) - // }) + it('smooths withdrawals if report out of limit', async () => { + await withdrawalRewarderMock.reward({ value: ETH(1.1) }) + + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: ETH(0.05), + strangerBalanceDiff: ETH(0.3 * 0.9), + anotherStrangerBalanceDiff: ETH(0.7 * 0.9), + curatedModuleBalanceDiff: ETH(0.05) + }) + + assert.equals(await ethers.provider.getBalance(withdrawalVault), ETH(0.1)) + }) + + it('does not smooth el rewards if report in limit without lido fee', async () => { + await elRewarderMock.reward({ value: ETH(1) }) + + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1), 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: 0, + strangerBalanceDiff: ETH(0.3), + anotherStrangerBalanceDiff: ETH(0.7), + curatedModuleBalanceDiff: 0 + }) + + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + }) + + it('does not smooth el rewards if report in limit without lido fee', async () => { + await elRewarderMock.reward({ value: ETH(1.5) }) + + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(95.5), 0, ETH(1.5), 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.5) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: 0, + strangerBalanceDiff: ETH(0.3), + anotherStrangerBalanceDiff: ETH(0.7), + curatedModuleBalanceDiff: 0 + }) + + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + }) + + it('smooths el rewards if report out of limit without lido fee', async () => { + await elRewarderMock.reward({ value: ETH(1.1) }) + + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1.1), 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: 0, + strangerBalanceDiff: ETH(0.3), + anotherStrangerBalanceDiff: ETH(0.7), + curatedModuleBalanceDiff: 0 + }) + + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.1)) + }) + + it('does not smooth el rewards if report in limit', async () => { + await elRewarderMock.reward({ value: ETH(1) }) + + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(0.9), 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: ETH(0.05), + strangerBalanceDiff: ETH(0.3 * 0.9), + anotherStrangerBalanceDiff: ETH(0.7 * 0.9), + curatedModuleBalanceDiff: ETH(0.05) + }) + + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.1)) + }) + + it('smooths el rewards if report out of limit', async () => { + await elRewarderMock.reward({ value: ETH(1.1) }) + + await oracleReportSanityChecker.setOracleReportLimits( + { + churnValidatorsPerDayLimit: 100, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + shareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 10000000, + maxAccountingExtraDataListItemsCount: 10000 + }, + { from: voting, gasPrice: 1 } + ) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(1.1), 0, 0, { from: oracle, gasPrice: 1 }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), + treasuryBalanceDiff: ETH(0.05), + strangerBalanceDiff: ETH(0.3 * 0.9), + anotherStrangerBalanceDiff: ETH(0.7 * 0.9), + curatedModuleBalanceDiff: ETH(0.05) + }) + + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.2)) + }) }) }) From 9fffe8265b3c4635c47534f9a9fc0bd5ca891350 Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 13 Feb 2023 23:36:34 +0700 Subject: [PATCH 68/82] skip unchecked tests --- test/0.4.24/node-operators-registry.test.js | 140 ++++++++++---------- 1 file changed, 69 insertions(+), 71 deletions(-) diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index 6ff1b585b..3b5f4ab3f 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -1558,44 +1558,44 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.exitedSigningKeysCount, 1) }) - // it('respects staking limit', async () => { - // const [firstNodeOperatorKeysStats, secondNodeOperatorKeysStats] = await Promise.all([ - // app.getNodeOperatorSummary(firstNodeOperatorId), - // app.getValidatorsKeysStats(secondNodeOperatorId) - // ]) - - // assert.isTrue(firstNodeOperatorKeysStats.readyToDepositValidatorsKeysCount.toNumber() > 0) - // assert.isTrue(secondNodeOperatorKeysStats.readyToDepositValidatorsKeysCount.toNumber() > 0) - - // assert.equals(firstNodeOperatorKeysStats.exitedValidatorsCount, 1) - // assert.equals(firstNodeOperatorKeysStats.activeValidatorsKeysCount, 4) - // assert.equals(firstNodeOperatorKeysStats.readyToDepositValidatorsKeysCount, 3) - - // assert.equals(secondNodeOperatorKeysStats.exitedValidatorsCount, 0) - // assert.equals(secondNodeOperatorKeysStats.activeValidatorsKeysCount, 5) - // assert.equals(secondNodeOperatorKeysStats.readyToDepositValidatorsKeysCount, 5) - - // const keysToAllocate = 7 - // const { allocatedKeysCount, nodeOperatorIds, activeKeyCountsAfterAllocation } = - // await app.testing_getSigningKeysAllocationData(keysToAllocate) - - // assert.equals(allocatedKeysCount, keysToAllocate) - // assert.equal(nodeOperatorIds.length, 2) - // assert.equals(nodeOperatorIds[0], firstNodeOperatorId) - // assert.equals(nodeOperatorIds[1], secondNodeOperatorId) - - // assert.equal(activeKeyCountsAfterAllocation.length, 2) - // // the first node operator has to receive 3 deposits cause reached limit - // assert.equals( - // activeKeyCountsAfterAllocation[0], - // firstNodeOperatorKeysStats.activeValidatorsKeysCount.toNumber() + 3 - // ) - // // the second receives 4 deposits - // assert.equals( - // activeKeyCountsAfterAllocation[1], - // secondNodeOperatorKeysStats.activeValidatorsKeysCount.toNumber() + 4 - // ) - // }) + it.skip('respects staking limit', async () => { + const [firstNodeOperatorKeysStats, secondNodeOperatorKeysStats] = await Promise.all([ + app.getNodeOperatorSummary(firstNodeOperatorId), + app.getValidatorsKeysStats(secondNodeOperatorId) + ]) + + assert.isTrue(firstNodeOperatorKeysStats.readyToDepositValidatorsKeysCount.toNumber() > 0) + assert.isTrue(secondNodeOperatorKeysStats.readyToDepositValidatorsKeysCount.toNumber() > 0) + + assert.equals(firstNodeOperatorKeysStats.exitedValidatorsCount, 1) + assert.equals(firstNodeOperatorKeysStats.activeValidatorsKeysCount, 4) + assert.equals(firstNodeOperatorKeysStats.readyToDepositValidatorsKeysCount, 3) + + assert.equals(secondNodeOperatorKeysStats.exitedValidatorsCount, 0) + assert.equals(secondNodeOperatorKeysStats.activeValidatorsKeysCount, 5) + assert.equals(secondNodeOperatorKeysStats.readyToDepositValidatorsKeysCount, 5) + + const keysToAllocate = 7 + const { allocatedKeysCount, nodeOperatorIds, activeKeyCountsAfterAllocation } = + await app.testing_getSigningKeysAllocationData(keysToAllocate) + + assert.equals(allocatedKeysCount, keysToAllocate) + assert.equal(nodeOperatorIds.length, 2) + assert.equals(nodeOperatorIds[0], firstNodeOperatorId) + assert.equals(nodeOperatorIds[1], secondNodeOperatorId) + + assert.equal(activeKeyCountsAfterAllocation.length, 2) + // the first node operator has to receive 3 deposits cause reached limit + assert.equals( + activeKeyCountsAfterAllocation[0], + firstNodeOperatorKeysStats.activeValidatorsKeysCount.toNumber() + 3 + ) + // the second receives 4 deposits + assert.equals( + activeKeyCountsAfterAllocation[1], + secondNodeOperatorKeysStats.activeValidatorsKeysCount.toNumber() + 4 + ) + }) }) describe('getSigningKeysAllocationData()', async () => { @@ -2451,46 +2451,44 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ) }) - // it.only('correctly decreases global vetted signing keys and totalTargetStats count if key index is less then vetted keys counter of node operator', async () => { - // const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 - // assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - // const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - - // const { - // isTargetLimitActive: isTargetLimitActiveBefore, - // targetValidatorsCount: targetValidatorsCountBefore, - // excessValidatorsCount: excessValidatorsCountBefore, - // } = await app.testing_getTotalTargetStats(); + it.skip('correctly decreases global vetted signing keys and totalTargetStats count if key index is less then vetted keys counter of node operator', async () => { + const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 + assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) + const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - // // await app.updateTargetValidatorsLimits(secondNodeOperatorId, true, 2, { from: voting }) + const { + isTargetLimitActive: isTargetLimitActiveBefore, + targetValidatorsCount: targetValidatorsCountBefore, + excessValidatorsCount: excessValidatorsCountBefore, + } = await app.testing_getTotalTargetStats(); - // await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) - // const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() - // const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex - // assert.equal( - // vettedSigningKeysCountAfter.toNumber(), - // vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysDecrement - // ) + const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex + assert.equal( + vettedSigningKeysCountAfter.toNumber(), + vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysDecrement + ) - // const { - // isTargetLimitActive: isTargetLimitActiveAfter, - // targetValidatorsCount: targetValidatorsCountAfter, - // excessValidatorsCount: excessValidatorsCountAfter, - // } = await app.testing_getTotalTargetStats(); + const { + isTargetLimitActive: isTargetLimitActiveAfter, + targetValidatorsCount: targetValidatorsCountAfter, + excessValidatorsCount: excessValidatorsCountAfter, + } = await app.testing_getTotalTargetStats(); - // console.log({ - // targetValidatorsCountBefore: targetValidatorsCountBefore.toNumber(), - // targetValidatorsCountAfter: targetValidatorsCountAfter.toNumber(), - // vettedSigningKeysCountBefore: vettedSigningKeysCountBefore.toNumber() , - // vettedSigningKeysDecrement + console.log({ + targetValidatorsCountBefore: targetValidatorsCountBefore.toNumber(), + targetValidatorsCountAfter: targetValidatorsCountAfter.toNumber(), + vettedSigningKeysCountBefore: vettedSigningKeysCountBefore.toNumber() , + vettedSigningKeysDecrement - // }) + }) - // assertBn(isTargetLimitActiveAfter, isTargetLimitActiveBefore) - // assertBn(targetValidatorsCountAfter, targetValidatorsCountBefore.toNumber() - vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysDecrement) - // assertBn(excessValidatorsCountAfter, excessValidatorsCountBefore) - // }) + assertBn(isTargetLimitActiveAfter, isTargetLimitActiveBefore) + assertBn(targetValidatorsCountAfter, targetValidatorsCountBefore.toNumber() - vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysDecrement) + assertBn(excessValidatorsCountAfter, excessValidatorsCountBefore) + }) it("doesn't modify global vetted signing keys count if key index is equal to vettedSigningKeysCount", async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount From 2478df202989fae3d21d2c10aa7b1db35dd2d87a Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 13 Feb 2023 23:40:06 +0700 Subject: [PATCH 69/82] await reverts --- test/0.4.24/node-operators-registry-penalty.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/0.4.24/node-operators-registry-penalty.test.js b/test/0.4.24/node-operators-registry-penalty.test.js index 7cfd6af26..a94b78c61 100644 --- a/test/0.4.24/node-operators-registry-penalty.test.js +++ b/test/0.4.24/node-operators-registry-penalty.test.js @@ -311,7 +311,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 1, { from: voting }) await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0, { from: voting }) - assert.reverts(app.updateRefundedValidatorsCount(firstNodeOperator, 1000, { from: voting }), "test") + await assert.reverts(app.updateRefundedValidatorsCount(firstNodeOperator, 1000, { from: voting }), "test") }) it('penalized firstOperator, add refund less than stuck validators', async () => { From 72bf913577217fa130e0484ccddd54ad7ac52d82 Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 13 Feb 2023 23:44:31 +0700 Subject: [PATCH 70/82] fix test --- test/0.4.24/node-operators-registry-penalty.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/0.4.24/node-operators-registry-penalty.test.js b/test/0.4.24/node-operators-registry-penalty.test.js index a94b78c61..cfb05752b 100644 --- a/test/0.4.24/node-operators-registry-penalty.test.js +++ b/test/0.4.24/node-operators-registry-penalty.test.js @@ -311,7 +311,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await app.unsafeUpdateValidatorsCount(firstNodeOperator, 1, 1, { from: voting }) await app.unsafeUpdateValidatorsCount(secondNodeOperator, 1, 0, { from: voting }) - await assert.reverts(app.updateRefundedValidatorsCount(firstNodeOperator, 1000, { from: voting }), "test") + await assert.reverts(app.updateRefundedValidatorsCount(firstNodeOperator, 1000, { from: voting }), "OUT_OF_RANGE") }) it('penalized firstOperator, add refund less than stuck validators', async () => { From 38aa9edcfa049b7ccc82080fe1663ec23a7cd448 Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Mon, 13 Feb 2023 20:44:14 +0300 Subject: [PATCH 71/82] replace selfdestruct with setBalance --- contracts/0.8.9/test_helpers/FunderMock.sol | 10 -------- test/0.4.24/lido-handle-oracle-report.test.js | 25 ++++++++----------- test/helpers/utils.js | 6 +++++ 3 files changed, 16 insertions(+), 25 deletions(-) delete mode 100644 contracts/0.8.9/test_helpers/FunderMock.sol diff --git a/contracts/0.8.9/test_helpers/FunderMock.sol b/contracts/0.8.9/test_helpers/FunderMock.sol deleted file mode 100644 index 7795b1b85..000000000 --- a/contracts/0.8.9/test_helpers/FunderMock.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Lido -//SPDX-License-Identifier: GPL-3.0 - -pragma solidity 0.8.9; - -contract FunderMock { - function pay(address payable _target) external payable { - selfdestruct(_target); - } -} diff --git a/test/0.4.24/lido-handle-oracle-report.test.js b/test/0.4.24/lido-handle-oracle-report.test.js index b95a785d3..a94fb0913 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1,20 +1,18 @@ const hre = require('hardhat') const { assert } = require('../helpers/assert') -const { ETH, toBN, genKeys } = require('../helpers/utils') +const { ETH, toBN, genKeys, setBalance } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') const { EvmSnapshot } = require('../helpers/blockchain') const { ZERO_ADDRESS } = require('../helpers/constants') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') -const FunderMock = artifacts.require('FunderMock') -const RewardEmulatorMock = artifacts.require('RewardEmulatorMock') const ONE_YEAR = 3600 * 24 * 365 const ONE_DAY = 3600 * 24 contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, anotherStranger, depositor, operator]) => { let deployed, snapshot, lido, treasury, voting, oracle let curatedModule, oracleReportSanityChecker, elRewardsVault - let withdrawalRewarderMock, withdrawalVault, elRewarderMock + let withdrawalVault let strangerBalanceBefore, anotherStrangerBalanceBefore, totalPooledEtherBefore, @@ -40,10 +38,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another } }) - const funder = await FunderMock.new() - await funder.pay(deployed.oracle.address, { value: ETH(1) }) - withdrawalRewarderMock = await RewardEmulatorMock.new(deployed.withdrawalVault.address) - elRewarderMock = await RewardEmulatorMock.new(deployed.elRewardsVault.address) + await setBalance(deployed.oracle.address, ETH(1)) await hre.ethers.getImpersonatedSigner(deployed.oracle.address) await curatedModule.addNodeOperator('1', operator, { from: deployed.voting.address }) @@ -481,7 +476,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('does not smooth withdrawals if report in limits', async () => { - await withdrawalRewarderMock.reward({ value: ETH(1) }) + await setBalance(withdrawalVault, ETH(1)) await oracleReportSanityChecker.setOracleReportLimits( { @@ -509,7 +504,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('smooths withdrawals if report out of limit', async () => { - await withdrawalRewarderMock.reward({ value: ETH(1.1) }) + await setBalance(withdrawalVault, ETH(1.1)) await oracleReportSanityChecker.setOracleReportLimits( { @@ -538,7 +533,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('does not smooth el rewards if report in limit without lido fee', async () => { - await elRewarderMock.reward({ value: ETH(1) }) + await setBalance(elRewardsVault, ETH(1)) await oracleReportSanityChecker.setOracleReportLimits( { @@ -568,7 +563,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('does not smooth el rewards if report in limit without lido fee', async () => { - await elRewarderMock.reward({ value: ETH(1.5) }) + await setBalance(elRewardsVault, ETH(1.5)) await oracleReportSanityChecker.setOracleReportLimits( { @@ -597,7 +592,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('smooths el rewards if report out of limit without lido fee', async () => { - await elRewarderMock.reward({ value: ETH(1.1) }) + await setBalance(elRewardsVault, ETH(1.1)) await oracleReportSanityChecker.setOracleReportLimits( { @@ -626,7 +621,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('does not smooth el rewards if report in limit', async () => { - await elRewarderMock.reward({ value: ETH(1) }) + await setBalance(elRewardsVault, ETH(1)) await oracleReportSanityChecker.setOracleReportLimits( { @@ -656,7 +651,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('smooths el rewards if report out of limit', async () => { - await elRewarderMock.reward({ value: ETH(1.1) }) + await setBalance(elRewardsVault, ETH(1.1)) await oracleReportSanityChecker.setOracleReportLimits( { diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 70201a20c..7f0a59c75 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -1,3 +1,4 @@ +const hre = require('hardhat') const { BN } = require('bn.js') const { getEventAt } = require('@aragon/contract-helpers-test') @@ -140,6 +141,10 @@ const changeEndianness = (string) => { const toNum = (x) => Array.isArray(x) ? x.map(toNum) : +x const toStr = (x) => Array.isArray(x) ? x.map(toStr) : `${x}` +const setBalance = async (address, value) => { + await hre.network.provider.send('hardhat_setBalance', [address, '0x' + toBN(value).toString(16)]) +} + module.exports = { ZERO_HASH, pad, @@ -173,4 +178,5 @@ module.exports = { padRight, toNum, toStr, + setBalance } From 3775eeeeee3b6cc5debb71a33f50ddee5f87cce2 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 13 Feb 2023 22:21:59 +0400 Subject: [PATCH 72/82] Emit BaseURISet event --- contracts/0.8.9/WithdrawalRequestNFT.sol | 3 +++ lib/abi/WithdrawalRequestNFT.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/0.8.9/WithdrawalRequestNFT.sol b/contracts/0.8.9/WithdrawalRequestNFT.sol index 37e88d8c2..9f9bcc33d 100644 --- a/contracts/0.8.9/WithdrawalRequestNFT.sol +++ b/contracts/0.8.9/WithdrawalRequestNFT.sol @@ -39,6 +39,8 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { string value; } + event BaseURISet(string baseURI); + error ApprovalToOwner(); error ApproveToCaller(); error NotOwnerOrApprovedForAll(address sender); @@ -103,6 +105,7 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { /// @notice Sets the Base URI for computing {tokenURI} function setBaseUri(string calldata _baseUri) external onlyRole(SET_BASE_URI_ROLE) { _getBaseUri().value = _baseUri; + emit BaseURISet(_baseUri); } /// @dev See {IERC721-balanceOf}. diff --git a/lib/abi/WithdrawalRequestNFT.json b/lib/abi/WithdrawalRequestNFT.json index 1582771e6..37424a812 100644 --- a/lib/abi/WithdrawalRequestNFT.json +++ b/lib/abi/WithdrawalRequestNFT.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_wstETH","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"InvalidOwnerAddress","type":"error"},{"inputs":[],"name":"InvalidReportTimestamp","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"InvalidRequestId","type":"error"},{"inputs":[{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"endId","type":"uint256"}],"name":"InvalidRequestIdRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"_expectedLength","type":"uint256"},{"internalType":"uint256","name":"_actualLength","type":"uint256"}],"name":"LengthsMismatch","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NotEnoughEther","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"NotOwner","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApproved","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApprovedForAll","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooLarge","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooSmall","type":"error"},{"inputs":[],"name":"RequestIdsNotSorted","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"realOwner","type":"address"}],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferFromZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"TransferToNonIERC721Receiver","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"Unimplemented","type":"error"},{"inputs":[],"name":"Uninitialized","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[],"name":"BunkerModeDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"BunkerModeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_admin","type":"address"},{"indexed":false,"internalType":"address","name":"_pauser","type":"address"},{"indexed":false,"internalType":"address","name":"_resumer","type":"address"},{"indexed":false,"internalType":"address","name":"_finalizer","type":"address"},{"indexed":false,"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"to","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfETHLocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sharesToBurn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"WithdrawalBatchFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfETH","type":"uint256"}],"name":"WithdrawalClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"requestor","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"WithdrawalRequested","type":"event"},{"inputs":[],"name":"BUNKER_MODE_DISABLED_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUNKER_MODE_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_BASE_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WSTETH","outputs":[{"internalType":"contract IWstETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_hint","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256","name":"hint","type":"uint256"}],"internalType":"struct WithdrawalQueue.ClaimWithdrawalInput[]","name":"_claimWithdrawalInputs","type":"tuple[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalizationBatch","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"findCheckpointHint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"findCheckpointHintUnbounded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256","name":"_firstIndex","type":"uint256"},{"internalType":"uint256","name":"_lastIndex","type":"uint256"}],"name":"findCheckpointHints","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"findCheckpointHintsUnbounded","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"}],"name":"findLastFinalizableRequestId","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByBudget","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByTimestamp","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastCheckpointIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastFinalizedRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLockedEtherAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getWithdrawalRequestStatus","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalRequestStatuses","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus[]","name":"statuses","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_pauser","type":"address"},{"internalType":"address","name":"_resumer","type":"address"},{"internalType":"address","name":"_finalizer","type":"address"},{"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBunkerModeActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawals","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawalsWstETH","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWstETHWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseUri","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unfinalizedRequestNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unfinalizedStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"updateBunkerMode","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_wstETH","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"InvalidOwnerAddress","type":"error"},{"inputs":[],"name":"InvalidReportTimestamp","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"InvalidRequestId","type":"error"},{"inputs":[{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"endId","type":"uint256"}],"name":"InvalidRequestIdRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"_expectedLength","type":"uint256"},{"internalType":"uint256","name":"_actualLength","type":"uint256"}],"name":"LengthsMismatch","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NotEnoughEther","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"NotOwner","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApproved","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApprovedForAll","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooLarge","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooSmall","type":"error"},{"inputs":[],"name":"RequestIdsNotSorted","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"realOwner","type":"address"}],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferFromZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"TransferToNonIERC721Receiver","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"Unimplemented","type":"error"},{"inputs":[],"name":"Uninitialized","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURISet","type":"event"},{"anonymous":false,"inputs":[],"name":"BunkerModeDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"BunkerModeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_admin","type":"address"},{"indexed":false,"internalType":"address","name":"_pauser","type":"address"},{"indexed":false,"internalType":"address","name":"_resumer","type":"address"},{"indexed":false,"internalType":"address","name":"_finalizer","type":"address"},{"indexed":false,"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"to","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfETHLocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sharesToBurn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"WithdrawalBatchFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfETH","type":"uint256"}],"name":"WithdrawalClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"requestor","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"WithdrawalRequested","type":"event"},{"inputs":[],"name":"BUNKER_MODE_DISABLED_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUNKER_MODE_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_BASE_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WSTETH","outputs":[{"internalType":"contract IWstETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_hint","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256","name":"hint","type":"uint256"}],"internalType":"struct WithdrawalQueue.ClaimWithdrawalInput[]","name":"_claimWithdrawalInputs","type":"tuple[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalizationBatch","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"findCheckpointHint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"findCheckpointHintUnbounded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256","name":"_firstIndex","type":"uint256"},{"internalType":"uint256","name":"_lastIndex","type":"uint256"}],"name":"findCheckpointHints","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"findCheckpointHintsUnbounded","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"}],"name":"findLastFinalizableRequestId","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByBudget","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByTimestamp","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastCheckpointIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastFinalizedRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLockedEtherAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getWithdrawalRequestStatus","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalRequestStatuses","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus[]","name":"statuses","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_pauser","type":"address"},{"internalType":"address","name":"_resumer","type":"address"},{"internalType":"address","name":"_finalizer","type":"address"},{"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBunkerModeActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawals","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawalsWstETH","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWstETHWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseUri","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unfinalizedRequestNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unfinalizedStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"updateBunkerMode","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file From 516f6a30181e4505111bf5d6ece5be161630c73a Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 21:23:34 +0300 Subject: [PATCH 73/82] fix: redundant `_whenNotStopped()` in stETH --- contracts/0.4.24/StETH.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index 3e23f8e33..2b78eb9aa 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -229,8 +229,6 @@ contract StETH is IERC20, Pausable { * @dev The `_amount` argument is the amount of tokens, not shares. */ function transferFrom(address _sender, address _recipient, uint256 _amount) external returns (bool) { - _whenNotStopped(); - uint256 currentAllowance = allowances[_sender][msg.sender]; require(currentAllowance >= _amount, "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); @@ -488,7 +486,6 @@ contract StETH is IERC20, Pausable { */ function _burnShares(address _account, uint256 _sharesAmount) internal returns (uint256 newTotalShares) { require(_account != address(0), "BURN_FROM_THE_ZERO_ADDRESS"); - _whenNotStopped(); uint256 accountShares = shares[_account]; require(_sharesAmount <= accountShares, "BURN_AMOUNT_EXCEEDS_BALANCE"); From fe554e1951ea23e6afae277e7ae5fedc1cbda5bb Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 21:26:14 +0300 Subject: [PATCH 74/82] refactor: share rate sanity check precedence --- contracts/0.4.24/Lido.sol | 37 ++++++++++--------- .../OracleReportSanityChecker.sol | 17 ++++++--- .../OracleReportSanityCheckerMocks.sol | 6 ++- lib/abi/OracleReportSanityChecker.json | 2 +- .../oracle-report-sanity-checker.test.js | 9 +++-- 5 files changed, 43 insertions(+), 28 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index b04df0f4b..9fbd43f67 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -60,8 +60,10 @@ interface IOracleReportSanityChecker { ) external view; function checkSimulatedShareRate( - uint256 _noWithdrawalsPostTotalPooledEther, - uint256 _noWithdrawalsPostTotalShares, + uint256 _postTotalPooledEther, + uint256 _postTotalShares, + uint256 _etherLockedOnWithdrawalQueue, + uint256 _sharesBurntFromWithdrawalQueue, uint256 _simulatedShareRate ) external view; } @@ -102,7 +104,7 @@ interface IStakingRouter { } interface IWithdrawalQueue { - function finalizationBatch(uint256 _nextFinalizedRequestId, uint256 _shareRate) + function finalizationBatch(uint256 _newLastFinalizedRequestId, uint256 _shareRate) external view returns (uint128 eth, uint128 shares); @@ -1281,8 +1283,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 7. // Burn excess shares (withdrawn stETH at least) - uint256 postponedSharesToBurn = _burnSharesLimited( + uint256 burntWithdrawalQueueShares = _burnSharesLimited( IBurner(_contracts.burner), + reportContext.sharesToBurnFromWithdrawalQueue, reportContext.sharesToBurnLimit ); @@ -1299,16 +1302,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 9. Sanity check for the provided simulated share rate if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { - uint256 noWithdrawalsPostTotalShares = postTotalShares; - if (postponedSharesToBurn < reportContext.sharesToBurnFromWithdrawalQueue) { - noWithdrawalsPostTotalShares = noWithdrawalsPostTotalShares.add( - reportContext.sharesToBurnFromWithdrawalQueue - postponedSharesToBurn - ); - } - IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkSimulatedShareRate( - postTotalPooledEther.add(reportContext.etherToLockOnWithdrawalQueue), - noWithdrawalsPostTotalShares, + postTotalPooledEther, + postTotalShares, + reportContext.etherToLockOnWithdrawalQueue, + burntWithdrawalQueueShares, _reportedData.simulatedShareRate ); } @@ -1375,11 +1373,13 @@ contract Lido is Versioned, StETHPermit, AragonApp { * NB: some of the burning amount can be postponed for the next reports * if positive token rebase smoothened. * - * @return unburnt shares (postponed for next oracle reports) + * @return burnt shares from withdrawals queue (when some requests finalized) */ function _burnSharesLimited( - IBurner _burner, uint256 _sharesToBurnLimit - ) internal returns (uint256 postponedSharesToBurn) { + IBurner _burner, + uint256 _withdrawalsSharesToBurn, + uint256 _sharesToBurnLimit + ) internal returns (uint256 burntWithdrawalsShares) { if (_sharesToBurnLimit > 0) { uint256 sharesCommittedToBurnNow = _burner.commitSharesToBurn(_sharesToBurnLimit); @@ -1389,8 +1389,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { } (uint256 coverShares, uint256 nonCoverShares) = _burner.getSharesRequestedToBurn(); + uint256 postponedSharesToBurn = coverShares.add(nonCoverShares); - return coverShares.add(nonCoverShares); + burntWithdrawalsShares = + postponedSharesToBurn < _withdrawalsSharesToBurn ? + _withdrawalsSharesToBurn - postponedSharesToBurn : 0; } /** diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 1fc9ae88c..cc1dc2fc5 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -440,18 +440,25 @@ contract OracleReportSanityChecker is AccessControlEnumerable { } /// @notice Applies sanity checks to the simulated share rate for withdrawal requests finalization - /// @param _noWithdrawalsPostTotalPooledEther total pooled ether after report applied if no withdrawal requests finalized - /// @param _noWithdrawalsPostTotalShares total shares after report applied if no withdrawal requests finalized + /// @param _postTotalPooledEther total pooled ether after report applied + /// @param _postTotalShares total shares after report applied + /// @param _etherLockedOnWithdrawalQueue ether to lock on withdrawal queue + /// @param _sharesBurntFromWithdrawalQueue shares assigned to burn from withdrawal queue /// @param _simulatedShareRate share rate provided with the oracle report (simulated via static call) function checkSimulatedShareRate( - uint256 _noWithdrawalsPostTotalPooledEther, - uint256 _noWithdrawalsPostTotalShares, + uint256 _postTotalPooledEther, + uint256 _postTotalShares, + uint256 _etherLockedOnWithdrawalQueue, + uint256 _sharesBurntFromWithdrawalQueue, uint256 _simulatedShareRate ) external view { LimitsList memory limitsList = _limits.unpack(); _checkFinalizationShareRate( - limitsList, _noWithdrawalsPostTotalPooledEther, _noWithdrawalsPostTotalShares, _simulatedShareRate + limitsList, + _postTotalPooledEther + _etherLockedOnWithdrawalQueue, + _postTotalShares + _sharesBurntFromWithdrawalQueue, + _simulatedShareRate ); } diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index fede96cd3..195cdd32f 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -104,8 +104,10 @@ contract OracleReportSanityCheckerStub { ) external view {} function checkSimulatedShareRate( - uint256 _noWithdrawalsPostTotalPooledEther, - uint256 _noWithdrawalsPostTotalShares, + uint256 _postTotalPooledEther, + uint256 _postTotalShares, + uint256 _etherLockedOnWithdrawalQueue, + uint256 _sharesBurntFromWithdrawalQueue, uint256 _simulatedShareRate ) external view {} diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index fb15c9566..0b666eab2 100644 --- a/lib/abi/OracleReportSanityChecker.json +++ b/lib/abi/OracleReportSanityChecker.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualELRewardsVaultBalance","type":"uint256"}],"name":"IncorrectELRewardsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkAccountingOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_noWithdrawalsPostTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_noWithdrawalsPostTotalShares","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"checkSimulatedShareRate","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_lidoLocator","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"},{"components":[{"internalType":"address[]","name":"allLimitsManagers","type":"address[]"},{"internalType":"address[]","name":"churnValidatorsPerDayLimitManagers","type":"address[]"},{"internalType":"address[]","name":"oneOffCLBalanceDecreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"annualBalanceIncreaseLimitManagers","type":"address[]"},{"internalType":"address[]","name":"shareRateDeviationLimitManagers","type":"address[]"},{"internalType":"address[]","name":"maxValidatorExitRequestsPerReportManagers","type":"address[]"},{"internalType":"address[]","name":"maxAccountingExtraDataListItemsCountManagers","type":"address[]"},{"internalType":"address[]","name":"requestTimestampMarginManagers","type":"address[]"},{"internalType":"address[]","name":"maxPositiveTokenRebaseManagers","type":"address[]"}],"internalType":"struct OracleReportSanityChecker.ManagersRoster","name":"_managersRoster","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"limitPerDay","type":"uint256"},{"internalType":"uint256","name":"exitedPerDay","type":"uint256"}],"name":"ExitedValidatorsLimitExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectAppearedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBP","type":"uint256"}],"name":"IncorrectCLBalanceDecrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"annualBalanceDiff","type":"uint256"}],"name":"IncorrectCLBalanceIncrease","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualELRewardsVaultBalance","type":"uint256"}],"name":"IncorrectELRewardsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"churnLimit","type":"uint256"}],"name":"IncorrectExitedValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"finalizationShareDeviation","type":"uint256"}],"name":"IncorrectFinalizationShareRate","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxRequestsCount","type":"uint256"}],"name":"IncorrectNumberOfExitRequestsPerReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestCreationBlock","type":"uint256"}],"name":"IncorrectRequestFinalization","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualWithdrawalVaultBalance","type":"uint256"}],"name":"IncorrectWithdrawalsVaultBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxItemsCount","type":"uint256"},{"internalType":"uint256","name":"receivedItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataItemsCountExceeded","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[],"name":"TooLowTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"itemIndex","type":"uint256"},{"internalType":"uint256","name":"nodeOpsCount","type":"uint256"}],"name":"TooManyNodeOpsPerExtraDataItem","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"AnnualBalanceIncreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"}],"name":"ChurnValidatorsPerDayLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"MaxAccountingExtraDataListItemsCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"}],"name":"MaxPositiveTokenRebaseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"MaxValidatorExitRequestsPerReportSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"OneOffCLBalanceDecreaseBPLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"}],"name":"RequestTimestampMarginSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"}],"name":"ShareRateDeviationBPLimitSet","type":"event"},{"inputs":[],"name":"ALL_LIMITS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_extraDataListItemsCount","type":"uint256"}],"name":"checkAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeElapsed","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_preCLValidators","type":"uint256"},{"internalType":"uint256","name":"_postCLValidators","type":"uint256"}],"name":"checkAccountingOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitRequestsCount","type":"uint256"}],"name":"checkExitBusOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_exitedValidatorsCount","type":"uint256"}],"name":"checkExitedValidatorsRatePerDay","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemIndex","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorsCount","type":"uint256"}],"name":"checkNodeOperatorsPerExtraDataItemCount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_postTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_postTotalShares","type":"uint256"},{"internalType":"uint256","name":"_etherLockedOnWithdrawalQueue","type":"uint256"},{"internalType":"uint256","name":"_sharesBurntFromWithdrawalQueue","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"checkSimulatedShareRate","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lastFinalizableRequestId","type":"uint256"},{"internalType":"uint256","name":"_reportTimestamp","type":"uint256"}],"name":"checkWithdrawalQueueOracleReport","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLidoLocator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxPositiveTokenRebase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleReportLimits","outputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_annualBalanceIncreaseBPLimit","type":"uint256"}],"name":"setAnnualBalanceIncreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_churnValidatorsPerDayLimit","type":"uint256"}],"name":"setChurnValidatorsPerDayLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxAccountingExtraDataListItemsCount","type":"uint256"}],"name":"setMaxAccountingExtraDataListItemsCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxValidatorExitRequestsPerReport","type":"uint256"}],"name":"setMaxExitRequestsPerOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPositiveTokenRebase","type":"uint256"}],"name":"setMaxPositiveTokenRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_oneOffCLBalanceDecreaseBPLimit","type":"uint256"}],"name":"setOneOffCLBalanceDecreaseBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"churnValidatorsPerDayLimit","type":"uint256"},{"internalType":"uint256","name":"oneOffCLBalanceDecreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"annualBalanceIncreaseBPLimit","type":"uint256"},{"internalType":"uint256","name":"shareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"}],"internalType":"struct LimitsList","name":"_limitsList","type":"tuple"}],"name":"setOracleReportLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestTimestampMargin","type":"uint256"}],"name":"setRequestTimestampMargin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shareRateDeviationBPLimit","type":"uint256"}],"name":"setShareRateDeviationBPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preTotalPooledEther","type":"uint256"},{"internalType":"uint256","name":"_preTotalShares","type":"uint256"},{"internalType":"uint256","name":"_preCLBalance","type":"uint256"},{"internalType":"uint256","name":"_postCLBalance","type":"uint256"},{"internalType":"uint256","name":"_withdrawalVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_elRewardsVaultBalance","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"sharesToBurnLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/test/0.8.9/oracle-report-sanity-checker.test.js b/test/0.8.9/oracle-report-sanity-checker.test.js index 09b6948c5..aec6dab7d 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -223,8 +223,10 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa describe('checkSimulatedShareRate', async () => { const correctSimulatedShareRate = { - noWithdrawalsPostTotalPooledEther: ETH(10), - noWithdrawalsPostTotalShares: ETH(5), + postTotalPooledEther: ETH(9), + postTotalShares: ETH(4), + etherLockedOnWithdrawalQueue: ETH(1), + sharesBurntFromWithdrawalQueue: ETH(1), simulatedShareRate: (BigInt(2) * 10n ** 27n).toString() } @@ -249,7 +251,8 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa oracleReportSanityChecker.checkSimulatedShareRate( ...Object.values({ ...correctSimulatedShareRate, - noWithdrawalsPostTotalPooledEther: ETH(0) + etherLockedOnWithdrawalQueue: ETH(0), + postTotalPooledEther: ETH(0) }) ), `IncorrectFinalizationShareRate(${deviation.toString()})` From 1bcc13a7b7d940c7734583cb476cf58a6e10ebb7 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 13 Feb 2023 22:33:11 +0400 Subject: [PATCH 75/82] Consistent naming with ERC721 for baseURI --- contracts/0.8.9/WithdrawalRequestNFT.sol | 18 +++++++++--------- lib/abi/WithdrawalRequestNFT.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/0.8.9/WithdrawalRequestNFT.sol b/contracts/0.8.9/WithdrawalRequestNFT.sol index 9f9bcc33d..d834d1b66 100644 --- a/contracts/0.8.9/WithdrawalRequestNFT.sol +++ b/contracts/0.8.9/WithdrawalRequestNFT.sol @@ -35,7 +35,7 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { // @notion simple wrapper for base URI string // Solidity does not allow to store string in UnstructuredStorage - struct BaseUri { + struct BaseURI { string value; } @@ -92,20 +92,20 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { function tokenURI(uint256 _requestId) public view virtual override returns (string memory) { if (!_existsAndNotClaimed(_requestId)) revert InvalidRequestId(_requestId); - string memory baseURI = _getBaseUri().value; + string memory baseURI = _getBaseURI().value; return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, _requestId.toString())) : ""; } /// @notice Base URI for computing {tokenURI}. If set, the resulting URI for each /// token will be the concatenation of the `baseURI` and the `_requestId`. - function getBaseUri() external view returns (string memory) { - return _getBaseUri().value; + function getBaseURI() external view returns (string memory) { + return _getBaseURI().value; } /// @notice Sets the Base URI for computing {tokenURI} - function setBaseUri(string calldata _baseUri) external onlyRole(SET_BASE_URI_ROLE) { - _getBaseUri().value = _baseUri; - emit BaseURISet(_baseUri); + function setBaseURI(string calldata _baseURI) external onlyRole(SET_BASE_URI_ROLE) { + _getBaseURI().value = _baseURI; + emit BaseURISet(_baseURI); } /// @dev See {IERC721-balanceOf}. @@ -305,10 +305,10 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { return OPERATOR_APPROVALS_POSITION.storageMapAddressMapAddressBool(); } - function _getBaseUri() internal pure returns (BaseUri storage baseUri) { + function _getBaseURI() internal pure returns (BaseURI storage baseURI) { bytes32 position = BASE_URI_POSITION; assembly { - baseUri.slot := position + baseURI.slot := position } } } diff --git a/lib/abi/WithdrawalRequestNFT.json b/lib/abi/WithdrawalRequestNFT.json index 37424a812..0ccb54190 100644 --- a/lib/abi/WithdrawalRequestNFT.json +++ b/lib/abi/WithdrawalRequestNFT.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_wstETH","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"InvalidOwnerAddress","type":"error"},{"inputs":[],"name":"InvalidReportTimestamp","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"InvalidRequestId","type":"error"},{"inputs":[{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"endId","type":"uint256"}],"name":"InvalidRequestIdRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"_expectedLength","type":"uint256"},{"internalType":"uint256","name":"_actualLength","type":"uint256"}],"name":"LengthsMismatch","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NotEnoughEther","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"NotOwner","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApproved","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApprovedForAll","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooLarge","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooSmall","type":"error"},{"inputs":[],"name":"RequestIdsNotSorted","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"realOwner","type":"address"}],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferFromZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"TransferToNonIERC721Receiver","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"Unimplemented","type":"error"},{"inputs":[],"name":"Uninitialized","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURISet","type":"event"},{"anonymous":false,"inputs":[],"name":"BunkerModeDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"BunkerModeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_admin","type":"address"},{"indexed":false,"internalType":"address","name":"_pauser","type":"address"},{"indexed":false,"internalType":"address","name":"_resumer","type":"address"},{"indexed":false,"internalType":"address","name":"_finalizer","type":"address"},{"indexed":false,"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"to","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfETHLocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sharesToBurn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"WithdrawalBatchFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfETH","type":"uint256"}],"name":"WithdrawalClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"requestor","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"WithdrawalRequested","type":"event"},{"inputs":[],"name":"BUNKER_MODE_DISABLED_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUNKER_MODE_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_BASE_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WSTETH","outputs":[{"internalType":"contract IWstETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_hint","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256","name":"hint","type":"uint256"}],"internalType":"struct WithdrawalQueue.ClaimWithdrawalInput[]","name":"_claimWithdrawalInputs","type":"tuple[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalizationBatch","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"findCheckpointHint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"findCheckpointHintUnbounded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256","name":"_firstIndex","type":"uint256"},{"internalType":"uint256","name":"_lastIndex","type":"uint256"}],"name":"findCheckpointHints","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"findCheckpointHintsUnbounded","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"}],"name":"findLastFinalizableRequestId","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByBudget","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByTimestamp","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseUri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastCheckpointIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastFinalizedRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLockedEtherAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getWithdrawalRequestStatus","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalRequestStatuses","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus[]","name":"statuses","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_pauser","type":"address"},{"internalType":"address","name":"_resumer","type":"address"},{"internalType":"address","name":"_finalizer","type":"address"},{"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBunkerModeActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawals","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawalsWstETH","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWstETHWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseUri","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unfinalizedRequestNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unfinalizedStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"updateBunkerMode","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_wstETH","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"InvalidOwnerAddress","type":"error"},{"inputs":[],"name":"InvalidReportTimestamp","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"InvalidRequestId","type":"error"},{"inputs":[{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"endId","type":"uint256"}],"name":"InvalidRequestIdRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"_expectedLength","type":"uint256"},{"internalType":"uint256","name":"_actualLength","type":"uint256"}],"name":"LengthsMismatch","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"NotEnoughEther","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"NotOwner","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApproved","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotOwnerOrApprovedForAll","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooLarge","type":"error"},{"inputs":[{"internalType":"uint256","name":"_amountOfStETH","type":"uint256"}],"name":"RequestAmountTooSmall","type":"error"},{"inputs":[],"name":"RequestIdsNotSorted","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"realOwner","type":"address"}],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferFromZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"TransferToNonIERC721Receiver","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"Unimplemented","type":"error"},{"inputs":[],"name":"Uninitialized","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURISet","type":"event"},{"anonymous":false,"inputs":[],"name":"BunkerModeDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"BunkerModeEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"}],"name":"ContractVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_admin","type":"address"},{"indexed":false,"internalType":"address","name":"_pauser","type":"address"},{"indexed":false,"internalType":"address","name":"_resumer","type":"address"},{"indexed":false,"internalType":"address","name":"_finalizer","type":"address"},{"indexed":false,"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Resumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"to","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfETHLocked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sharesToBurn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"WithdrawalBatchFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfETH","type":"uint256"}],"name":"WithdrawalClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"requestor","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOfShares","type":"uint256"}],"name":"WithdrawalRequested","type":"event"},{"inputs":[],"name":"BUNKER_MODE_DISABLED_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUNKER_MODE_REPORT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_STETH_WITHDRAWAL_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_INFINITELY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESUME_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_BASE_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WSTETH","outputs":[{"internalType":"contract IWstETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_hint","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256","name":"hint","type":"uint256"}],"internalType":"struct WithdrawalQueue.ClaimWithdrawalInput[]","name":"_claimWithdrawalInputs","type":"tuple[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalizationBatch","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"findCheckpointHint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"findCheckpointHintUnbounded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256","name":"_firstIndex","type":"uint256"},{"internalType":"uint256","name":"_lastIndex","type":"uint256"}],"name":"findCheckpointHints","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"findCheckpointHintsUnbounded","outputs":[{"internalType":"uint256[]","name":"hintIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"}],"name":"findLastFinalizableRequestId","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethBudget","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByBudget","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_startId","type":"uint256"},{"internalType":"uint256","name":"_endId","type":"uint256"}],"name":"findLastFinalizableRequestIdByTimestamp","outputs":[{"internalType":"uint256","name":"finalizableRequestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastCheckpointIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastFinalizedRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLockedEtherAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getWithdrawalRequestStatus","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalRequestStatuses","outputs":[{"components":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"internalType":"struct WithdrawalQueueBase.WithdrawalRequestStatus[]","name":"statuses","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_pauser","type":"address"},{"internalType":"address","name":"_resumer","type":"address"},{"internalType":"address","name":"_finalizer","type":"address"},{"internalType":"address","name":"_bunkerReporter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBunkerModeActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawals","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"requestWithdrawalsWstETH","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct WithdrawalQueue.PermitInput","name":"_permit","type":"tuple"}],"name":"requestWithdrawalsWstETHWithPermit","outputs":[{"internalType":"uint256[]","name":"requestIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unfinalizedRequestNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unfinalizedStETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"}],"name":"updateBunkerMode","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file From 8327ee2628c203dff16c4f6842c6c626df6ff1f1 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 21:41:06 +0300 Subject: [PATCH 76/82] fix: zero check --- contracts/0.4.24/Lido.sol | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 9fbd43f67..66472f011 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -824,7 +824,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 _withdrawalsToWithdraw, uint256 _elRewardsToWithdraw, uint256 _lastFinalizableRequestId, - uint256 _sharesToBurnFromWithdrawalQueue, uint256 _etherToLockOnWithdrawalQueue ) internal { // withdraw execution layer rewards and put them to the buffer @@ -839,10 +838,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { // finalize withdrawals (send ether, assign shares for burning) if (_etherToLockOnWithdrawalQueue > 0) { - IBurner burner = IBurner(_contracts.burner); IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(_contracts.withdrawalQueue); - - burner.requestBurnShares(address(withdrawalQueue), _sharesToBurnFromWithdrawalQueue); withdrawalQueue.finalize.value(_etherToLockOnWithdrawalQueue)(_lastFinalizableRequestId); } @@ -1259,7 +1255,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { withdrawals, elRewards, _reportedData.lastFinalizableRequestId, - reportContext.sharesToBurnFromWithdrawalQueue, reportContext.etherToLockOnWithdrawalQueue ); @@ -1285,6 +1280,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Burn excess shares (withdrawn stETH at least) uint256 burntWithdrawalQueueShares = _burnSharesLimited( IBurner(_contracts.burner), + _contracts.withdrawalQueue, reportContext.sharesToBurnFromWithdrawalQueue, reportContext.sharesToBurnLimit ); @@ -1377,9 +1373,14 @@ contract Lido is Versioned, StETHPermit, AragonApp { */ function _burnSharesLimited( IBurner _burner, + address _withdrawalQueue, uint256 _withdrawalsSharesToBurn, uint256 _sharesToBurnLimit ) internal returns (uint256 burntWithdrawalsShares) { + if (_withdrawalsSharesToBurn > 0) { + _burner.requestBurnShares(_withdrawalQueue, _withdrawalsSharesToBurn); + } + if (_sharesToBurnLimit > 0) { uint256 sharesCommittedToBurnNow = _burner.commitSharesToBurn(_sharesToBurnLimit); From 0ee669098d9b1fcbe4398797d37768d8000e9cea Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 21:44:40 +0300 Subject: [PATCH 77/82] chore: naming --- contracts/0.4.24/Lido.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 66472f011..0ccd120a9 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -1374,11 +1374,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { function _burnSharesLimited( IBurner _burner, address _withdrawalQueue, - uint256 _withdrawalsSharesToBurn, + uint256 _sharesToBurnFromWithdrawalQueue, uint256 _sharesToBurnLimit ) internal returns (uint256 burntWithdrawalsShares) { - if (_withdrawalsSharesToBurn > 0) { - _burner.requestBurnShares(_withdrawalQueue, _withdrawalsSharesToBurn); + if (_sharesToBurnFromWithdrawalQueue > 0) { + _burner.requestBurnShares(_withdrawalQueue, _sharesToBurnFromWithdrawalQueue); } if (_sharesToBurnLimit > 0) { @@ -1393,8 +1393,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 postponedSharesToBurn = coverShares.add(nonCoverShares); burntWithdrawalsShares = - postponedSharesToBurn < _withdrawalsSharesToBurn ? - _withdrawalsSharesToBurn - postponedSharesToBurn : 0; + postponedSharesToBurn < _sharesToBurnFromWithdrawalQueue ? + _sharesToBurnFromWithdrawalQueue - postponedSharesToBurn : 0; } /** From ea14cc554cf7008061c05cf387bae061376c9232 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 21:23:34 +0300 Subject: [PATCH 78/82] fix: redundant `_whenNotStopped()` in stETH --- contracts/0.4.24/StETH.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index 3e23f8e33..2b78eb9aa 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -229,8 +229,6 @@ contract StETH is IERC20, Pausable { * @dev The `_amount` argument is the amount of tokens, not shares. */ function transferFrom(address _sender, address _recipient, uint256 _amount) external returns (bool) { - _whenNotStopped(); - uint256 currentAllowance = allowances[_sender][msg.sender]; require(currentAllowance >= _amount, "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); @@ -488,7 +486,6 @@ contract StETH is IERC20, Pausable { */ function _burnShares(address _account, uint256 _sharesAmount) internal returns (uint256 newTotalShares) { require(_account != address(0), "BURN_FROM_THE_ZERO_ADDRESS"); - _whenNotStopped(); uint256 accountShares = shares[_account]; require(_sharesAmount <= accountShares, "BURN_AMOUNT_EXCEEDS_BALANCE"); From ce08fb2dd96f3d152b408ec6fc7d6405db3e3eb2 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Feb 2023 21:51:29 +0300 Subject: [PATCH 79/82] chore: comment about sanity check --- contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index cc1dc2fc5..ce741481b 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -454,6 +454,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { ) external view { LimitsList memory limitsList = _limits.unpack(); + // Pretending that withdrawals were not processed + // virtually return locked ether back to postTotalPooledEther + // virtually return burnt shares back to postTotalShares _checkFinalizationShareRate( limitsList, _postTotalPooledEther + _etherLockedOnWithdrawalQueue, From 5d1c5511940e46428531c21811bb51f2b5490e31 Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Mon, 13 Feb 2023 21:58:07 +0300 Subject: [PATCH 80/82] remove selfdestruct from tests completely --- .../0.8.9/test_helpers/ETHForwarderMock.sol | 10 ----- .../0.8.9/test_helpers/RewardEmulatorMock.sol | 44 ------------------- test/0.4.24/lido.test.js | 40 ++++++++++------- .../oracle/base-oracle-set-consensus.test.js | 2 +- test/helpers/utils.js | 2 +- ...execution_layer_rewards_after_the_merge.js | 24 +++++----- 6 files changed, 37 insertions(+), 85 deletions(-) delete mode 100644 contracts/0.8.9/test_helpers/ETHForwarderMock.sol delete mode 100644 contracts/0.8.9/test_helpers/RewardEmulatorMock.sol diff --git a/contracts/0.8.9/test_helpers/ETHForwarderMock.sol b/contracts/0.8.9/test_helpers/ETHForwarderMock.sol deleted file mode 100644 index 88f9aba52..000000000 --- a/contracts/0.8.9/test_helpers/ETHForwarderMock.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Lido -//SPDX-License-Identifier: GPL-3.0 - -pragma solidity 0.8.9; - -contract ETHForwarderMock { - constructor(address payable _target) payable { - selfdestruct(_target); - } -} diff --git a/contracts/0.8.9/test_helpers/RewardEmulatorMock.sol b/contracts/0.8.9/test_helpers/RewardEmulatorMock.sol deleted file mode 100644 index 0f489de62..000000000 --- a/contracts/0.8.9/test_helpers/RewardEmulatorMock.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Lido -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.9; - -import "./ETHForwarderMock.sol"; - -contract RewardEmulatorMock { - address payable private target; - - event Rewarded(address target, uint256 amount); - - constructor(address _target) { - target = payable(_target); - } - - function reward() public payable { - require(target != address(0), "no target"); - uint256 amount = msg.value; - uint256 balance = target.balance + amount; - bytes memory bytecode = abi.encodePacked(type(ETHForwarderMock).creationCode, abi.encode(target)); - address addr; - - /* - NOTE: How to call create2 - create2(v, p, n, s) - create new contract with code at memory p to p + n - and send v wei - and return the new address - where new address = first 20 bytes of keccak256(0xff + address(this) + s + keccak256(mem[p…(p+n))) - s = big-endian 256-bit value - */ - assembly { - addr := create2( - amount, // wei sent with current call - // Actual code starts after skipping the first 32 bytes - add(bytecode, 0x20), - mload(bytecode), // Load the size of code contained in the first 32 bytes - 0 // Salt - ) - } - require(target.balance == balance, "incorrect balance"); - emit Rewarded(target, msg.value); - } -} diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index c8df0b85c..1ddb37ef9 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -1,7 +1,7 @@ const hre = require('hardhat') const { hash } = require('eth-ens-namehash') -const { artifacts } = require('hardhat') +const { artifacts, ethers } = require('hardhat') const { getInstalledApp } = require('@aragon/contract-helpers-test/src/aragon-os') const { assertBn, assertEvent } = require('@aragon/contract-helpers-test/src/asserts') @@ -10,7 +10,19 @@ const { assertRevert } = require('../helpers/assertThrow') const { ZERO_ADDRESS, bn } = require('@aragon/contract-helpers-test') const { formatEther } = require('ethers/lib/utils') const { waitBlocks, EvmSnapshot } = require('../helpers/blockchain') -const { getEthBalance, formatStEth, formatBN, hexConcat, pad, ETH, tokens, div15, assertNoEvent, StETH } = require('../helpers/utils') +const { + getEthBalance, + formatStEth, + formatBN, + hexConcat, + pad, + ETH, + tokens, + div15, + assertNoEvent, + StETH, + setBalance +} = require('../helpers/utils') const { assert } = require('../helpers/assert') const nodeOperators = require('../helpers/node-operators') const { deployProtocol } = require('../helpers/protocol') @@ -24,7 +36,6 @@ const { newApp } = require('../helpers/dao') const ERC20Mock = artifacts.require('ERC20Mock.sol') const AragonVaultMock = artifacts.require('AragonVaultMock.sol') const ERC20WrongTransferMock = artifacts.require('ERC20WrongTransferMock.sol') -const RewardEmulatorMock = artifacts.require('RewardEmulatorMock.sol') const WithdrawalVault = artifacts.require('WithdrawalVault.sol') const LidoMock = artifacts.require('LidoMock') @@ -215,11 +226,8 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody }) context('EL Rewards', async () => { - let rewarder - - beforeEach('set up rewarder and limits', async () => { - rewarder = await RewardEmulatorMock.new(elRewardsVault.address) + beforeEach('set up limits', async () => { //TODO(DZhon): revive //const maxPositiveTokenRebase = bn(1).mul(bn(10).pow(bn(8))) // 10% //await assertRevert(app.setMaxPositiveTokenRebase(maxPositiveTokenRebase), 'APP_AUTH_FAILED') @@ -275,9 +283,10 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await setupNodeOperatorsForELRewardsVaultTests(user2, ETH(depositAmount)) await pushReport(1, ETH(depositAmount)) + await setBalance(elRewardsVault.address, ETH(elRewards)) - await rewarder.reward({ from: user1, value: ETH(elRewards) }) await pushReport(1, ETH(depositAmount + beaconRewards)) + console.log((await app.getTotalPooledEther()).toString()) assertBn(await app.getTotalPooledEther(), ETH(depositAmount + elRewards + beaconRewards)) assertBn(await app.totalSupply(), ETH(depositAmount + elRewards + beaconRewards)) @@ -293,7 +302,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await setupNodeOperatorsForELRewardsVaultTests(user2, ETH(depositAmount)) await pushReport(1, ETH(depositAmount)) - await rewarder.reward({ from: user1, value: ETH(elRewards) }) + await setBalance(elRewardsVault.address, ETH(elRewards)) await pushReport(1, ETH(depositAmount + beaconRewards)) assertBn(await app.getTotalPooledEther(), ETH(depositAmount + elRewards + beaconRewards)) @@ -309,7 +318,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await setupNodeOperatorsForELRewardsVaultTests(user2, ETH(depositAmount)) await pushReport(1, ETH(depositAmount)) - await rewarder.reward({ from: user1, value: ETH(elRewards) }) + await setBalance(elRewardsVault.address, ETH(elRewards)) await pushReport(1, ETH(depositAmount + beaconRewards)) assertBn(await app.getTotalPooledEther(), ETH(depositAmount + elRewards + beaconRewards)) @@ -366,7 +375,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await setupNodeOperatorsForELRewardsVaultTests(user2, ETH(depositAmount)) await pushReport(1, ETH(depositAmount)) - await rewarder.reward({ from: user1, value: ETH(elRewards) }) + await setBalance(elRewardsVault.address, ETH(elRewards)) await pushReport(1, ETH(depositAmount + beaconRewards)) assertBn(await app.getTotalPooledEther(), ETH(depositAmount + elRewards + beaconRewards)) @@ -383,7 +392,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await setupNodeOperatorsForELRewardsVaultTests(user2, ETH(depositAmount)) await pushReport(1, ETH(depositAmount)) - await rewarder.reward({ from: user1, value: ETH(elRewards) }) + await setBalance(elRewardsVault.address, ETH(elRewards)) await pushReport(1, ETH(depositAmount + beaconRewards)) assertBn(await app.getTotalPooledEther(), ETH(depositAmount + elRewards + beaconRewards)) @@ -400,7 +409,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await setupNodeOperatorsForELRewardsVaultTests(user2, ETH(depositAmount)) await pushReport(1, ETH(depositAmount)) - await rewarder.reward({ from: user1, value: ETH(elRewards) }) + await setBalance(elRewardsVault.address, ETH(elRewards)) await pushReport(1, ETH(depositAmount + beaconRewards)) const {totalFee} = await app.getFee() @@ -438,7 +447,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody it('event work', async () => { await ethers.provider.send('hardhat_impersonateAccount', [elRewardsVault.address]) - await ethers.provider.send('hardhat_setBalance', [elRewardsVault.address, web3.utils.numberToHex(ETH(100))]) + await setBalance(elRewardsVault.address, ETH(100)) const receipt = await app.receiveELRewards({ from: elRewardsVault.address, value: ETH(2) }) @@ -460,7 +469,8 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await ethers.provider.send('hardhat_impersonateAccount', [stakingRouter.address]) // add some amount to the sender - await ethers.provider.send('hardhat_setBalance', [stakingRouter.address, web3.utils.numberToHex(ETH(100))]) + + await setBalance(stakingRouter.address, ETH(100)) const receipt = await app.receiveStakingRouterDepositRemainder({ from: stakingRouter.address, value: ETH(2) }) diff --git a/test/0.8.9/oracle/base-oracle-set-consensus.test.js b/test/0.8.9/oracle/base-oracle-set-consensus.test.js index 67edc3f00..e771a7fe5 100644 --- a/test/0.8.9/oracle/base-oracle-set-consensus.test.js +++ b/test/0.8.9/oracle/base-oracle-set-consensus.test.js @@ -95,7 +95,7 @@ contract('BaseOracle', ([admin, member, notMember]) => { ) await newConsensusContract.setCurrentFrame(10, initialRefSlot + 1, initialRefSlot + SLOTS_PER_FRAME) const tx = await baseOracle.setConsensusContract(newConsensusContract.address) - assert.emits(tx, 'ConsensusContractSet', { addr: newConsensusContract.address, prevAddr: consensus.address }) + assert.emits(tx, 'ConsensusHashContractSet', { addr: newConsensusContract.address, prevAddr: consensus.address }) const addressAtStorage = await baseOracle.getConsensusContract() assert.addressEqual(addressAtStorage, newConsensusContract.address) }) diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 7f0a59c75..27bcd91b9 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -142,7 +142,7 @@ const toNum = (x) => Array.isArray(x) ? x.map(toNum) : +x const toStr = (x) => Array.isArray(x) ? x.map(toStr) : `${x}` const setBalance = async (address, value) => { - await hre.network.provider.send('hardhat_setBalance', [address, '0x' + toBN(value).toString(16)]) + await hre.network.provider.send('hardhat_setBalance', [address, web3.utils.numberToHex(value)]) } module.exports = { diff --git a/test/scenario/execution_layer_rewards_after_the_merge.js b/test/scenario/execution_layer_rewards_after_the_merge.js index b77c70409..6634af78e 100644 --- a/test/scenario/execution_layer_rewards_after_the_merge.js +++ b/test/scenario/execution_layer_rewards_after_the_merge.js @@ -4,14 +4,13 @@ const { assertBn } = require('@aragon/contract-helpers-test/src/asserts') const { getEventArgument } = require('@aragon/contract-helpers-test') const { gwei, ZERO_HASH } = require('../helpers/utils') -const { pad, toBN, ETH, tokens } = require('../helpers/utils') +const { pad, toBN, ETH, tokens, setBalance } = require('../helpers/utils') const { DSMAttestMessage, DSMPauseMessage } = require('../helpers/signatures') const { waitBlocks } = require('../helpers/blockchain') const { deployProtocol } = require('../helpers/protocol') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') const { SLOTS_PER_FRAME } = require('../helpers/constants') -const RewardEmulatorMock = artifacts.require('RewardEmulatorMock.sol') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') const TOTAL_BASIS_POINTS = 10**4 @@ -54,7 +53,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { let oracleMock, depositContractMock let treasuryAddr, guardians, stakingRouter let depositSecurityModule, depositRoot - let rewarder, elRewardsVault, voting + let elRewardsVault, voting // Total fee is 1% const totalFeePoints = 0.01 * TOTAL_BASIS_POINTS @@ -128,9 +127,6 @@ contract.skip('Lido: merge acceptance', (addresses) => { depositRoot = await depositContractMock.get_deposit_root() - rewarder = await RewardEmulatorMock.new(elRewardsVault.address) - - assertBn(await web3.eth.getBalance(rewarder.address), ETH(0), 'rewarder balance') assertBn(await web3.eth.getBalance(elRewardsVault.address), ETH(0), 'Execution layer rewards vault balance') await stakingRouter.setWithdrawalCredentials(withdrawalCredentials, { from: voting }) @@ -352,7 +348,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('collect 9 ETH execution layer rewards to the vault', async () => { - await rewarder.reward({ from: userELRewards, value: ETH(9) }) + await setBalance(elRewardsVault.address, ETH(9)) assertBn(await web3.eth.getBalance(elRewardsVault.address), ETH(9), 'Execution layer rewards vault balance') }) @@ -441,14 +437,14 @@ contract.skip('Lido: merge acceptance', (addresses) => { it('collect another 7 ETH execution layer rewards to the vault', async () => { const balanceBefore = await web3.eth.getBalance(elRewardsVault.address) - await rewarder.reward({ from: userELRewards, value: ETH(2) }) + await setBalance(elRewardsVault.address, ETH(2)) assertBn( await web3.eth.getBalance(elRewardsVault.address), ETH(2) + balanceBefore, 'Execution layer rewards vault balance' ) - await rewarder.reward({ from: userELRewards, value: ETH(5) }) + await setBalance(elRewardsVault.address, ETH(5)) assertBn( await web3.eth.getBalance(elRewardsVault.address), ETH(7) + balanceBefore, @@ -520,7 +516,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('collect another 5 ETH execution layer rewards to the vault', async () => { - await rewarder.reward({ from: userELRewards, value: ETH(5) }) + await setBalance(elRewardsVault.address, ETH(5)) assertBn(await web3.eth.getBalance(elRewardsVault.address), ETH(5), 'Execution layer rewards vault balance') }) @@ -581,7 +577,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('collect another 3 ETH execution layer rewards to the vault', async () => { - await rewarder.reward({ from: userELRewards, value: ETH(3) }) + await setBalance(elRewardsVault.address, ETH(3)) assertBn(await web3.eth.getBalance(elRewardsVault.address), ETH(3), 'Execution layer rewards vault balance') }) @@ -640,7 +636,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('collect another 2 ETH execution layer rewards to the vault', async () => { - await rewarder.reward({ from: userELRewards, value: ETH(2) }) + await setBalance(elRewardsVault.address, ETH(2)) assertBn(await web3.eth.getBalance(elRewardsVault.address), ETH(2), 'Execution layer rewards vault balance') }) @@ -699,7 +695,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('collect another 3 ETH execution layer rewards to the vault', async () => { - await rewarder.reward({ from: userELRewards, value: ETH(3) }) + await setBalance(elRewardsVault.address, ETH(3)) assertBn(await web3.eth.getBalance(elRewardsVault.address), ETH(3), 'Execution layer vault balance') }) @@ -776,7 +772,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { } const elRewards = ETH(0.1) - await rewarder.reward({ from: userELRewards, value: elRewards }) + await setBalance(elRewardsVault.address, elRewards) assertBn(await web3.eth.getBalance(elRewardsVault.address), elRewards, 'Execution layer rewards vault balance') let frame = 7 From 2d16655075474d4f614faa928448d0aebfd7a3aa Mon Sep 17 00:00:00 2001 From: KRogLA Date: Mon, 13 Feb 2023 20:01:20 +0100 Subject: [PATCH 81/82] refactor: transfer method --- contracts/0.8.9/WithdrawalRequestNFT.sol | 25 ++++++------------------ 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/contracts/0.8.9/WithdrawalRequestNFT.sol b/contracts/0.8.9/WithdrawalRequestNFT.sol index d834d1b66..d7a2255bd 100644 --- a/contracts/0.8.9/WithdrawalRequestNFT.sol +++ b/contracts/0.8.9/WithdrawalRequestNFT.sol @@ -161,15 +161,11 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { if (!_checkOnERC721Received(_from, _to, _requestId, _data)) { revert TransferToNonIERC721Receiver(_to); } - - emit Transfer(_from, _to, _requestId); } /// @dev See {IERC721-transferFrom}. function transferFrom(address _from, address _to, uint256 _requestId) external override { _transfer(_from, _to, _requestId); - - emit Transfer(_from, _to, _requestId); } /// @dev Transfers `_requestId` from `_from` to `_to`. @@ -181,6 +177,9 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { /// - `_requestId` request must not be claimed and be owned by `_from`. /// - `msg.sender` should be approved, or approved for all, or owner function _transfer(address _from, address _to, uint256 _requestId) internal { + + + if (_to == address(0)) revert TransferToZeroAddress(); if (_requestId == 0 || _requestId > getLastRequestId()) revert InvalidRequestId(_requestId); @@ -188,13 +187,15 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { if (request.claimed) revert RequestAlreadyClaimed(_requestId); if (_from != request.owner) revert TransferFromIncorrectOwner(_from, request.owner); - if (!_isApprovedOrOwner(msg.sender, _requestId, request)) revert NotOwnerOrApproved(msg.sender); + if (!(msg.sender == _from || isApprovedForAll(_from, msg.sender) || _getTokenApprovals()[_requestId] == msg.sender)) revert NotOwnerOrApproved(msg.sender); delete _getTokenApprovals()[_requestId]; request.owner = payable(_to); _getRequestsByOwner()[_to].add(_requestId); _getRequestsByOwner()[_from].remove(_requestId); + + _emitTransfer(_from, _to, _requestId); } /// @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. @@ -227,20 +228,6 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { } } - /// @dev Returns whether `_spender` is allowed to manage `_requestId`. - /// - /// Requirements: - /// - /// - `_requestId` must exist (not checking). - function _isApprovedOrOwner(address _spender, uint256 _requestId, WithdrawalRequest memory request) - internal - view - returns (bool) - { - address owner = request.owner; - return (_spender == owner || isApprovedForAll(owner, _spender) || _getTokenApprovals()[_requestId] == _spender); - } - // // Internal getters and setters // From 313113ee12a316d668fb38dce66c2596161185a3 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Mon, 13 Feb 2023 20:12:22 +0100 Subject: [PATCH 82/82] refactor: transfer optimize --- contracts/0.8.9/WithdrawalRequestNFT.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/0.8.9/WithdrawalRequestNFT.sol b/contracts/0.8.9/WithdrawalRequestNFT.sol index d7a2255bd..b0d7930f1 100644 --- a/contracts/0.8.9/WithdrawalRequestNFT.sol +++ b/contracts/0.8.9/WithdrawalRequestNFT.sol @@ -177,9 +177,6 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { /// - `_requestId` request must not be claimed and be owned by `_from`. /// - `msg.sender` should be approved, or approved for all, or owner function _transfer(address _from, address _to, uint256 _requestId) internal { - - - if (_to == address(0)) revert TransferToZeroAddress(); if (_requestId == 0 || _requestId > getLastRequestId()) revert InvalidRequestId(_requestId); @@ -187,7 +184,9 @@ contract WithdrawalRequestNFT is IERC721Metadata, WithdrawalQueue { if (request.claimed) revert RequestAlreadyClaimed(_requestId); if (_from != request.owner) revert TransferFromIncorrectOwner(_from, request.owner); - if (!(msg.sender == _from || isApprovedForAll(_from, msg.sender) || _getTokenApprovals()[_requestId] == msg.sender)) revert NotOwnerOrApproved(msg.sender); + // here and below we are sure that `_from` is the owner of the request + address msgSender = msg.sender; + if (!(_from == msgSender || isApprovedForAll(_from, msgSender) || _getTokenApprovals()[_requestId] == msgSender)) revert NotOwnerOrApproved(msgSender); delete _getTokenApprovals()[_requestId]; request.owner = payable(_to);