From 2220024ac27b486f02a818856285080ddf14c35d Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Tue, 21 Feb 2023 19:27:17 +0700 Subject: [PATCH 001/236] test: withdrawal queue reusable deploy as standalone module --- test/0.8.9/withdrawal-queue-deploy.test.js | 42 ++++++++++++++++++++++ test/0.8.9/withdrawal-queue.test.js | 23 ++++++------ test/0.8.9/withdrawal-request-nft.test.js | 35 +++++++++--------- 3 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 test/0.8.9/withdrawal-queue-deploy.test.js diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js new file mode 100644 index 000000000..29a3df7f6 --- /dev/null +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -0,0 +1,42 @@ +const { artifacts } = require('hardhat') + +const { ETH } = require('../helpers/utils') +const withdrawals = require('../helpers/withdrawals') + +const StETHMock = artifacts.require('StETHMock.sol') +const WstETH = artifacts.require('WstETHMock.sol') + +async function deployWithdrawalQueue({ + stethOwner, + queueOwner, + queuePauser, + queueResumer, + queueFinalizer, + queueBunkerReporter, + queueName, + symbol +}) { + const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) + const wsteth = await WstETH.new(steth.address, { from: stethOwner }) + + const { queue: withdrawalQueue } = await withdrawals.deploy(queueOwner, wsteth.address, queueName, symbol) + + await withdrawalQueue.initialize( + queueOwner, + queuePauser, + queueResumer, + queueFinalizer || steth.address, + queueBunkerReporter || steth.address + ) + await withdrawalQueue.resume({ from: queueOwner }) + + return { + steth, + wsteth, + withdrawalQueue + } +} + +module.exports = { + deployWithdrawalQueue +} diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 12ea31350..f0b68ae0f 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -1,16 +1,14 @@ const hre = require('hardhat') -const { artifacts, contract, ethers } = require('hardhat') +const { contract, ethers } = require('hardhat') const { bn, getEventArgument, ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const { ETH, StETH, shareRate, shares, setBalance } = require('../helpers/utils') const { assert } = require('../helpers/assert') -const withdrawals = require('../helpers/withdrawals') const { signPermit, makeDomainSeparator } = require('../0.6.12/helpers/permit_helpers') const { MAX_UINT256, ACCOUNTS_AND_KEYS } = require('../0.6.12/helpers/constants') const { impersonate, EvmSnapshot } = require('../helpers/blockchain') -const StETHMock = artifacts.require('StETHMock.sol') -const WstETH = artifacts.require('WstETHMock.sol') +const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { let withdrawalQueue, steth, wsteth @@ -18,13 +16,16 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { const snapshot = new EvmSnapshot(ethers.provider) before('Deploy', async () => { - steth = await StETHMock.new({ value: ETH(1) }) - wsteth = await WstETH.new(steth.address) - - withdrawalQueue = (await withdrawals.deploy(daoAgent, wsteth.address)).queue + const deployed = await deployWithdrawalQueue({ + stethOwner: owner, + queueOwner: daoAgent, + queuePauser: daoAgent, + queueResumer: daoAgent + }) - await withdrawalQueue.initialize(daoAgent, daoAgent, daoAgent, steth.address, steth.address) - await withdrawalQueue.resume({ from: daoAgent }) + steth = deployed.steth + wsteth = deployed.wsteth + withdrawalQueue = deployed.withdrawalQueue await steth.setTotalPooledEther(ETH(600)) await setBalance(steth.address, ETH(600)) @@ -32,7 +33,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) await impersonate(ethers.provider, steth.address) - await snapshot.make(); + await snapshot.make() }) afterEach(async () => { diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index d38a37440..496f60ab4 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -2,12 +2,11 @@ const hre = require('hardhat') const { assert } = require('../helpers/assert') const { EvmSnapshot } = require('../helpers/blockchain') const { shares, ETH, shareRate, setBalance } = require('../helpers/utils') -const withdrawals = require('../helpers/withdrawals') -const StETH = hre.artifacts.require('StETHMock') -const WstETH = hre.artifacts.require('WstETHMock') const ERC721ReceiverMock = hre.artifacts.require('ERC721ReceiverMock') +const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') + hre.contract( 'WithdrawalNFT', ([deployer, stEthHolder, wstEthHolder, nftHolderStETH, nftHolderWstETH, recipient, stranger]) => { @@ -16,20 +15,24 @@ hre.contract( const snapshot = new EvmSnapshot(hre.ethers.provider) before(async () => { - stETH = await StETH.new({ value: ETH(1), from: deployer }) - await setBalance(stETH.address, ETH(100)) - - wstETH = await WstETH.new(stETH.address, { from: deployer }) erc721ReceiverMock = await ERC721ReceiverMock.new({ from: deployer }) - withdrawalQueueERC721 = (await withdrawals.deploy(deployer, wstETH.address, "Lido TEST Request", "unstEsT")).queue - await withdrawalQueueERC721.initialize( - deployer, // owner - deployer, // pauser - deployer, // resumer - deployer, // finalizer - deployer - ) - await withdrawalQueueERC721.resume({ from: deployer }) + + const deployed = await deployWithdrawalQueue({ + stethOwner: deployer, + queueOwner: deployer, + queuePauser: deployer, + queueResumer: deployer, + queueFinalizer: deployer, + queueBunkerReporter: deployer, + queueName: 'Lido TEST Request', + symbol: 'unstEsT' + }) + + stETH = deployed.steth + wstETH = deployed.wsteth + withdrawalQueueERC721 = deployed.withdrawalQueue + + await setBalance(stETH.address, ETH(100)) await stETH.setTotalPooledEther(ETH(101)) await stETH.mintShares(stEthHolder, shares(50)) From d00f15b4b09c3882320e8561921f5fa919df413a Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 21 Feb 2023 21:46:48 +0700 Subject: [PATCH 002/236] feat: add testcases missing from coverage --- test/0.8.9/withdrawal-queue-deploy.test.js | 4 +- test/0.8.9/withdrawal-queue.test.js | 270 ++++++++++++++------- 2 files changed, 186 insertions(+), 88 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 29a3df7f6..05a517580 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -13,8 +13,8 @@ async function deployWithdrawalQueue({ queueResumer, queueFinalizer, queueBunkerReporter, - queueName, - symbol + queueName = 'Unsteth nft', + symbol = 'UNSTETH' }) { const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) const wsteth = await WstETH.new(steth.address, { from: stethOwner }) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index f0b68ae0f..806d7c36a 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -53,9 +53,9 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { context('Request', async () => { it('One can request a withdrawal', async () => { const receipt = await withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }) - const requestId = getEventArgument(receipt, "WithdrawalRequested", "requestId") + const requestId = getEventArgument(receipt, 'WithdrawalRequested', 'requestId') - assert.emits(receipt, "WithdrawalRequested", { + assert.emits(receipt, 'WithdrawalRequested', { requestId: 1, requestor: user.toLowerCase(), owner: owner.toLowerCase(), @@ -87,8 +87,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { const amount = min.sub(bn(1)) - await assert.reverts(withdrawalQueue.requestWithdrawals([amount], owner, { from: user }), - `RequestAmountTooSmall(${amount})`) + await assert.reverts( + withdrawalQueue.requestWithdrawals([amount], owner, { from: user }), + `RequestAmountTooSmall(${amount})` + ) }) it('One can request MIN', async () => { @@ -96,14 +98,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { const shares = await steth.getSharesByPooledEth(min) const receipt = await withdrawalQueue.requestWithdrawals([min], owner, { from: user }) - const requestId = getEventArgument(receipt, "WithdrawalRequested", "requestId") + const requestId = getEventArgument(receipt, 'WithdrawalRequested', 'requestId') - assert.emits(receipt, "WithdrawalRequested", { + assert.emits(receipt, 'WithdrawalRequested', { requestId: 1, requestor: user.toLowerCase(), owner: owner.toLowerCase(), amountOfStETH: min, - amountOfShares: shares, + amountOfShares: shares }) assert.equals(await withdrawalQueue.getLastRequestId(), requestId) @@ -124,8 +126,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await steth.setTotalPooledEther(amount) await steth.approve(withdrawalQueue.address, amount, { from: user }) - await assert.reverts(withdrawalQueue.requestWithdrawals([amount], owner, { from: user }), - `RequestAmountTooLarge(${amount})`) + await assert.reverts( + withdrawalQueue.requestWithdrawals([amount], owner, { from: user }), + `RequestAmountTooLarge(${amount})` + ) }) it('One can request MAX', async () => { @@ -134,9 +138,9 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await steth.approve(withdrawalQueue.address, max, { from: user }) const receipt = await withdrawalQueue.requestWithdrawals([max], owner, { from: user }) - const requestId = getEventArgument(receipt, "WithdrawalRequested", "requestId") + const requestId = getEventArgument(receipt, 'WithdrawalRequested', 'requestId') - assert.emits(receipt, "WithdrawalRequested", { + assert.emits(receipt, 'WithdrawalRequested', { requestId: 1, requestor: user.toLowerCase(), owner: owner.toLowerCase(), @@ -157,15 +161,19 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) it('One cant request more than they have', async () => { - await assert.reverts(withdrawalQueue.requestWithdrawals([StETH(400)], owner, { from: user }), - "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE") + await assert.reverts( + withdrawalQueue.requestWithdrawals([StETH(400)], owner, { from: user }), + 'TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE' + ) }) it('One cant request more than allowed', async () => { await steth.approve(withdrawalQueue.address, StETH(200), { from: user }) - await assert.reverts(withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), - "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE") + await assert.reverts( + withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), + 'TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE' + ) }) }) @@ -184,19 +192,27 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) it('Finalizer can finalize a request', async () => { - await assert.reverts(withdrawalQueue.finalize(1, { from: stranger }), - `AccessControl: account ${stranger.toLowerCase()} is missing role ${await withdrawalQueue.FINALIZE_ROLE()}`) + await assert.reverts( + withdrawalQueue.finalize(1, { from: stranger }), + `AccessControl: account ${stranger.toLowerCase()} is missing role ${await withdrawalQueue.FINALIZE_ROLE()}` + ) await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), amount) - assert.equals(await withdrawalQueue.getLockedEtherAmount(), await ethers.provider.getBalance(withdrawalQueue.address)) + assert.equals( + await withdrawalQueue.getLockedEtherAmount(), + await ethers.provider.getBalance(withdrawalQueue.address) + ) }) it('One can finalize requests with discount', async () => { await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(150) }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(150)) - assert.equals(await withdrawalQueue.getLockedEtherAmount(), await ethers.provider.getBalance(withdrawalQueue.address)) + assert.equals( + await withdrawalQueue.getLockedEtherAmount(), + await ethers.provider.getBalance(withdrawalQueue.address) + ) }) it('Same discounts is squashed into one', async () => { @@ -226,7 +242,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 2) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(600)) - assert.equals(await withdrawalQueue.getLockedEtherAmount(), await ethers.provider.getBalance(withdrawalQueue.address)) + assert.equals( + await withdrawalQueue.getLockedEtherAmount(), + await ethers.provider.getBalance(withdrawalQueue.address) + ) }) it('One can finalize part of the queue', async () => { @@ -241,14 +260,20 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 1) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(300)) - assert.equals(await withdrawalQueue.getLockedEtherAmount(), await ethers.provider.getBalance(withdrawalQueue.address)) + assert.equals( + await withdrawalQueue.getLockedEtherAmount(), + await ethers.provider.getBalance(withdrawalQueue.address) + ) await withdrawalQueue.finalize(2, { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 2) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(600)) - assert.equals(await withdrawalQueue.getLockedEtherAmount(), await ethers.provider.getBalance(withdrawalQueue.address)) + assert.equals( + await withdrawalQueue.getLockedEtherAmount(), + await ethers.provider.getBalance(withdrawalQueue.address) + ) }) }) @@ -287,6 +312,12 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') + + await withdrawalQueue.requestWithdrawals([ETH(1), [ETH(1)]], owner, { from: user }) + await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(0.99) }) + await withdrawalQueue.finalize(3, { from: steth.address, value: ETH(0.98) }) + + await assert.reverts(withdrawalQueue.getClaimableEther([3], [1]), 'InvalidHint(1)') }) }) @@ -317,8 +348,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) it('One cant claim not finalized or not existed request', async () => { - await assert.reverts(withdrawalQueue.claimWithdrawals([1], [1], { from: owner }), `RequestNotFoundOrNotFinalized(1)`) - await assert.reverts(withdrawalQueue.claimWithdrawals([2], [1], { from: owner }), `RequestNotFoundOrNotFinalized(2)`) + await assert.reverts( + withdrawalQueue.claimWithdrawals([1], [1], { from: owner }), + `RequestNotFoundOrNotFinalized(1)` + ) + await assert.reverts( + withdrawalQueue.claimWithdrawals([2], [1], { from: owner }), + `RequestNotFoundOrNotFinalized(2)` + ) }) it('Cant claim request with a wrong hint', async () => { @@ -337,8 +374,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(1, { from: owner }) - await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: owner }), - 'RequestAlreadyClaimed(1)') + await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: owner }), 'RequestAlreadyClaimed(1)') }) it('Discounted withdrawals produce less eth', async () => { @@ -380,17 +416,17 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) context('findLastFinalizableRequestIdByTimestamp()', async () => { - const numOfRequests = 10; + const numOfRequests = 10 beforeEach(async () => { - for (i = 1; i <= numOfRequests; i++) { + for (let i = 1; i <= numOfRequests; i++) { await withdrawalQueue.requestWithdrawals([ETH(20)], owner, { from: user }) } }) it('works', async () => { for (let i = 1; i <= numOfRequests; i++) { - const timestamp = ((await withdrawalQueue.getWithdrawalStatus([i]))[0]).timestamp; + const timestamp = (await withdrawalQueue.getWithdrawalStatus([i]))[0].timestamp assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 1, 10), i) } }) @@ -400,32 +436,42 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) it('return zero if no unfinalized request found', async () => { - const timestamp = ((await withdrawalQueue.getWithdrawalStatus([1]))[0]).timestamp; + const timestamp = (await withdrawalQueue.getWithdrawalStatus([1]))[0].timestamp await withdrawalQueue.finalize(1, { from: steth.address, value: ETH[10] }) assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 2, 10), 0) }) it('checks params', async () => { - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByTimestamp(0, 0, 10), - "ZeroTimestamp()") + await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByTimestamp(0, 0, 10), 'ZeroTimestamp()') - const timestamp = ((await withdrawalQueue.getWithdrawalStatus([2]))[0]).timestamp; + const timestamp = (await withdrawalQueue.getWithdrawalStatus([2]))[0].timestamp - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 0, 10), - "InvalidRequestIdRange(0, 10)") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 0, 10), + 'InvalidRequestIdRange(0, 10)' + ) - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 0, 11), - "InvalidRequestIdRange(0, 11)") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 0, 11), + 'InvalidRequestIdRange(0, 11)' + ) await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(20) }) - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 1, 10), - "InvalidRequestIdRange(1, 10)") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 1, 10), + 'InvalidRequestIdRange(1, 10)' + ) + + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 2, 1000), + 'InvalidRequestIdRange(2, 1000)' + ) }) }) context('findLastFinalizableRequestIdByBudget()', async () => { - const numOfRequests = 10; + const numOfRequests = 10 beforeEach(async () => { for (let i = 1; i <= numOfRequests; i++) { @@ -438,7 +484,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { const rate = shareRate(150) for (let i = 1; i <= numOfRequests; i++) { - const budget = ETH(i * 10 + 5); + const budget = ETH(i * 10 + 5) assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByBudget(budget, rate, 1, 10), i) } }) @@ -453,26 +499,45 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) it('checks params', async () => { - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(0), shareRate(300), 0, 10), - "ZeroAmountOfETH()") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(0), shareRate(300), 0, 10), + 'ZeroAmountOfETH()' + ) - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(0), 0, 10), - "ZeroShareRate()") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(0), 0, 10), + 'ZeroShareRate()' + ) - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 0, 10), - "InvalidRequestIdRange(0, 10)") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 0, 10), + 'InvalidRequestIdRange(0, 10)' + ) - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 0, 11), - "InvalidRequestIdRange(0, 11)") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 0, 11), + 'InvalidRequestIdRange(0, 11)' + ) await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(20) }) - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 1, 10), - "InvalidRequestIdRange(1, 10)") + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 1, 10), + 'InvalidRequestIdRange(1, 10)' + ) + + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 1, 10), + 'InvalidRequestIdRange(1, 10)' + ) + await assert.reverts( + withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 2, 1000), + 'InvalidRequestIdRange(2, 1000)' + ) }) }) context('findLastFinalizableRequestId()', async () => { - const numOfRequests = 10; + const numOfRequests = 10 beforeEach(async () => { for (let i = 1; i <= numOfRequests + 1; i++) { @@ -482,8 +547,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { it('works', async () => { for (let i = 1; i <= numOfRequests; i++) { - const budget = ETH(i * 10 + 5); - const timestamp = (await withdrawalQueue.getWithdrawalStatus([i]))[0].timestamp; + const budget = ETH(i * 10 + 5) + const timestamp = (await withdrawalQueue.getWithdrawalStatus([i]))[0].timestamp assert.equals(await withdrawalQueue.findLastFinalizableRequestId(budget, shareRate(150), timestamp), i) } }) @@ -491,26 +556,25 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { it('returns zero if no unfinalized requests', async () => { await withdrawalQueue.finalize(10, { from: steth.address, value: ETH[10] }) - const timestamp = (await withdrawalQueue.getWithdrawalStatus([10]))[0].timestamp; + const timestamp = (await withdrawalQueue.getWithdrawalStatus([10]))[0].timestamp assert.equals(await withdrawalQueue.findLastFinalizableRequestId(ETH(100), shareRate(100), timestamp), 0) }) it('checks params', async () => { - await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(0), shareRate(300), 1), - "ZeroAmountOfETH()") + await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(0), shareRate(300), 1), 'ZeroAmountOfETH()') - await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(1), shareRate(0), 1), - "ZeroShareRate()") + await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(1), shareRate(0), 1), 'ZeroShareRate()') - await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(1), shareRate(1), 0), - "ZeroTimestamp()") + await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(1), shareRate(1), 0), 'ZeroTimestamp()') }) }) context('findCheckpointsHint()', async () => { - const numOfRequests = 10; + const numOfRequests = 10 const requests = Array(numOfRequests).fill(ETH(20)) - const discountedPrices = Array(numOfRequests).fill().map((_, i) => ETH(i)); + const discountedPrices = Array(numOfRequests) + .fill() + .map((_, i) => ETH(i)) beforeEach(async () => { await withdrawalQueue.requestWithdrawals(requests, owner, { from: user }) @@ -518,24 +582,28 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await withdrawalQueue.finalize(i, { from: steth.address, value: discountedPrices[i] }) } assert.equals(await withdrawalQueue.getLastCheckpointIndex(), numOfRequests) - assert.equals(await withdrawalQueue.findCheckpointHintsUnbounded([await withdrawalQueue.getLastFinalizedRequestId()]), - await withdrawalQueue.getLastCheckpointIndex()) + assert.equals( + await withdrawalQueue.findCheckpointHintsUnbounded([await withdrawalQueue.getLastFinalizedRequestId()]), + await withdrawalQueue.getLastCheckpointIndex() + ) }) it('works unbounded', async () => { - assert.equals(await withdrawalQueue.findCheckpointHintsUnbounded([10]), await withdrawalQueue.getLastCheckpointIndex()) + assert.equals( + await withdrawalQueue.findCheckpointHintsUnbounded([10]), + await withdrawalQueue.getLastCheckpointIndex() + ) }) it('reverts if request is not finalized', async () => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) - await assert.reverts(withdrawalQueue.findCheckpointHints([11], 1, 10), "RequestNotFoundOrNotFinalized(11)") - await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([11]), "RequestNotFoundOrNotFinalized(11)") - + await assert.reverts(withdrawalQueue.findCheckpointHints([11], 1, 10), 'RequestNotFoundOrNotFinalized(11)') + await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([11]), 'RequestNotFoundOrNotFinalized(11)') }) it('reverts if there is no such a request', async () => { - await assert.reverts(withdrawalQueue.findCheckpointHints([12], 1, 10), "RequestNotFoundOrNotFinalized(12)") - await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([12]), "RequestNotFoundOrNotFinalized(12)") + await assert.reverts(withdrawalQueue.findCheckpointHints([12], 1, 10), 'RequestNotFoundOrNotFinalized(12)') + await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([12]), 'RequestNotFoundOrNotFinalized(12)') }) it('range search (found)', async () => { @@ -553,7 +621,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) it('sequential search', async () => { - for ([idToFind, searchLength] of [[1, 3], [1, 10], [10, 2], [10, 3], [8, 2], [9, 3]]) { + for ([idToFind, searchLength] of [ + [1, 3], + [1, 10], + [10, 2], + [10, 3], + [8, 2], + [9, 3] + ]) { assert.equals(await sequentialSearch(idToFind, searchLength), idToFind) } }) @@ -568,7 +643,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { if (foundIndex != 0) return foundIndex } } - }) context('findCheckpointHints()', () => { @@ -586,6 +660,19 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { assert.equal(hints.length, 0) }) + it('returns not found when indexes have negative overlap', async () => { + const batch = await withdrawalQueue.finalizationBatch(requestId, shareRate(300)) + await withdrawalQueue.finalize(requestId, { from: steth.address, value: batch.ethToLock }) + const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() + const hints = await withdrawalQueue.findCheckpointHints( + [requestId], + +lastCheckpointIndex + 1, + lastCheckpointIndex + ) + assert.equal(hints.length, 1) + assert.equals(hints[0], 0) + }) + it('returns hints array with one item for list from single request id', async () => { const batch = await withdrawalQueue.finalizationBatch(requestId, shareRate(300)) await withdrawalQueue.finalize(requestId, { from: steth.address, value: batch.ethToLock }) @@ -799,26 +886,30 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { const senderWithdrawalsBefore = await withdrawalQueue.getWithdrawalRequests(user) const ownerWithdrawalsBefore = await withdrawalQueue.getWithdrawalRequests(owner) - assert.isTrue(senderWithdrawalsBefore.map(v => v.toNumber()).includes(requestId)) - assert.isFalse(ownerWithdrawalsBefore.map(v => v.toNumber()).includes(requestId)) + assert.isTrue(senderWithdrawalsBefore.map((v) => v.toNumber()).includes(requestId)) + assert.isFalse(ownerWithdrawalsBefore.map((v) => v.toNumber()).includes(requestId)) await withdrawalQueue.transferFrom(user, owner, requestId, { from: user }) const senderWithdrawalAfter = await withdrawalQueue.getWithdrawalRequests(user) const ownerWithdrawalsAfter = await withdrawalQueue.getWithdrawalRequests(owner) - assert.isFalse(senderWithdrawalAfter.map(v => v.toNumber()).includes(requestId)) - assert.isTrue(ownerWithdrawalsAfter.map(v => v.toNumber()).includes(requestId)) + assert.isFalse(senderWithdrawalAfter.map((v) => v.toNumber()).includes(requestId)) + assert.isTrue(ownerWithdrawalsAfter.map((v) => v.toNumber()).includes(requestId)) }) it("One can't change someone else's request", async () => { - await assert.reverts(withdrawalQueue.transferFrom(user, owner, requestId, { from: stranger }), - `NotOwnerOrApproved("${stranger}")`) + await assert.reverts( + withdrawalQueue.transferFrom(user, owner, requestId, { from: stranger }), + `NotOwnerOrApproved("${stranger}")` + ) }) it("One can't pass zero owner", async () => { - await assert.reverts(withdrawalQueue.transferFrom(user, ZERO_ADDRESS, requestId, { from: user }), - 'TransferToZeroAddress()') + await assert.reverts( + withdrawalQueue.transferFrom(user, ZERO_ADDRESS, requestId, { from: user }), + 'TransferToZeroAddress()' + ) }) it("One can't pass zero requestId", async () => { @@ -829,13 +920,18 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await withdrawalQueue.finalize(requestId, { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(requestId, { from: user }) - await assert.reverts(withdrawalQueue.transferFrom(user, owner, requestId, { from: user }), `RequestAlreadyClaimed(1)`) + await assert.reverts( + withdrawalQueue.transferFrom(user, owner, requestId, { from: user }), + `RequestAlreadyClaimed(1)` + ) }) it("Changing owner doesn't work with wrong request id", async () => { const wrongRequestId = requestId + 1 - await assert.reverts(withdrawalQueue.transferFrom(user, owner, wrongRequestId, { from: user }), - `InvalidRequestId(${wrongRequestId})`) + await assert.reverts( + withdrawalQueue.transferFrom(user, owner, wrongRequestId, { from: user }), + `InvalidRequestId(${wrongRequestId})` + ) }) }) @@ -849,12 +945,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { for (let i = 0; i < firstRequestCount; i++) { await withdrawalQueue.requestWithdrawals([ETH(1 / secondRequestCount)], user, { from: user }) } - const firstGasUsed = (await withdrawalQueue.changeRecipient(firstRequestCount - 1, owner, { from: user })).receipt.gasUsed + const firstGasUsed = (await withdrawalQueue.changeRecipient(firstRequestCount - 1, owner, { from: user })).receipt + .gasUsed for (let i = firstRequestCount; i < secondRequestCount; i++) { await withdrawalQueue.requestWithdrawals([ETH(1 / secondRequestCount)], user, { from: user }) } - const secondGasUsed = (await withdrawalQueue.changeRecipient(secondRequestCount / 2, owner, { from: user })).receipt.gasUsed + const secondGasUsed = (await withdrawalQueue.changeRecipient(secondRequestCount / 2, owner, { from: user })) + .receipt.gasUsed assert.isTrue(firstGasUsed >= secondGasUsed) }) From 4dd5df83eea7190f966979c8722b377d3bf050d1 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 22 Feb 2023 14:32:23 +0700 Subject: [PATCH 003/236] feat: steth permit withdrawal test --- test/0.8.9/withdrawal-queue-deploy.test.js | 5 ++- test/0.8.9/withdrawal-queue.test.js | 41 +++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 05a517580..19417ebe9 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -3,8 +3,9 @@ const { artifacts } = require('hardhat') const { ETH } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') -const StETHMock = artifacts.require('StETHMock.sol') +const StETHMock = artifacts.require('StETHPermitMock.sol') const WstETH = artifacts.require('WstETHMock.sol') +const EIP712StETH = artifacts.require('EIP712StETH') async function deployWithdrawalQueue({ stethOwner, @@ -18,6 +19,8 @@ async function deployWithdrawalQueue({ }) { const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) const wsteth = await WstETH.new(steth.address, { from: stethOwner }) + const eip712StETH = await EIP712StETH.new(steth.address, { from: stethOwner }) + await steth.initializeEIP712StETH(eip712StETH.address) const { queue: withdrawalQueue } = await withdrawals.deploy(queueOwner, wsteth.address, queueName, symbol) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 8ddea3900..66ca92869 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -314,7 +314,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') - await withdrawalQueue.requestWithdrawals([ETH(1), [ETH(1)]], owner, { from: user }) + await withdrawalQueue.requestWithdrawals([ETH(1), ETH(1)], owner, { from: user }) await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(0.99) }) await withdrawalQueue.finalize(3, { from: steth.address, value: ETH(0.98) }) @@ -877,6 +877,45 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { }) }) + context('requestWithdrawalsWithPermit()', () => { + const [alice] = ACCOUNTS_AND_KEYS + it('works correctly with non empty payload', async () => { + await steth.mintShares(alice.address, shares(100)) + const withdrawalRequestsCount = 5 + const requests = Array(withdrawalRequestsCount).fill(ETH(10)) + + const amount = bn(ETH(10)).mul(bn(withdrawalRequestsCount)) + const chainId = await wsteth.getChainId() + const deadline = MAX_UINT256 + await impersonate(hre.ethers.provider, alice.address) + const dom = await steth.DOMAIN_SEPARATOR() + console.log(dom) + const domainSeparator = makeDomainSeparator('Liquid staked Ether 2.0', '2', chainId, steth.address) + const { v, r, s } = signPermit( + alice.address, + withdrawalQueue.address, + amount, // amount + 0, // nonce + deadline, + domainSeparator, + alice.key + ) + const permission = [ + amount, + deadline, // deadline + v, + r, + s + ] + + const aliceBalancesBefore = await steth.balanceOf(alice.address) + const lastRequestIdBefore = await withdrawalQueue.getLastRequestId() + await withdrawalQueue.requestWithdrawalsWithPermit(requests, owner, permission, { from: alice.address }) + assert.equals(await withdrawalQueue.getLastRequestId(), lastRequestIdBefore.add(bn(requests.length))) + const aliceBalancesAfter = await steth.balanceOf(alice.address) + assert.equals(aliceBalancesAfter, aliceBalancesBefore.sub(bn(ETH(10)).mul(bn(withdrawalRequestsCount)))) + }) + }) context('Transfer request', async () => { const amount = ETH(300) let requestId From dc60516dd9c7cb7e9edb2b51d3ee5071630009c9 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 22 Feb 2023 14:40:19 +0700 Subject: [PATCH 004/236] fix: steth permit test --- test/0.8.9/withdrawal-queue.test.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 66ca92869..ddb06e3cb 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -880,17 +880,15 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { context('requestWithdrawalsWithPermit()', () => { const [alice] = ACCOUNTS_AND_KEYS it('works correctly with non empty payload', async () => { + await web3.eth.sendTransaction({ to: alice.address, from: user, value: ETH(1) }) await steth.mintShares(alice.address, shares(100)) const withdrawalRequestsCount = 5 const requests = Array(withdrawalRequestsCount).fill(ETH(10)) const amount = bn(ETH(10)).mul(bn(withdrawalRequestsCount)) - const chainId = await wsteth.getChainId() const deadline = MAX_UINT256 await impersonate(hre.ethers.provider, alice.address) - const dom = await steth.DOMAIN_SEPARATOR() - console.log(dom) - const domainSeparator = makeDomainSeparator('Liquid staked Ether 2.0', '2', chainId, steth.address) + const domainSeparator = await steth.DOMAIN_SEPARATOR() const { v, r, s } = signPermit( alice.address, withdrawalQueue.address, From 5d7ba4eaee3448fbc7b880faa7ceca6a6a3c8bd0 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 22 Feb 2023 16:31:10 +0700 Subject: [PATCH 005/236] feat: pause/resume tests --- test/0.8.9/withdrawal-queue.test.js | 41 +++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index ddb06e3cb..7e2b27099 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -1,6 +1,6 @@ const hre = require('hardhat') const { contract, ethers } = require('hardhat') -const { bn, getEventArgument, ZERO_ADDRESS } = require('@aragon/contract-helpers-test') +const { bn, getEventArgument, ZERO_ADDRESS, ZERO_BYTES32 } = require('@aragon/contract-helpers-test') const { ETH, StETH, shareRate, shares, setBalance } = require('../helpers/utils') const { assert } = require('../helpers/assert') @@ -10,7 +10,7 @@ const { impersonate, EvmSnapshot } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') -contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { +contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer]) => { let withdrawalQueue, steth, wsteth const snapshot = new EvmSnapshot(ethers.provider) @@ -51,6 +51,43 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user]) => { assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(0)) }) + context('Pause/Resume', async () => { + it('only correct roles can alter pause state', async () => { + const [PAUSE_ROLE, RESUME_ROLE] = await Promise.all([withdrawalQueue.PAUSE_ROLE(), withdrawalQueue.RESUME_ROLE()]) + await withdrawalQueue.grantRole(PAUSE_ROLE, pauser, { from: daoAgent }) + await withdrawalQueue.grantRole(RESUME_ROLE, resumer, { from: daoAgent }) + await withdrawalQueue.pause(100000000, { from: pauser }) + assert(await withdrawalQueue.isPaused()) + await withdrawalQueue.resume({ from: resumer }) + assert(!(await withdrawalQueue.isPaused())) + await assert.revertsOZAccessControl(withdrawalQueue.pause(100000000, { from: resumer }), resumer, 'PAUSE_ROLE') + await assert.revertsOZAccessControl(withdrawalQueue.pause(100000000, { from: stranger }), stranger, 'PAUSE_ROLE') + await withdrawalQueue.pause(100000000, { from: pauser }) + await assert.revertsOZAccessControl(withdrawalQueue.resume({ from: pauser }), pauser, 'RESUME_ROLE') + await assert.revertsOZAccessControl(withdrawalQueue.resume({ from: stranger }), stranger, 'RESUME_ROLE') + }) + + it('withdraw/finalize only allowed when at resumed state', async () => { + await withdrawalQueue.pause(100000000, { from: daoAgent }) + assert(await withdrawalQueue.isPaused()) + await assert.reverts(withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }), 'ResumedExpected()') + await assert.reverts( + withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], owner, { from: user }), + 'ResumedExpected()' + ) + const stubPermit = [0, 0, ZERO_BYTES32, ZERO_BYTES32, ZERO_BYTES32] + await assert.reverts( + withdrawalQueue.requestWithdrawalsWithPermit([ETH(1)], owner, stubPermit, { from: user }), + 'ResumedExpected()' + ) + await assert.reverts( + withdrawalQueue.requestWithdrawalsWstETHWithPermit([ETH(1)], owner, stubPermit, { from: user }), + 'ResumedExpected()' + ) + await assert.reverts(withdrawalQueue.finalize(1, { from: owner }), 'ResumedExpected()') + }) + }) + context('Request', async () => { it('One can request a withdrawal', async () => { const receipt = await withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }) From 7fd2a64c6ba1e8ee95ab4b5153632e37b73aa9fc Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Wed, 22 Feb 2023 16:52:00 +0700 Subject: [PATCH 006/236] test: WithdrawalQueue initialization --- test/0.8.9/withdrawal-queue-deploy.test.js | 110 +++++++++++++++++++-- test/0.8.9/withdrawal-queue.test.js | 2 +- test/0.8.9/withdrawal-request-nft.test.js | 2 +- 3 files changed, 105 insertions(+), 9 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 19417ebe9..78f118792 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -1,7 +1,9 @@ -const { artifacts } = require('hardhat') +const { artifacts, contract } = require('hardhat') +const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const { ETH } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') +const { assert } = require('../helpers/assert') const StETHMock = artifacts.require('StETHPermitMock.sol') const WstETH = artifacts.require('WstETHMock.sol') @@ -9,31 +11,36 @@ const EIP712StETH = artifacts.require('EIP712StETH') async function deployWithdrawalQueue({ stethOwner, - queueOwner, + queueAdmin, queuePauser, queueResumer, queueFinalizer, queueBunkerReporter, queueName = 'Unsteth nft', - symbol = 'UNSTETH' + symbol = 'UNSTETH', + doResume = true }) { const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) const wsteth = await WstETH.new(steth.address, { from: stethOwner }) const eip712StETH = await EIP712StETH.new(steth.address, { from: stethOwner }) await steth.initializeEIP712StETH(eip712StETH.address) - const { queue: withdrawalQueue } = await withdrawals.deploy(queueOwner, wsteth.address, queueName, symbol) + const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, wsteth.address, queueName, symbol) - await withdrawalQueue.initialize( - queueOwner, + const initTx = await withdrawalQueue.initialize( + queueAdmin, queuePauser, queueResumer, queueFinalizer || steth.address, queueBunkerReporter || steth.address ) - await withdrawalQueue.resume({ from: queueOwner }) + + if (doResume) { + await withdrawalQueue.resume({ from: queueResumer }) + } return { + initTx, steth, wsteth, withdrawalQueue @@ -43,3 +50,92 @@ async function deployWithdrawalQueue({ module.exports = { deployWithdrawalQueue } + +contract( + 'WithdrawalQueue', + ([stethOwner, queueAdmin, queuePauser, queueResumer, queueFinalizer, queueBunkerReporter]) => { + context('initialization', () => { + it('is paused right after deploy', async () => { + const { withdrawalQueue } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer, + doResume: false + }) + assert.equals(await withdrawalQueue.isPaused(), true) + }) + + it('emits InitializedV1', async () => { + const { initTx } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer, + queueFinalizer, + queueBunkerReporter + }) + await assert.emits(initTx, 'InitializedV1', { + _admin: queueAdmin, + _pauser: queuePauser, + _resumer: queueResumer, + _finalizer: queueFinalizer, + _bunkerReporter: queueBunkerReporter + }) + }) + + context('no roles for zero addresses', () => { + it('check if pauser is zero', async () => { + const { withdrawalQueue } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser: ZERO_ADDRESS, + queueResumer + }) + const role = await withdrawalQueue.PAUSE_ROLE() + const memberCount = await withdrawalQueue.getRoleMemberCount(role) + assert.equals(memberCount, 0) + }) + + it('check if pauser is zero', async () => { + const { withdrawalQueue } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer: ZERO_ADDRESS, + doResume: false + }) + const role = await withdrawalQueue.RESUME_ROLE() + const memberCount = await withdrawalQueue.getRoleMemberCount(role) + assert.equals(memberCount, 0) + }) + + it('check if finalizer is zero', async () => { + const { withdrawalQueue } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer, + queueFinalizer: ZERO_ADDRESS + }) + const role = await withdrawalQueue.FINALIZE_ROLE() + const memberCount = await withdrawalQueue.getRoleMemberCount(role) + assert.equals(memberCount, 0) + }) + + it('check if bunker reporter is zero', async () => { + const { withdrawalQueue } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer, + queueBunkerReporter: ZERO_ADDRESS + }) + const role = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() + const memberCount = await withdrawalQueue.getRoleMemberCount(role) + assert.equals(memberCount, 0) + }) + }) + }) + } +) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 7e2b27099..ed7469351 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -18,7 +18,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer]) before('Deploy', async () => { const deployed = await deployWithdrawalQueue({ stethOwner: owner, - queueOwner: daoAgent, + queueAdmin: daoAgent, queuePauser: daoAgent, queueResumer: daoAgent }) diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index 496f60ab4..849503aa8 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -19,7 +19,7 @@ hre.contract( const deployed = await deployWithdrawalQueue({ stethOwner: deployer, - queueOwner: deployer, + queueAdmin: deployer, queuePauser: deployer, queueResumer: deployer, queueFinalizer: deployer, From 0b78bd6d5092c708b0f2f14612db37158de5eec3 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Wed, 22 Feb 2023 17:06:12 +0700 Subject: [PATCH 007/236] test: WithdrawalQueue initialization check that bunker mode is disabled by default --- test/0.8.9/withdrawal-queue-deploy.test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 78f118792..0a4938922 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -66,6 +66,21 @@ contract( assert.equals(await withdrawalQueue.isPaused(), true) }) + it('bunker mode is disabled by default', async () => { + const { withdrawalQueue } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer + }) + const BUNKER_MODE_DISABLED_TIMESTAMP = await withdrawalQueue.BUNKER_MODE_DISABLED_TIMESTAMP() + const isBunkerModeActive = await withdrawalQueue.isBunkerModeActive() + const bunkerModeSinceTimestamp = await withdrawalQueue.bunkerModeSinceTimestamp() + + assert.equals(isBunkerModeActive, false) + assert.equals(+bunkerModeSinceTimestamp, +BUNKER_MODE_DISABLED_TIMESTAMP) + }) + it('emits InitializedV1', async () => { const { initTx } = await deployWithdrawalQueue({ stethOwner, From b7666039bfb4dffbcdb486469fa0b9eb246a746b Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 22 Feb 2023 19:01:01 +0700 Subject: [PATCH 008/236] feat: bunker mode tests --- test/0.8.9/withdrawal-queue.test.js | 46 +++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 7e2b27099..1f372f456 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -6,11 +6,11 @@ const { ETH, StETH, shareRate, shares, setBalance } = require('../helpers/utils' const { assert } = require('../helpers/assert') const { signPermit, makeDomainSeparator } = require('../0.6.12/helpers/permit_helpers') const { MAX_UINT256, ACCOUNTS_AND_KEYS } = require('../0.6.12/helpers/constants') -const { impersonate, EvmSnapshot } = require('../helpers/blockchain') +const { impersonate, EvmSnapshot, getCurrentBlockTimestamp } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') -contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer]) => { +contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, bunkerReporter]) => { let withdrawalQueue, steth, wsteth const snapshot = new EvmSnapshot(ethers.provider) @@ -88,6 +88,47 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer]) }) }) + context('BunkerMode', async () => { + it('init config', async () => { + assert(!(await withdrawalQueue.isBunkerModeActive())) + assert.equals(ethers.constants.MaxUint256, await withdrawalQueue.bunkerModeSinceTimestamp()) + }) + + it('access control', async () => { + assert(!(await withdrawalQueue.isBunkerModeActive())) + const BUNKER_MODE_REPORT_ROLE = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() + await withdrawalQueue.grantRole(BUNKER_MODE_REPORT_ROLE, bunkerReporter, { from: daoAgent }) + await assert.revertsOZAccessControl( + withdrawalQueue.updateBunkerMode(true, 0, { from: stranger }), + stranger, + 'BUNKER_MODE_REPORT_ROLE' + ) + await withdrawalQueue.updateBunkerMode(true, 0, { from: bunkerReporter }) + }) + + it('state and events', async () => { + assert(!(await withdrawalQueue.isBunkerModeActive())) + assert.equals(ethers.constants.MaxUint256, await withdrawalQueue.bunkerModeSinceTimestamp()) + let timestamp = await getCurrentBlockTimestamp() + await assert.reverts( + withdrawalQueue.updateBunkerMode(true, +timestamp + 1000000, { from: steth.address }), + 'InvalidReportTimestamp()' + ) + // enable + timestamp = await getCurrentBlockTimestamp() + const tx1 = await withdrawalQueue.updateBunkerMode(true, timestamp, { from: steth.address }) + assert.emits(tx1, 'BunkerModeEnabled', { _sinceTimestamp: timestamp }) + assert(await withdrawalQueue.isBunkerModeActive()) + assert.equals(timestamp, await withdrawalQueue.bunkerModeSinceTimestamp()) + // disable + timestamp = await getCurrentBlockTimestamp() + const tx2 = await withdrawalQueue.updateBunkerMode(false, timestamp, { from: steth.address }) + assert.emits(tx2, 'BunkerModeDisabled') + assert(!(await withdrawalQueue.isBunkerModeActive())) + assert.equals(ethers.constants.MaxUint256, await withdrawalQueue.bunkerModeSinceTimestamp()) + }) + }) + context('Request', async () => { it('One can request a withdrawal', async () => { const receipt = await withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }) @@ -951,6 +992,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer]) assert.equals(aliceBalancesAfter, aliceBalancesBefore.sub(bn(ETH(10)).mul(bn(withdrawalRequestsCount)))) }) }) + context('Transfer request', async () => { const amount = ETH(300) let requestId From 378e2943eb00856117d297e4cea9d570211fa3c7 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Wed, 22 Feb 2023 19:20:51 +0700 Subject: [PATCH 009/236] test: check WithdrawalQueue initial queue and checkpoint items --- .../WithdrawalQueueERC721Mock.sol | 24 +++++++++++++++++++ test/0.8.9/withdrawal-queue-deploy.test.js | 22 +++++++++++++++++ test/helpers/withdrawals.js | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol diff --git a/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol b/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol new file mode 100644 index 000000000..8ab843d98 --- /dev/null +++ b/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +/* See contracts/COMPILERS.md */ +pragma solidity 0.8.9; + +import {WithdrawalQueueERC721} from "../WithdrawalQueueERC721.sol"; + +contract WithdrawalQueueERC721Mock is WithdrawalQueueERC721 { + constructor( + address _wstETH, + string memory _name, + string memory _symbol + ) WithdrawalQueueERC721(_wstETH, _name, _symbol) { + } + + function getQueueItem(uint256 id) external view returns (WithdrawalRequest memory) { + return _getQueue()[id]; + } + + function getCheckpointItem(uint256 id) external view returns (DiscountCheckpoint memory) { + return _getCheckpoints()[id]; + } +} diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 0a4938922..d34816f25 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -99,6 +99,28 @@ contract( }) }) + it('initial queue and checkpoint items', async () => { + const { withdrawalQueue } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer + }) + const initialQueueItem = await withdrawalQueue.getQueueItem(0) + + const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() + const initialCheckpointItem = await withdrawalQueue.getCheckpointItem(lastCheckpointIndex) + + assert.equals(+initialQueueItem.cumulativeStETH, 0) + assert.equals(+initialQueueItem.cumulativeShares, 0) + assert.equals(initialQueueItem.owner, ZERO_ADDRESS) + // assert.equals(initialQueueItem.timestamp, (block.number)) + assert.equals(initialQueueItem.claimed, true) + + assert.equals(+initialCheckpointItem.fromRequestId, 0) + assert.equals(+initialCheckpointItem.discountFactor, 0) + }) + context('no roles for zero addresses', () => { it('check if pauser is zero', async () => { const { withdrawalQueue } = await deployWithdrawalQueue({ diff --git a/test/helpers/withdrawals.js b/test/helpers/withdrawals.js index 9a247fc80..00fc9d356 100644 --- a/test/helpers/withdrawals.js +++ b/test/helpers/withdrawals.js @@ -1,7 +1,7 @@ const { utils } = require('ethers') const OssifiableProxy = artifacts.require('OssifiableProxy.sol') -const WithdrawalQueueERC721 = artifacts.require('WithdrawalQueueERC721.sol') +const WithdrawalQueueERC721 = artifacts.require('WithdrawalQueueERC721Mock.sol') async function deploy(ownerAddress, wstethAddress, name = "Lido: Withdrawal Request NFT", symbol = "unstETH") { const impl = await WithdrawalQueueERC721.new(wstethAddress, name, symbol) From ae4d7e77e681e220401337626f75d5fd86e043cc Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 22 Feb 2023 19:25:08 +0700 Subject: [PATCH 010/236] chore: remove await for emits asserts --- ...ors-exit-bus-oracle-access-control.test.js | 2 +- test/0.8.9/staking-router.test.js | 38 +++++++++---------- test/0.8.9/withdrawal-queue-deploy.test.js | 24 ++++++------ 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js index dca98c7f8..b086964eb 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js @@ -88,7 +88,7 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, account1 context('Admin is set at initialize', () => { it('should set admin at initialize', async () => { const DEFAULT_ADMIN_ROLE = await oracle.DEFAULT_ADMIN_ROLE() - await assert.emits(initTx, 'RoleGranted', { role: DEFAULT_ADMIN_ROLE, account: admin, sender: admin }) + assert.emits(initTx, 'RoleGranted', { role: DEFAULT_ADMIN_ROLE, account: admin, sender: admin }) }) it('should revert without admin address', async () => { diff --git a/test/0.8.9/staking-router.test.js b/test/0.8.9/staking-router.test.js index fd7e1fe3f..73e5f909b 100644 --- a/test/0.8.9/staking-router.test.js +++ b/test/0.8.9/staking-router.test.js @@ -65,9 +65,9 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(tx.logs.length, 3) - await assert.emits(tx, 'ContractVersionSet', { version: 1 }) - await assert.emits(tx, 'RoleGranted', { role: DEFAULT_ADMIN_ROLE, account: admin, sender: deployer }) - await assert.emits(tx, 'WithdrawalCredentialsSet', { withdrawalCredentials: wc }) + assert.emits(tx, 'ContractVersionSet', { version: 1 }) + assert.emits(tx, 'RoleGranted', { role: DEFAULT_ADMIN_ROLE, account: admin, sender: deployer }) + assert.emits(tx, 'WithdrawalCredentialsSet', { withdrawalCredentials: wc }) }) it('second initialize reverts', async () => { @@ -90,7 +90,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await app.hasRole(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, appManager), true) assert.equals(tx.logs.length, 1) - await assert.emits(tx, 'RoleGranted', { + assert.emits(tx, 'RoleGranted', { role: MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, account: appManager, sender: admin, @@ -103,7 +103,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await app.hasRole(STAKING_MODULE_PAUSE_ROLE, appManager), true) assert.equals(tx.logs.length, 1) - await assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_PAUSE_ROLE, account: appManager, sender: admin }) + assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_PAUSE_ROLE, account: appManager, sender: admin }) }) it('grant role STAKING_MODULE_RESUME_ROLE', async () => { @@ -112,7 +112,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await app.hasRole(STAKING_MODULE_RESUME_ROLE, appManager), true) assert.equals(tx.logs.length, 1) - await assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_RESUME_ROLE, account: appManager, sender: admin }) + assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_RESUME_ROLE, account: appManager, sender: admin }) }) it('grant role STAKING_MODULE_MANAGE_ROLE', async () => { @@ -121,7 +121,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await app.hasRole(STAKING_MODULE_MANAGE_ROLE, appManager), true) assert.equals(tx.logs.length, 1) - await assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_MANAGE_ROLE, account: appManager, sender: admin }) + assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_MANAGE_ROLE, account: appManager, sender: admin }) }) it('public constants', async () => { @@ -227,7 +227,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { const newWC = '0x'.padEnd(66, '5678') const tx = await app.setWithdrawalCredentials(newWC, { from: appManager }) - await assert.emits(tx, 'WithdrawalCredentialsSet', { withdrawalCredentials: newWC }) + assert.emits(tx, 'WithdrawalCredentialsSet', { withdrawalCredentials: newWC }) assert.equals(await stakingModule.getAvailableValidatorsCount(), 0) }) @@ -437,18 +437,18 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { } ) assert.equals(tx.logs.length, 3) - await assert.emits(tx, 'StakingModuleAdded', { + assert.emits(tx, 'StakingModuleAdded', { stakingModuleId: stakingModulesParams[0].expectedModuleId, stakingModule: stakingModule1.address, name: stakingModulesParams[0].name, createdBy: appManager, }) - await assert.emits(tx, 'StakingModuleTargetShareSet', { + assert.emits(tx, 'StakingModuleTargetShareSet', { stakingModuleId: stakingModulesParams[0].expectedModuleId, targetShare: stakingModulesParams[0].targetShare, setBy: appManager, }) - await assert.emits(tx, 'StakingModuleFeesSet', { + assert.emits(tx, 'StakingModuleFeesSet', { stakingModuleId: stakingModulesParams[0].expectedModuleId, stakingModuleFee: stakingModulesParams[0].stakingModuleFee, treasuryFee: stakingModulesParams[0].treasuryFee, @@ -495,18 +495,18 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ) assert.equals(tx.logs.length, 3) - await assert.emits(tx, 'StakingModuleAdded', { + assert.emits(tx, 'StakingModuleAdded', { stakingModuleId: stakingModulesParams[1].expectedModuleId, stakingModule: stakingModule2.address, name: stakingModulesParams[1].name, createdBy: appManager, }) - await assert.emits(tx, 'StakingModuleTargetShareSet', { + assert.emits(tx, 'StakingModuleTargetShareSet', { stakingModuleId: stakingModulesParams[1].expectedModuleId, targetShare: stakingModulesParams[1].targetShare, setBy: appManager, }) - await assert.emits(tx, 'StakingModuleFeesSet', { + assert.emits(tx, 'StakingModuleFeesSet', { stakingModuleId: stakingModulesParams[1].expectedModuleId, stakingModuleFee: stakingModulesParams[1].stakingModuleFee, treasuryFee: stakingModulesParams[1].treasuryFee, @@ -638,12 +638,12 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(tx.logs.length, 2) - await assert.emits(tx, 'StakingModuleTargetShareSet', { + assert.emits(tx, 'StakingModuleTargetShareSet', { stakingModuleId: stakingModuleNewParams.id, targetShare: stakingModuleNewParams.targetShare, setBy: appManager, }) - await assert.emits(tx, 'StakingModuleFeesSet', { + assert.emits(tx, 'StakingModuleFeesSet', { stakingModuleId: stakingModuleNewParams.id, stakingModuleFee: stakingModuleNewParams.stakingModuleFee, treasuryFee: stakingModuleNewParams.treasuryFee, @@ -688,7 +688,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { } ) - await assert.emits(tx, 'StakingModuleStatusSet', { + assert.emits(tx, 'StakingModuleStatusSet', { stakingModuleId: stakingModulesParams[0].expectedModuleId, status: StakingModuleStatus.Stopped, setBy: appManager, @@ -746,7 +746,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { from: appManager, }) - await assert.emits(tx, 'StakingModuleStatusSet', { + assert.emits(tx, 'StakingModuleStatusSet', { stakingModuleId: stakingModulesParams[0].expectedModuleId, status: StakingModuleStatus.DepositsPaused, setBy: appManager, @@ -821,7 +821,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { from: appManager, }) - await assert.emits(tx, 'StakingModuleStatusSet', { + assert.emits(tx, 'StakingModuleStatusSet', { stakingModuleId: stakingModulesParams[0].expectedModuleId, status: StakingModuleStatus.Active, setBy: appManager, diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 0a4938922..0604db507 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -18,7 +18,7 @@ async function deployWithdrawalQueue({ queueBunkerReporter, queueName = 'Unsteth nft', symbol = 'UNSTETH', - doResume = true + doResume = true, }) { const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) const wsteth = await WstETH.new(steth.address, { from: stethOwner }) @@ -43,12 +43,12 @@ async function deployWithdrawalQueue({ initTx, steth, wsteth, - withdrawalQueue + withdrawalQueue, } } module.exports = { - deployWithdrawalQueue + deployWithdrawalQueue, } contract( @@ -61,7 +61,7 @@ contract( queueAdmin, queuePauser, queueResumer, - doResume: false + doResume: false, }) assert.equals(await withdrawalQueue.isPaused(), true) }) @@ -71,7 +71,7 @@ contract( stethOwner, queueAdmin, queuePauser, - queueResumer + queueResumer, }) const BUNKER_MODE_DISABLED_TIMESTAMP = await withdrawalQueue.BUNKER_MODE_DISABLED_TIMESTAMP() const isBunkerModeActive = await withdrawalQueue.isBunkerModeActive() @@ -88,14 +88,14 @@ contract( queuePauser, queueResumer, queueFinalizer, - queueBunkerReporter + queueBunkerReporter, }) - await assert.emits(initTx, 'InitializedV1', { + assert.emits(initTx, 'InitializedV1', { _admin: queueAdmin, _pauser: queuePauser, _resumer: queueResumer, _finalizer: queueFinalizer, - _bunkerReporter: queueBunkerReporter + _bunkerReporter: queueBunkerReporter, }) }) @@ -105,7 +105,7 @@ contract( stethOwner, queueAdmin, queuePauser: ZERO_ADDRESS, - queueResumer + queueResumer, }) const role = await withdrawalQueue.PAUSE_ROLE() const memberCount = await withdrawalQueue.getRoleMemberCount(role) @@ -118,7 +118,7 @@ contract( queueAdmin, queuePauser, queueResumer: ZERO_ADDRESS, - doResume: false + doResume: false, }) const role = await withdrawalQueue.RESUME_ROLE() const memberCount = await withdrawalQueue.getRoleMemberCount(role) @@ -131,7 +131,7 @@ contract( queueAdmin, queuePauser, queueResumer, - queueFinalizer: ZERO_ADDRESS + queueFinalizer: ZERO_ADDRESS, }) const role = await withdrawalQueue.FINALIZE_ROLE() const memberCount = await withdrawalQueue.getRoleMemberCount(role) @@ -144,7 +144,7 @@ contract( queueAdmin, queuePauser, queueResumer, - queueBunkerReporter: ZERO_ADDRESS + queueBunkerReporter: ZERO_ADDRESS, }) const role = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() const memberCount = await withdrawalQueue.getRoleMemberCount(role) From 380cf4a0e4fe1c3c25a4a67d0dc9d7fc90b7751a Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Wed, 22 Feb 2023 20:15:54 +0700 Subject: [PATCH 011/236] test: WithdrawalQueue do not accept requests while is paused --- test/0.8.9/withdrawal-queue.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 0d88154c1..e7b0bc260 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -253,6 +253,16 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, 'TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE' ) }) + + it('One cant request while is paused', async () => { + const PAUSE_INFINITELY = await withdrawalQueue.PAUSE_INFINITELY() + await withdrawalQueue.pause(PAUSE_INFINITELY, { from: daoAgent }) + await assert.reverts(withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), 'ResumedExpected()') + await assert.reverts( + withdrawalQueue.requestWithdrawalsWstETH([ETH(300)], owner, { from: user }), + 'ResumedExpected()' + ) + }) }) context('Finalization', async () => { From 75f9c756fdec1c9711b8d319d84a8002165daaaf Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Wed, 22 Feb 2023 20:16:12 +0700 Subject: [PATCH 012/236] test: WithdrawalQueue requests data is being accumulated properly --- test/0.8.9/withdrawal-queue-deploy.test.js | 23 +++++++++-------- test/0.8.9/withdrawal-queue.test.js | 30 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 52ab816a8..b02ed0482 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -104,21 +104,22 @@ contract( stethOwner, queueAdmin, queuePauser, - queueResumer + queueResumer, }) - const initialQueueItem = await withdrawalQueue.getQueueItem(0) - const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() - const initialCheckpointItem = await withdrawalQueue.getCheckpointItem(lastCheckpointIndex) + const queueId = await withdrawalQueue.getLastRequestId() + const queueItem = await withdrawalQueue.getQueueItem(queueId) + + const checkpointIndex = await withdrawalQueue.getLastCheckpointIndex() + const checkpointItem = await withdrawalQueue.getCheckpointItem(checkpointIndex) - assert.equals(+initialQueueItem.cumulativeStETH, 0) - assert.equals(+initialQueueItem.cumulativeShares, 0) - assert.equals(initialQueueItem.owner, ZERO_ADDRESS) - // assert.equals(initialQueueItem.timestamp, (block.number)) - assert.equals(initialQueueItem.claimed, true) + assert.equals(+queueItem.cumulativeStETH, 0) + assert.equals(+queueItem.cumulativeShares, 0) + assert.equals(queueItem.owner, ZERO_ADDRESS) + assert.equals(queueItem.claimed, true) - assert.equals(+initialCheckpointItem.fromRequestId, 0) - assert.equals(+initialCheckpointItem.discountFactor, 0) + assert.equals(+checkpointItem.fromRequestId, 0) + assert.equals(+checkpointItem.discountFactor, 0) }) context('no roles for zero addresses', () => { diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index e7b0bc260..b38ee25fa 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -263,6 +263,36 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, 'ResumedExpected()' ) }) + + it('data is being accumulated properly', async () => { + const queueItemStep0 = await withdrawalQueue.getQueueItem(await withdrawalQueue.getLastRequestId()) + + const amountStep1 = StETH(50) + const sharesStep1 = await steth.getSharesByPooledEth(amountStep1) + await withdrawalQueue.requestWithdrawals([amountStep1], owner, { from: user }) + const queueItemStep1 = await withdrawalQueue.getQueueItem(await withdrawalQueue.getLastRequestId()) + + assert.equals(+queueItemStep1.cumulativeStETH, +amountStep1 + +queueItemStep0.cumulativeStETH) + assert.equals(+queueItemStep1.cumulativeShares, +sharesStep1 + +queueItemStep0.cumulativeShares) + assert.equals(queueItemStep1.owner, owner) + assert.equals(queueItemStep1.claimed, false) + + const amountStep2 = StETH(100) + const sharesStep2 = await steth.getSharesByPooledEth(amountStep2) + await withdrawalQueue.requestWithdrawals([amountStep2], owner, { from: user }) + const queueItemStep2 = await withdrawalQueue.getQueueItem(await withdrawalQueue.getLastRequestId()) + + assert.equals( + +queueItemStep2.cumulativeStETH, + +amountStep2 + +queueItemStep1.cumulativeStETH + +queueItemStep0.cumulativeStETH + ) + assert.equals( + +queueItemStep2.cumulativeShares, + +sharesStep2 + +queueItemStep1.cumulativeShares + +queueItemStep0.cumulativeShares + ) + assert.equals(queueItemStep2.owner, owner) + assert.equals(queueItemStep2.claimed, false) + }) }) context('Finalization', async () => { From d71ffb94ec179a7e4e8bdf30000c2f9c36d26bbe Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Wed, 22 Feb 2023 21:25:21 +0700 Subject: [PATCH 013/236] test: WithdrawalQueue finalization revert cases --- test/0.8.9/withdrawal-queue.test.js | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index b38ee25fa..876328c4c 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -393,6 +393,52 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await ethers.provider.getBalance(withdrawalQueue.address) ) }) + + it('batch reverts if share rate is zero', async () => { + await assert.reverts( + withdrawalQueue.finalizationBatch(1, shareRate(0)), + 'ZeroShareRate()' + ) + }) + + it('reverts if request with given id did not even created', async () => { + const idAhead = +(await withdrawalQueue.getLastRequestId()) + 1 + + await assert.reverts( + withdrawalQueue.finalize(idAhead, { from: steth.address, value: amount }), + `InvalidRequestId(${idAhead})` + ) + + await assert.reverts( + withdrawalQueue.finalizationBatch(idAhead, shareRate(300)), + `InvalidRequestId(${idAhead})` + ) + }) + + it('reverts if request with given id was finalized already', async () => { + const id = +(await withdrawalQueue.getLastRequestId()) + await withdrawalQueue.finalize(id, { from: steth.address, value: amount }) + + await assert.reverts( + withdrawalQueue.finalize(id, { from: steth.address, value: amount }), + `InvalidRequestId(${id})` + ) + + await assert.reverts( + withdrawalQueue.finalizationBatch(id, shareRate(300)), + `InvalidRequestId(${id})` + ) + }) + + it('reverts if given amount to finalize exceeds requested', async () => { + const id = +(await withdrawalQueue.getLastRequestId()) + const amountExceeded = bn(ETH(400)) + + await assert.reverts( + withdrawalQueue.finalize(id, { from: steth.address, value: amountExceeded }), + `TooMuchEtherToFinalize(${+amountExceeded}, ${+amount})` + ) + }) }) context('getClaimableEth()', () => { From 6bea9b9bb3e2644f3aa2f277c1c09b2b2bffd35e Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Wed, 22 Feb 2023 21:26:18 +0700 Subject: [PATCH 014/236] test: prettier --- test/0.8.9/withdrawal-queue.test.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 876328c4c..b1c64b828 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -395,10 +395,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('batch reverts if share rate is zero', async () => { - await assert.reverts( - withdrawalQueue.finalizationBatch(1, shareRate(0)), - 'ZeroShareRate()' - ) + await assert.reverts(withdrawalQueue.finalizationBatch(1, shareRate(0)), 'ZeroShareRate()') }) it('reverts if request with given id did not even created', async () => { @@ -409,10 +406,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, `InvalidRequestId(${idAhead})` ) - await assert.reverts( - withdrawalQueue.finalizationBatch(idAhead, shareRate(300)), - `InvalidRequestId(${idAhead})` - ) + await assert.reverts(withdrawalQueue.finalizationBatch(idAhead, shareRate(300)), `InvalidRequestId(${idAhead})`) }) it('reverts if request with given id was finalized already', async () => { @@ -424,10 +418,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, `InvalidRequestId(${id})` ) - await assert.reverts( - withdrawalQueue.finalizationBatch(id, shareRate(300)), - `InvalidRequestId(${id})` - ) + await assert.reverts(withdrawalQueue.finalizationBatch(id, shareRate(300)), `InvalidRequestId(${id})`) }) it('reverts if given amount to finalize exceeds requested', async () => { From 0c99d242d5565e7830702be1d5a1165c31946b19 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Wed, 22 Feb 2023 22:04:06 +0200 Subject: [PATCH 015/236] chore: improve assertions --- test/helpers/assert.js | 50 ++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/test/helpers/assert.js b/test/helpers/assert.js index 37d27791e..5c077074c 100644 --- a/test/helpers/assert.js +++ b/test/helpers/assert.js @@ -6,14 +6,23 @@ const { toChecksumAddress } = require('ethereumjs-util') const { isAddress } = require('ethers/lib/utils') const { toBN } = require('./utils') -chai.util.addMethod(chai.assert, 'emits', function (receipt, eventName, args = {}, options = {}) { - const event = getEvent(receipt, eventName, args, options.abi) - this.isTrue(event !== undefined, `Event ${eventName} with args ${JSON.stringify(args)} wasn't found`) +chai.util.addMethod(chai.assert, 'emits', function (receipt, eventName, args = undefined, options = {}) { + const events = getEvents(receipt, eventName, { decodeForAbi: options.abi }) + chai.assert(events.length !== 0, () => `Expected event '${eventName}' wasn't emitted`) + if (args !== undefined) { + chai.assert( + findEventWithArgs(args, events) !== undefined, + () => `No '${eventName}' event was emitted with expected args ${JSON.stringify(args)}` + ) + } }) chai.util.addMethod(chai.assert, 'emitsAt', function (receipt, eventName, index, args = {}, options = {}) { const event = getEventAt(receipt, eventName, index, args, options.abi) - this.isTrue(event !== undefined, `Event ${eventName} at ${index} with args ${JSON.stringify(args)} wasn't found`) + chai.assert( + event !== undefined, + () => `Event '${eventName}' at index ${index} with args ${JSON.stringify(args)} wasn't found` + ) }) chai.util.addMethod( @@ -63,17 +72,25 @@ chai.util.addMethod(chai.assert, 'equals', function (actual, expected, errorMsg) }) chai.util.addMethod(chai.assert, 'equalsDelta', function (actual, expected, delta, errorMsg) { + this.isClose(actual, expected, delta, errorMsg) +}) + +const msg = (errorMsg, str) => `${errorMsg ? `${errorMsg}: ` : ''}${str}` + +chai.util.addMethod(chai.assert, 'isClose', function (actual, expected, delta, errorMsg) { const diff = toBN(actual).sub(toBN(expected)).abs() chai.assert( diff.lte(toBN(delta)), - () => - `${ - errorMsg ? `${errorMsg}: ` : '' - }Expected ${actual} to be close to ${expected} with max diff ${delta}, actual diff ${diff}`, - () => - `${ - errorMsg ? `${errorMsg}: ` : '' - }Expected ${actual} not to be close to ${expected} with min diff ${delta}, actual diff ${diff}` + () => msg(errorMsg, `Expected ${actual} to be close to ${expected} with max diff ${delta}, actual diff ${diff}`), + () => msg(errorMsg, `Expected ${actual} not to be close to ${expected} with min diff ${delta}, actual diff ${diff}`) + ) +}) + +chai.util.addMethod(chai.assert, 'bnAbove', function (nAbove, nBelow, errorMsg) { + chai.assert( + toBN(nAbove).gt(toBN(nBelow)), + () => msg(errorMsg, `Expected ${nAbove} to be above ${nBelow}`), + () => msg(errorMsg, `Expected ${nAbove} not to be above ${nBelow}`) ) }) @@ -131,8 +148,13 @@ function getEventAt(receipt, eventName, index, args, abi) { } function getEvent(receipt, eventName, args, abi) { - return getEvents(receipt, eventName, { decodeForAbi: abi }).find((e) => - // find the first index where every event argument matches the expected one + const events = getEvents(receipt, eventName, { decodeForAbi: abi }) + return findEventWithArgs(args, events) +} + +function findEventWithArgs(args, events) { + // find the first index where every event argument matches the expected one + return events.find((e) => Object.entries(args).every( ([argName, argValue]) => e.args[argName] !== undefined && normalizeArg(e.args[argName]) === normalizeArg(argValue) ) From d09ee914bb54a59013a9b2fc3cf914f15e7fd070 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Wed, 22 Feb 2023 22:05:07 +0200 Subject: [PATCH 016/236] withdrawal queue: add a failing test for the multiple rates scenario --- test/0.8.9/withdrawal-queue-deploy.test.js | 6 +- ...ithdrawal-queue-share-rate-changes.test.js | 100 ++++++++++++++++++ test/helpers/utils.js | 9 ++ 3 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 test/0.8.9/withdrawal-queue-share-rate-changes.test.js diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index b02ed0482..4fa959103 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -29,14 +29,14 @@ async function deployWithdrawalQueue({ const initTx = await withdrawalQueue.initialize( queueAdmin, - queuePauser, - queueResumer, + queuePauser || queueAdmin, + queueResumer || queueAdmin, queueFinalizer || steth.address, queueBunkerReporter || steth.address ) if (doResume) { - await withdrawalQueue.resume({ from: queueResumer }) + await withdrawalQueue.resume({ from: queueResumer || queueAdmin }) } return { diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js new file mode 100644 index 000000000..b860af6bc --- /dev/null +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -0,0 +1,100 @@ +const { contract, ethers } = require('hardhat') + +const { assert } = require('../helpers/assert') +const { e18, e27, toBN, getFirstEventArgs } = require('../helpers/utils') +const { MAX_UINT256 } = require('../0.6.12/helpers/constants') +const { EvmSnapshot } = require('../helpers/blockchain') + +const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') + +contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { + const evmSnapshot = new EvmSnapshot(ethers.provider) + const snapshot = () => evmSnapshot.make() + const rollback = () => evmSnapshot.rollback() + + const TOTAL_SHARES = toBN(e18(10)) + + let queue, steth + + const setShareRate = async (rate) => { + await steth.setTotalPooledEther(TOTAL_SHARES.mul(toBN(rate))) + } + + before('deploy', async () => { + const deployed = await deployWithdrawalQueue({ + stethOwner: owner, + queueAdmin: daoAgent, + queueFinalizer: finalizer, + }) + + steth = deployed.steth + queue = deployed.withdrawalQueue + + const userShares = toBN(TOTAL_SHARES).sub(toBN(await steth.getTotalShares())) + assert.bnAbove(userShares, 0) + + await steth.mintShares(user, userShares) + await setShareRate(1) + + await steth.approve(queue.address, MAX_UINT256, { from: user }) + + await snapshot() + }) + + context(`multiple requests with diff entry share rate`, async () => { + /// + /// invariant 1: all requests in the same batch should be finalized using the same share rate + /// + /// invariant 2: a withdrawal request cannot be finalized using a lower share rate than the + /// minimum share rate that was reported by the oracle since the last oracle report before + /// the request was added to the queue + /// + after(rollback) + + const requestIds = [0, 0] + + it(`share rate 1.0: a user requests a withdrawal of 1 stETH (10**18 shares)`, async () => { + const tx = await queue.requestWithdrawals([e18(1)], user, { from: user }) + requestIds[0] = +getFirstEventArgs(tx, 'WithdrawalRequested').requestId + assert.equals(await queue.unfinalizedStETH(), e18(1)) + }) + + it(`protocol receives rewards, changing share rate to 2.0`, async () => { + await setShareRate(2) + }) + + it(`share rate 2.0: a user requests a withdrawal of 2 stETH (10**18 shares)`, async () => { + const tx = await queue.requestWithdrawals([e18(2)], user, { from: user }) + requestIds[1] = +getFirstEventArgs(tx, 'WithdrawalRequested').requestId + assert.equals(await queue.unfinalizedStETH(), e18(3)) + }) + + it(`protocol receives slashing, changing share rate to 1.0`, async () => { + await setShareRate(1) + }) + + it(`both requests can be finalized with 2 ETH`, async () => { + const batch = await queue.finalizationBatch(requestIds[1], e27(1)) + assert.equals(batch.ethToLock, e18(2)) + assert.equals(batch.sharesToBurn, e18(2)) + }) + + let claimableEther + + it(`requests get finalized`, async () => { + await queue.finalize(requestIds[1], { from: finalizer, value: e18(2) }) + assert.equals(await queue.getLastFinalizedRequestId(), requestIds[1]) + + const hints = await queue.findCheckpointHintsUnbounded(requestIds) + claimableEther = await queue.getClaimableEther(requestIds, hints) + }) + + it(`first request is fullfilled with 1 ETH`, async () => { + assert.isClose(claimableEther[0], e18(1), 10) + }) + + it(`second request is fullfilled with 1 ETH`, async () => { + assert.isClose(claimableEther[1], e18(1), 10) + }) + }) +}) diff --git a/test/helpers/utils.js b/test/helpers/utils.js index aaaede6c9..f72e879c9 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -1,6 +1,8 @@ const { web3 } = require('hardhat') const assert = require('node:assert') +const chai = require('chai') const { BN } = require('bn.js') +const { getEvents } = require('@aragon/contract-helpers-test') const ZERO_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000' @@ -117,6 +119,12 @@ const calcSharesMintedAsFees = (rewards, fee, feePoints, prevTotalShares, newTot ) } +function getFirstEventArgs(receipt, eventName, abi = undefined) { + const events = getEvents(receipt, eventName, { decodeForAbi: abi }) + chai.assert(events.length !== 0, () => `Expected event ${eventName} wasn't emitted`) + return events[0].args +} + module.exports = { ZERO_HASH, pad, @@ -143,4 +151,5 @@ module.exports = { toStr, prepIdsCountsPayload, calcSharesMintedAsFees, + getFirstEventArgs, } From 1f25a5bb58e3be862b430709dd51aa6067075a1b Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Thu, 23 Feb 2023 14:31:28 +0700 Subject: [PATCH 017/236] feat: claiming scenarios --- test/0.8.9/withdrawal-queue.test.js | 55 +++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index b1c64b828..f1269e1d2 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -1,4 +1,4 @@ -const { artifacts, contract, ethers, web3 } = require('hardhat') +const { contract, ethers, web3 } = require('hardhat') const { bn, getEventArgument, ZERO_ADDRESS, ZERO_BYTES32 } = require('@aragon/contract-helpers-test') const { ETH, StETH, shareRate, shares } = require('../helpers/utils') @@ -572,6 +572,57 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) + context('claim scenarios', async () => { + const requestCount = 5 + const requestsAmounts = Array(requestCount).fill(StETH(1)) + const total = StETH(requestCount) + let requestIds + + beforeEach(async () => { + await withdrawalQueue.requestWithdrawals(requestsAmounts, user, { from: user }) + requestIds = await withdrawalQueue.getWithdrawalRequests(user, { from: user }) + }) + + it('direct', async () => { + const balanceBefore = bn(await ethers.provider.getBalance(user)) + const id = await withdrawalQueue.getLastRequestId() + withdrawalQueue.finalize(id, { from: steth.address, value: total }) + for (let index = 0; index < requestIds.length; index++) { + const requestId = requestIds[index] + await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + } + const balanceAfter = bn(await ethers.provider.getBalance(user)) + assert.equals(balanceBefore.add(bn(total)), balanceAfter) + }) + + it('reverse', async () => { + const balanceBefore = bn(await ethers.provider.getBalance(user)) + const id = await withdrawalQueue.getLastRequestId() + withdrawalQueue.finalize(id, { from: steth.address, value: total }) + + for (let index = requestIds.length - 1; index >= 0; index--) { + const requestId = requestIds[index] + await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + } + const balanceAfter = bn(await ethers.provider.getBalance(user)) + assert.equals(balanceBefore.add(bn(total)), balanceAfter) + }) + + it('random', async () => { + const randomIds = [...requestIds].sort(() => 0.5 - Math.random()) + const balanceBefore = bn(await ethers.provider.getBalance(user)) + const id = await withdrawalQueue.getLastRequestId() + withdrawalQueue.finalize(id, { from: steth.address, value: total }) + + for (let index = 0; index < randomIds.length; index++) { + const requestId = randomIds[index] + await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + } + const balanceAfter = bn(await ethers.provider.getBalance(user)) + assert.equals(balanceBefore.add(bn(total)), balanceAfter) + }) + }) + context('findLastFinalizableRequestIdByTimestamp()', async () => { const numOfRequests = 10 @@ -1039,7 +1090,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const amount = bn(ETH(10)).mul(bn(withdrawalRequestsCount)) const deadline = MAX_UINT256 - await impersonate(hre.ethers.provider, alice.address) + await impersonate(ethers.provider, alice.address) const domainSeparator = await steth.DOMAIN_SEPARATOR() const { v, r, s } = signPermit( alice.address, From 23e800d49eebe50c21d5c462aae284f96e0c2e72 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Thu, 23 Feb 2023 14:40:20 +0700 Subject: [PATCH 018/236] feat: changing rate scenario --- test/0.8.9/withdrawal-queue.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index f1269e1d2..c4ba2f9be 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -621,6 +621,24 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const balanceAfter = bn(await ethers.provider.getBalance(user)) assert.equals(balanceBefore.add(bn(total)), balanceAfter) }) + + it('different rates', async () => { + const balanceBefore = bn(await ethers.provider.getBalance(user)) + const totalDistributedEth = bn(0) + for (let index = 0; index < requestIds.length; index++) { + const requestId = requestIds[index] + await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(1 / (index + 1)) }) + totalDistributedEth.iadd(bn(ETH(1 / (index + 1)))) + } + const id = await withdrawalQueue.getLastRequestId() + withdrawalQueue.finalize(id, { from: steth.address, value: total }) + for (let index = 0; index < requestIds.length; index++) { + const requestId = requestIds[index] + await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + } + const balanceAfter = bn(await ethers.provider.getBalance(user)) + assert.equals(balanceBefore.add(totalDistributedEth), balanceAfter) + }) }) context('findLastFinalizableRequestIdByTimestamp()', async () => { From 9d6f7cd79f344c067123d93eb376f411c1939072 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Thu, 23 Feb 2023 20:20:08 +0700 Subject: [PATCH 019/236] test: WithdrawalQueue claimWithdrawalsTo reverts for zero recipient --- test/0.8.9/withdrawal-queue.test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index c4ba2f9be..1e8f4cdc5 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -492,6 +492,13 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.equals(await ethers.provider.getBalance(user), balanceBefore.add(bn(amount))) }) + it('claimWithdrawalsTo reverts for zero recipient', async () => { + await assert.reverts( + withdrawalQueue.claimWithdrawalsTo([1], [1], ZERO_ADDRESS, { from: owner }), + 'ZeroRecipient()' + ) + }) + it('Owner can claim a finalized request without hint', async () => { await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) From b150682e1297d3a1c3fce302e7097a3e1224c99f Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Thu, 23 Feb 2023 20:58:48 +0700 Subject: [PATCH 020/236] test: WithdrawalQueue more revert cases for claimWithdrawalsTo --- test/0.8.9/withdrawal-queue.test.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 1e8f4cdc5..5b87a87a1 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -492,11 +492,25 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.equals(await ethers.provider.getBalance(user), balanceBefore.add(bn(amount))) }) - it('claimWithdrawalsTo reverts for zero recipient', async () => { - await assert.reverts( - withdrawalQueue.claimWithdrawalsTo([1], [1], ZERO_ADDRESS, { from: owner }), - 'ZeroRecipient()' - ) + context('claimWithdrawalsTo', () => { + it('reverts for zero recipient', async () => { + await assert.reverts( + withdrawalQueue.claimWithdrawalsTo([1], [1], ZERO_ADDRESS, { from: owner }), + 'ZeroRecipient()' + ) + }) + + it('reverts with zero _requestId', async () => { + await assert.reverts(withdrawalQueue.claimWithdrawalsTo([0], [1], user, { from: owner }), 'InvalidRequestId(0)') + }) + + it('reverts if sender is not owner', async () => { + await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await assert.reverts( + withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: stranger }), + `NotOwner("${stranger}", "${owner}")` + ) + }) }) it('Owner can claim a finalized request without hint', async () => { From 5198418319160ff520bf8b0b3d48ee7890a41d4d Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Thu, 23 Feb 2023 23:03:23 +0700 Subject: [PATCH 021/236] test: WithdrawalQueue findCheckpointHints revert cases --- test/0.8.9/withdrawal-queue.test.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 5b87a87a1..afba8a725 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -901,6 +901,27 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, requestId = await withdrawalQueue.getLastRequestId() }) + it('reverts if requestId is zero', async () => { + const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() + await assert.reverts(withdrawalQueue.findCheckpointHints([0], 1, lastCheckpointIndex), 'InvalidRequestId(0)') + }) + + it('reverts if first index is zero', async () => { + const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() + await assert.reverts( + withdrawalQueue.findCheckpointHints([1], 0, lastCheckpointIndex), + `InvalidRequestIdRange(0, ${+lastCheckpointIndex})` + ) + }) + + it('reverts if last index is larger than in store', async () => { + const lastCheckpointWrong = (await withdrawalQueue.getLastCheckpointIndex()) + 1 + await assert.reverts( + withdrawalQueue.findCheckpointHints([1], 1, lastCheckpointWrong), + `InvalidRequestIdRange(0, ${+lastCheckpointWrong})` + ) + }) + it('returns empty list when passed empty request ids list', async () => { const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints([], 1, lastCheckpointIndex) From 2d9f2f4739286a3eb643a8447e841c4a1ef82f7b Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Fri, 24 Feb 2023 14:46:52 +0700 Subject: [PATCH 022/236] test: WithdrawalQueue getWithdrawalStatus revert scenarios --- test/0.8.9/withdrawal-queue.test.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index afba8a725..2484578f0 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -918,7 +918,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const lastCheckpointWrong = (await withdrawalQueue.getLastCheckpointIndex()) + 1 await assert.reverts( withdrawalQueue.findCheckpointHints([1], 1, lastCheckpointWrong), - `InvalidRequestIdRange(0, ${+lastCheckpointWrong})` + `InvalidRequestIdRange(1, ${+lastCheckpointWrong})` ) }) @@ -1262,4 +1262,15 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.isTrue(firstGasUsed >= secondGasUsed) }) }) + + context('getWithdrawalStatus', () => { + it('reverts if requestId is zero', async () => { + await assert.reverts(withdrawalQueue.getWithdrawalStatus([0]), `InvalidRequestId(0)`) + }) + + it('reverts if requestId is zero', async () => { + const idAhead = +(await withdrawalQueue.getLastRequestId()) + 1 + await assert.reverts(withdrawalQueue.getWithdrawalStatus([idAhead]), `InvalidRequestId(${idAhead})`) + }) + }) }) From 25fd7dee1230f0521469dc6768ce8a636a280fbb Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Fri, 24 Feb 2023 15:40:51 +0700 Subject: [PATCH 023/236] test: WithdrawalQueue.getClaimableEth reverts if last hint checkpoint is ahead of requestId --- test/0.8.9/withdrawal-queue.test.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 2484578f0..a6b7ed612 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -444,6 +444,15 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(1)) }) + it('reverts if last hint checkpoint is ahead of requestId', async () => { + await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(0.5) }) + + await withdrawalQueue.requestWithdrawals([ETH(2)], owner, { from: user }) + await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(0.5) }) + + await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') + }) + it('return 0 for non-finalized request', async () => { assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(0)) assert.equals(await withdrawalQueue.getClaimableEther([1], [51]), ETH(0)) From 50501d7ee1062ebdbf3036a936168348911e428d Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Fri, 24 Feb 2023 18:42:29 +0700 Subject: [PATCH 024/236] test: WithdrawalQueue more coverage testcases --- test/0.8.9/withdrawal-queue.test.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index a6b7ed612..f8b3c12f8 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -85,6 +85,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, ) await assert.reverts(withdrawalQueue.finalize(1, { from: owner }), 'ResumedExpected()') }) + + it('cant resume if not paused', async () => { + await assert.reverts(withdrawalQueue.resume(), 'PausedExpected()') + }) }) context('BunkerMode', async () => { @@ -520,6 +524,12 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, `NotOwner("${stranger}", "${owner}")` ) }) + + it('reverts if there is not enough balance', async () => { + await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await setBalance(withdrawalQueue.address, ETH(200)) + await assert.reverts(withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: owner }), 'NotEnoughEther()') + }) }) it('Owner can claim a finalized request without hint', async () => { @@ -1099,6 +1109,23 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const wstETHBalanceAfter = await wsteth.balanceOf(user) assert.equals(wstETHBalanceAfter, wstETHBalanceBefore.sub(bn(requests[0])).sub(bn(requests[1]))) }) + + it('uses sender address as owner if zero passed', async () => { + await wsteth.mint(user, ETH(1)) + await steth.mintShares(wsteth.address, shares(1)) + await steth.mintShares(user, shares(1)) + await wsteth.approve(withdrawalQueue.address, ETH(1), { from: user }) + + const tx = await withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], ZERO_ADDRESS, { from: user }) + + assert.emits(tx, 'WithdrawalRequested', { + requestId: 1, + requestor: user.toLowerCase(), + owner: user.toLowerCase(), + amountOfStETH: await steth.getPooledEthByShares(ETH(1)), + amountOfShares: shares(1), + }) + }) }) context('requestWithdrawalsWstETHWithPermit()', () => { @@ -1277,7 +1304,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts(withdrawalQueue.getWithdrawalStatus([0]), `InvalidRequestId(0)`) }) - it('reverts if requestId is zero', async () => { + it('reverts if requestId is ahead of currently stored', async () => { const idAhead = +(await withdrawalQueue.getLastRequestId()) + 1 await assert.reverts(withdrawalQueue.getWithdrawalStatus([idAhead]), `InvalidRequestId(${idAhead})`) }) From 4155d36a7a9077c2f38ef9ab9beabe5db81bdc03 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Fri, 24 Feb 2023 19:29:20 +0700 Subject: [PATCH 025/236] test: a bit better coverage for WithdrawalQueue --- test/0.8.9/withdrawal-queue-deploy.test.js | 19 +++++++++++++++++++ test/0.8.9/withdrawal-request-nft.test.js | 10 +++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 4fa959103..84b884e45 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -122,6 +122,25 @@ contract( assert.equals(+checkpointItem.discountFactor, 0) }) + it('check if pauser is zero', async () => { + await assert.reverts( + deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queueName: '', + }), + 'ZeroMetadata()' + ) + await assert.reverts( + deployWithdrawalQueue({ + stethOwner, + queueAdmin, + symbol: '', + }), + 'ZeroMetadata()' + ) + }) + context('no roles for zero addresses', () => { it('check if pauser is zero', async () => { const { withdrawalQueue } = await deployWithdrawalQueue({ diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index 44538619f..747f3c7e6 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -1,3 +1,4 @@ +const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const { contract, artifacts, ethers } = require('hardhat') const { assert } = require('../helpers/assert') @@ -58,12 +59,15 @@ contract('WithdrawalNFT', (addresses) => { }) describe('supportsInterface()', () => { - it('returns true for IERC165 interfaceiId (0x01ffc9a7)', async () => { + it('returns true for IERC165 interface id (0x01ffc9a7)', async () => { assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x01ffc9a7')) }) it('returns true for IERC721 interface id (0x80ac58cd)', async () => { assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x80ac58cd')) }) + it('returns true for IERC721Metadata interface id (0x5b5e139f)', async () => { + assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x5b5e139f')) + }) it('returns true for AccessControlEnumerable interface id (0x5a05180f)', async () => { assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x5a05180f')) }) @@ -84,6 +88,10 @@ contract('WithdrawalNFT', (addresses) => { assert.equals(await withdrawalQueueERC721.balanceOf(nftHolderStETH), 2) assert.equals(await withdrawalQueueERC721.balanceOf(nftHolderWstETH), 1) }) + + it('reverts for zero address', async () => { + await assert.reverts(withdrawalQueueERC721.balanceOf(ZERO_ADDRESS), `InvalidOwnerAddress("${ZERO_ADDRESS}")`) + }) }) describe('ownerOf()', () => { From 117b0fa33f76e96cf41a3fa6fcd6cde15f2a66de Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Fri, 24 Feb 2023 17:46:51 +0300 Subject: [PATCH 026/236] feat: report burner's balance --- contracts/0.4.24/Lido.sol | 118 +++++++----------- contracts/0.8.9/Burner.sol | 28 ++--- contracts/0.8.9/oracle/AccountingOracle.sol | 6 + .../OracleReportSanityChecker.sol | 56 ++++++--- .../test_helpers/AccountingOracleMock.sol | 2 + .../OracleReportSanityCheckerMocks.sol | 36 +++++- .../oracle/MockLidoForAccountingOracle.sol | 3 + contracts/common/interfaces/IBurner.sol | 6 +- lib/abi/AccountingOracle.json | 2 +- lib/abi/Burner.json | 2 +- lib/abi/ILido.json | 2 +- lib/abi/Lido.json | 2 +- lib/abi/OracleReportSanityChecker.json | 2 +- 13 files changed, 152 insertions(+), 113 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 47061b896..59aef31fa 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -36,6 +36,7 @@ interface IOracleReportSanityChecker { uint256 _postCLBalance, uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, + uint256 _sharesRequestedToBurn, uint256 _preCLValidators, uint256 _postCLValidators ) external view; @@ -47,11 +48,14 @@ interface IOracleReportSanityChecker { uint256 _postCLBalance, uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, - uint256 _etherToLockForWithdrawals + uint256 _sharesRequestedToBurn, + uint256 _etherToLockForWithdrawals, + uint256 _newSharesToBurnForWithdrawals ) external view returns ( uint256 withdrawals, uint256 elRewards, - uint256 sharesToBurnLimit + uint256 simulatedSharesToBurn, + uint256 sharesToBurn ); function checkWithdrawalQueueOracleReport( @@ -524,6 +528,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { // EL values uint256 withdrawalVaultBalance; uint256 elRewardsVaultBalance; + uint256 sharesRequestedToBurn; // Decision about withdrawals processing uint256 lastFinalizableRequestId; uint256 simulatedShareRate; @@ -544,15 +549,16 @@ contract Lido is Versioned, StETHPermit, AragonApp { /** * @notice Updates accounting stats, collects EL rewards and distributes collected rewards - * if beacon balance increased - * @dev periodically called by the Oracle contract + * if beacon balance increased, performs withdrawal requests finalization + * @dev periodically called by the AccountingOracle contract * * @param _reportTimestamp the moment of the oracle report calculation * @param _timeElapsed seconds elapsed since the previous report calculation * @param _clValidators number of Lido validators on Consensus Layer * @param _clBalance sum of all Lido validators' balances on Consensus Layer - * @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer for report block - * @param _elRewardsVaultBalance elRewards vault balance on Execution Layer for report block + * @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer at `_reportTimestamp` + * @param _elRewardsVaultBalance elRewards vault balance on Execution Layer at `_reportTimestamp` + * @param _sharesRequestedToBurn shares requested to burn through Burner at `_reportTimestamp` * @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 (1e27 precision) * @@ -575,6 +581,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { // EL values uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, + uint256 _sharesRequestedToBurn, // Decision about withdrawals processing uint256 _lastFinalizableRequestId, uint256 _simulatedShareRate @@ -586,9 +593,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { ) { _whenNotStopped(); - OracleReportContracts memory contracts = _loadOracleReportContracts(); - require(msg.sender == contracts.accountingOracle, "APP_AUTH_FAILED"); - return _handleOracleReport( OracleReportedData( _reportTimestamp, @@ -597,10 +601,10 @@ contract Lido is Versioned, StETHPermit, AragonApp { _clBalance, _withdrawalVaultBalance, _elRewardsVaultBalance, + _sharesRequestedToBurn, _lastFinalizableRequestId, _simulatedShareRate - ), - contracts + ) ); } @@ -1149,15 +1153,16 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @dev Intermediate data structure for `_handleOracleReport` * Helps to overcome `stack too deep` issue. */ - struct OracleReportContext{ + struct OracleReportContext { uint256 preCLValidators; uint256 preCLBalance; uint256 preTotalPooledEther; uint256 preTotalShares; - uint256 sharesToBurnLimit; - uint256 sharesMintedAsFees; uint256 etherToLockOnWithdrawalQueue; uint256 sharesToBurnFromWithdrawalQueue; + uint256 simulatedSharesToBurn; + uint256 sharesToBurn; + uint256 sharesMintedAsFees; } /** @@ -1178,14 +1183,16 @@ contract Lido is Versioned, StETHPermit, AragonApp { * 9. Sanity check for the provided simulated share rate */ function _handleOracleReport( - OracleReportedData memory _reportedData, - OracleReportContracts memory _contracts + OracleReportedData memory _reportedData ) internal returns ( uint256 postTotalPooledEther, uint256 postTotalShares, uint256 withdrawals, uint256 elRewards ) { + OracleReportContracts memory contracts = _loadOracleReportContracts(); + + require(msg.sender == contracts.accountingOracle, "APP_AUTH_FAILED"); require(_reportedData.reportTimestamp <= block.timestamp, "INVALID_REPORT_TIMESTAMP"); OracleReportContext memory reportContext; @@ -1204,35 +1211,45 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 2. // Pass the report data to sanity checker (reverts if malformed) - _checkAccountingOracleReport(_contracts, _reportedData, reportContext); + _checkAccountingOracleReport(contracts, _reportedData, reportContext); // Step 3. // Pre-calculate the ether to lock for withdrawal queue and shares to be burnt + // due to withdrawal requests to finalize if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { ( reportContext.etherToLockOnWithdrawalQueue, reportContext.sharesToBurnFromWithdrawalQueue - ) = _calculateWithdrawals(_contracts, _reportedData); + ) = _calculateWithdrawals(contracts, _reportedData); + + if (reportContext.sharesToBurnFromWithdrawalQueue > 0) { + IBurner(contracts.burner).requestBurnShares( + contracts.withdrawalQueue, + reportContext.sharesToBurnFromWithdrawalQueue + ); + } } // Step 4. // Pass the accounting values to sanity checker to smoothen positive token rebase ( - withdrawals, elRewards, reportContext.sharesToBurnLimit - ) = IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).smoothenTokenRebase( + withdrawals, elRewards, reportContext.simulatedSharesToBurn, reportContext.sharesToBurn + ) = IOracleReportSanityChecker(contracts.oracleReportSanityChecker).smoothenTokenRebase( reportContext.preTotalPooledEther, reportContext.preTotalShares, reportContext.preCLBalance, _reportedData.postCLBalance, _reportedData.withdrawalVaultBalance, _reportedData.elRewardsVaultBalance, - reportContext.etherToLockOnWithdrawalQueue + _reportedData.sharesRequestedToBurn, + reportContext.etherToLockOnWithdrawalQueue, + reportContext.sharesToBurnFromWithdrawalQueue ); // Step 5. // Invoke finalization of the withdrawal requests (send ether to withdrawal queue, assign shares to be burnt) _collectRewardsAndProcessWithdrawals( - _contracts, + contracts, withdrawals, elRewards, _reportedData.lastFinalizableRequestId, @@ -1258,14 +1275,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { ); // Step 7. - // Burn excess shares within the allowed limit (can postpone some shares to be burnt later) - // Return actually burnt shares of the current report's finalized withdrawal requests to use in sanity checks - uint256 burntCurrentWithdrawalShares = _burnSharesLimited( - IBurner(_contracts.burner), - _contracts.withdrawalQueue, - reportContext.sharesToBurnFromWithdrawalQueue, - reportContext.sharesToBurnLimit - ); + // Burn the previously requested shares + if (reportContext.sharesToBurn > 0) { + IBurner(contracts.burner).commitSharesToBurn(reportContext.sharesToBurn); + _burnShares(contracts.burner, reportContext.sharesToBurn); + } // Step 8. // Complete token rebase by informing observers (emit an event and call the external receivers if any) @@ -1275,16 +1289,16 @@ contract Lido is Versioned, StETHPermit, AragonApp { ) = _completeTokenRebase( _reportedData, reportContext, - IPostTokenRebaseReceiver(_contracts.postTokenRebaseReceiver) + IPostTokenRebaseReceiver(contracts.postTokenRebaseReceiver) ); // Step 9. Sanity check for the provided simulated share rate if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { - IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkSimulatedShareRate( + IOracleReportSanityChecker(contracts.oracleReportSanityChecker).checkSimulatedShareRate( postTotalPooledEther, postTotalShares, reportContext.etherToLockOnWithdrawalQueue, - burntCurrentWithdrawalShares, + reportContext.sharesToBurn.sub(reportContext.simulatedSharesToBurn), _reportedData.simulatedShareRate ); } @@ -1305,6 +1319,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { _reportedData.postCLBalance, _reportedData.withdrawalVaultBalance, _reportedData.elRewardsVaultBalance, + _reportedData.sharesRequestedToBurn, _reportContext.preCLValidators, _reportedData.clValidators ); @@ -1345,43 +1360,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { ); } - /* - * @dev Perform burning of `stETH` shares via the dedicated `Burner` contract. - * - * NB: some of the burning amount can be postponed for the next reports if positive token rebase smoothened. - * It's possible that underlying shares of the current oracle report's finalized withdrawals won't be burnt - * completely in a single oracle report round due to the provided `_sharesToBurnLimit` limit - * - * @return shares actually burnt for the current oracle report's finalized withdrawals - * these shares are assigned to be burnt most recently, so the amount can be calculated deducting - * `postponedSharesToBurn` shares (if any) after the burn commitment & execution - */ - function _burnSharesLimited( - IBurner _burner, - address _withdrawalQueue, - uint256 _sharesToBurnFromWithdrawalQueue, - uint256 _sharesToBurnLimit - ) internal returns (uint256 burntCurrentWithdrawalShares) { - if (_sharesToBurnFromWithdrawalQueue > 0) { - _burner.requestBurnShares(_withdrawalQueue, _sharesToBurnFromWithdrawalQueue); - } - - if (_sharesToBurnLimit > 0) { - uint256 sharesCommittedToBurnNow = _burner.commitSharesToBurn(_sharesToBurnLimit); - - if (sharesCommittedToBurnNow > 0) { - _burnShares(address(_burner), sharesCommittedToBurnNow); - } - } - - (uint256 coverShares, uint256 nonCoverShares) = _burner.getSharesRequestedToBurn(); - uint256 postponedSharesToBurn = coverShares.add(nonCoverShares); - - burntCurrentWithdrawalShares = - postponedSharesToBurn < _sharesToBurnFromWithdrawalQueue ? - _sharesToBurnFromWithdrawalQueue - postponedSharesToBurn : 0; - } - /** * @dev Load the contracts used for `handleOracleReport` internally. */ diff --git a/contracts/0.8.9/Burner.sol b/contracts/0.8.9/Burner.sol index c4997062c..b40b88d28 100644 --- a/contracts/0.8.9/Burner.sol +++ b/contracts/0.8.9/Burner.sol @@ -57,6 +57,7 @@ contract Burner is IBurner, AccessControlEnumerable { error ZeroRecoveryAmount(); error StETHRecoveryWrongFunc(); error ZeroBurnAmount(); + error BurnAmountExceedsActual(uint256 requestedAmount, uint256 actualAmount); error ZeroAddress(string field); bytes32 public constant REQUEST_BURN_MY_STETH_ROLE = keccak256("REQUEST_BURN_MY_STETH_ROLE"); @@ -278,19 +279,16 @@ contract Burner is IBurner, AccessControlEnumerable { * NB: The real burn enactment to be invoked after the call (via internal Lido._burnShares()) * * Increments `totalCoverSharesBurnt` and `totalNonCoverSharesBurnt` counters. - * Resets `coverSharesBurnRequested` and `nonCoverSharesBurnRequested` counters to zero. - * Does nothing if there are no pending burning requests. + * Decrements `coverSharesBurnRequested` and `nonCoverSharesBurnRequested` counters. + * Does nothing if zero amount passed. * - * @param _sharesToBurnLimit limit of the shares to be burnt - * @return sharesToBurnNow the actual value that can be burnt + * @param _sharesToBurn amount of shares to be burnt */ - function commitSharesToBurn( - uint256 _sharesToBurnLimit - ) external virtual override returns (uint256 sharesToBurnNow) { + function commitSharesToBurn(uint256 _sharesToBurn) external virtual override { if (msg.sender != STETH) revert AppAuthLidoFailed(); - if (_sharesToBurnLimit == 0) { - return 0; + if (_sharesToBurn == 0) { + return; } uint256 memCoverSharesBurnRequested = coverSharesBurnRequested; @@ -298,12 +296,13 @@ contract Burner is IBurner, AccessControlEnumerable { uint256 burnAmount = memCoverSharesBurnRequested + memNonCoverSharesBurnRequested; - if (burnAmount == 0) { - return 0; + if (_sharesToBurn > burnAmount) { + revert BurnAmountExceedsActual(_sharesToBurn, burnAmount); } + uint256 sharesToBurnNow; if (memCoverSharesBurnRequested > 0) { - uint256 sharesToBurnNowForCover = Math.min(_sharesToBurnLimit, memCoverSharesBurnRequested); + uint256 sharesToBurnNowForCover = Math.min(_sharesToBurn, memCoverSharesBurnRequested); totalCoverSharesBurnt += sharesToBurnNowForCover; uint256 stETHToBurnNowForCover = IStETH(STETH).getPooledEthByShares(sharesToBurnNowForCover); @@ -312,9 +311,9 @@ contract Burner is IBurner, AccessControlEnumerable { coverSharesBurnRequested -= sharesToBurnNowForCover; sharesToBurnNow += sharesToBurnNowForCover; } - if ((memNonCoverSharesBurnRequested > 0) && (sharesToBurnNow < _sharesToBurnLimit)) { + if ((memNonCoverSharesBurnRequested > 0) && (sharesToBurnNow < _sharesToBurn)) { uint256 sharesToBurnNowForNonCover = Math.min( - _sharesToBurnLimit - sharesToBurnNow, + _sharesToBurn - sharesToBurnNow, memNonCoverSharesBurnRequested ); @@ -325,6 +324,7 @@ contract Burner is IBurner, AccessControlEnumerable { nonCoverSharesBurnRequested -= sharesToBurnNowForNonCover; sharesToBurnNow += sharesToBurnNowForNonCover; } + assert(sharesToBurnNow == _sharesToBurn); } /** diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index f6ef31d40..b3c41a076 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -21,6 +21,7 @@ interface ILido { // EL values uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, + uint256 _sharesRequestedToBurn, // Decision about withdrawals processing uint256 _lastFinalizableRequestId, uint256 _simulatedShareRate @@ -232,6 +233,10 @@ contract AccountingOracle is BaseOracle { /// at the reference slot. uint256 elRewardsVaultBalance; + /// @dev The shares amount requested to burn through Burner as observed + /// at the reference slot. + uint256 sharesRequestedToBurn; + /// /// Decision /// @@ -610,6 +615,7 @@ contract AccountingOracle is BaseOracle { data.clBalanceGwei * 1e9, data.withdrawalVaultBalance, data.elRewardsVaultBalance, + data.sharesRequestedToBurn, data.lastFinalizableWithdrawalRequestId, data.simulatedShareRate ); diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index f15e06e5d..acf729969 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -10,6 +10,7 @@ import {Math256} from "../../common/lib/Math256.sol"; import {AccessControlEnumerable} from "../utils/access/AccessControlEnumerable.sol"; import {PositiveTokenRebaseLimiter, TokenRebaseLimiterData} from "../lib/PositiveTokenRebaseLimiter.sol"; import {ILidoLocator} from "../../common/interfaces/ILidoLocator.sol"; +import {IBurner} from "../../common/interfaces/IBurner.sol"; interface IWithdrawalQueue { function getWithdrawalRequestStatus(uint256 _requestId) @@ -327,12 +328,15 @@ contract OracleReportSanityChecker is AccessControlEnumerable { /// current oracle report /// @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 elRewards vault balance on Execution Layer for report block + /// @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer for the report calculation moment + /// @param _elRewardsVaultBalance elRewards vault balance on Execution Layer for the report calculation moment + /// @param _sharesRequestedToBurn shares requested to burn through Burner for the report calculation moment /// @param _etherToLockForWithdrawals ether to lock on withdrawals queue contract + /// @param _newSharesToBurnForWithdrawals new shares to burn due to withdrawal request finalization /// @return withdrawals ETH amount allowed to be taken from the withdrawals vault /// @return elRewards ETH amount allowed to be taken from the EL rewards vault - /// @return sharesToBurnLimit amount allowed to be burnt as part of the current token rebase + /// @return simulatedSharesToBurn simulated amount to be burnt (if no ether locked on withdrawals) + /// @return sharesToBurn amount to be burnt (accounting for withdrawals finalization) function smoothenTokenRebase( uint256 _preTotalPooledEther, uint256 _preTotalShares, @@ -340,8 +344,15 @@ contract OracleReportSanityChecker is AccessControlEnumerable { uint256 _postCLBalance, uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, - uint256 _etherToLockForWithdrawals - ) external view returns (uint256 withdrawals, uint256 elRewards, uint256 sharesToBurnLimit) { + uint256 _sharesRequestedToBurn, + uint256 _etherToLockForWithdrawals, + uint256 _newSharesToBurnForWithdrawals + ) external view returns ( + uint256 withdrawals, + uint256 elRewards, + uint256 simulatedSharesToBurn, + uint256 sharesToBurn + ) { TokenRebaseLimiterData memory tokenRebaseLimiter = PositiveTokenRebaseLimiter.initLimiterState( getMaxPositiveTokenRebase(), _preTotalPooledEther, @@ -356,9 +367,10 @@ contract OracleReportSanityChecker is AccessControlEnumerable { withdrawals = tokenRebaseLimiter.consumeLimit(_withdrawalVaultBalance); elRewards = tokenRebaseLimiter.consumeLimit(_elRewardsVaultBalance); - tokenRebaseLimiter.raiseLimit(_etherToLockForWithdrawals); - sharesToBurnLimit = tokenRebaseLimiter.getSharesToBurnLimit(); + simulatedSharesToBurn = Math256.min(tokenRebaseLimiter.getSharesToBurnLimit(), _sharesRequestedToBurn); + tokenRebaseLimiter.raiseLimit(_etherToLockForWithdrawals); + sharesToBurn = Math256.min(tokenRebaseLimiter.getSharesToBurnLimit(), _newSharesToBurnForWithdrawals + _sharesRequestedToBurn); } /// @notice Applies sanity checks to the accounting params of Lido's oracle report @@ -367,8 +379,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { /// 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 - /// @param _elRewardsVaultBalance el rewards vault balance on Execution Layer for report block + /// @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer for the report reference slot + /// @param _elRewardsVaultBalance el rewards vault balance on Execution Layer for the report reference slot + /// @param _sharesRequestedToBurn shares requested to burn for the report reference slot /// @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( @@ -377,6 +390,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { uint256 _postCLBalance, uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, + uint256 _sharesRequestedToBurn, uint256 _preCLValidators, uint256 _postCLValidators ) external view { @@ -390,13 +404,16 @@ contract OracleReportSanityChecker is AccessControlEnumerable { // 2. EL rewards vault reported balance _checkELRewardsVaultBalance(elRewardsVault.balance, _elRewardsVaultBalance); - // 3. Consensus Layer one-off balance decrease + // 3. Burn requests + _checkSharesRequestedToBurn(_sharesRequestedToBurn); + + // 4. Consensus Layer one-off balance decrease _checkOneOffCLBalanceDecrease(limitsList, _preCLBalance, _postCLBalance + _withdrawalVaultBalance); - // 4. Consensus Layer annual balances increase + // 5. Consensus Layer annual balances increase _checkAnnualBalancesIncrease(limitsList, _preCLBalance, _postCLBalance, _timeElapsed); - // 5. Appeared validators increase + // 6. Appeared validators increase if (_postCLValidators > _preCLValidators) { _checkValidatorsChurnLimit(limitsList, (_postCLValidators - _preCLValidators), _timeElapsed); } @@ -473,13 +490,13 @@ contract OracleReportSanityChecker is AccessControlEnumerable { /// @param _postTotalPooledEther total pooled ether after report applied /// @param _postTotalShares total shares after report applied /// @param _etherLockedOnWithdrawalQueue ether locked on withdrawal queue for the current oracle report - /// @param _sharesBurntFromWithdrawalQueue shares burnt from withdrawal queue for the current oracle report + /// @param _sharesBurntDueToWithdrawals shares burnt due to withdrawals finalization /// @param _simulatedShareRate share rate provided with the oracle report (simulated via off-chain "eth_call") function checkSimulatedShareRate( uint256 _postTotalPooledEther, uint256 _postTotalShares, uint256 _etherLockedOnWithdrawalQueue, - uint256 _sharesBurntFromWithdrawalQueue, + uint256 _sharesBurntDueToWithdrawals, uint256 _simulatedShareRate ) external view { LimitsList memory limitsList = _limits.unpack(); @@ -490,7 +507,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { _checkSimulatedShareRate( limitsList, _postTotalPooledEther + _etherLockedOnWithdrawalQueue, - _postTotalShares + _sharesBurntFromWithdrawalQueue, + _postTotalShares + _sharesBurntDueToWithdrawals, _simulatedShareRate ); } @@ -513,6 +530,14 @@ contract OracleReportSanityChecker is AccessControlEnumerable { } } + function _checkSharesRequestedToBurn(uint256 _sharesRequestedToBurn) internal view { + (uint256 coverShares, uint256 nonCoverShares) = IBurner(LIDO_LOCATOR.burner()).getSharesRequestedToBurn(); + uint256 actualBurnerRequests = coverShares + nonCoverShares; + if (_sharesRequestedToBurn > actualBurnerRequests) { + revert IncorrectBurnerRequests(actualBurnerRequests); + } + } + function _checkOneOffCLBalanceDecrease( LimitsList memory _limitsList, uint256 _preCLBalance, @@ -671,6 +696,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { error IncorrectLimitValue(uint256 value, uint256 maxAllowedValue); error IncorrectWithdrawalsVaultBalance(uint256 actualWithdrawalVaultBalance); error IncorrectELRewardsVaultBalance(uint256 actualELRewardsVaultBalance); + error IncorrectBurnerRequests(uint256 actualBurnerRequests); error IncorrectCLBalanceDecrease(uint256 oneOffCLBalanceDecreaseBP); error IncorrectCLBalanceIncrease(uint256 annualBalanceDiff); error IncorrectAppearedValidators(uint256 churnLimit); diff --git a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol index 8495b3de2..d3ef4f356 100644 --- a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol +++ b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol @@ -16,6 +16,7 @@ interface ILidoTemporary { // EL values uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, + uint256 _sharesRequestedToBurn, // decision uint256 _requestIdToFinalizeUpTo, uint256 _finalizationShareRate @@ -60,6 +61,7 @@ contract AccountingOracleMock { data.clBalanceGwei * 1e9, data.withdrawalVaultBalance, data.elRewardsVaultBalance, + data.sharesRequestedToBurn, data.lastFinalizableWithdrawalRequestId, data.simulatedShareRate ); diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index 195cdd32f..23d597ba2 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -41,8 +41,17 @@ contract WithdrawalQueueStub { } } +contract BurnerStub { + function getSharesRequestedToBurn() external view returns ( + uint256 coverShares, uint256 nonCoverShares + ) { + return (0, 0); + } +} + interface ILidoLocator { function lido() external view returns (address); + function burner() external view returns (address); function withdrawalVault() external view returns (address); function withdrawalQueue() external view returns (address); } @@ -52,17 +61,20 @@ contract LidoLocatorStub is ILidoLocator { address private immutable WITHDRAWAL_VAULT; address private immutable WITHDRAWAL_QUEUE; address private immutable EL_REWARDS_VAULT; + address private immutable BURNER; constructor( address _lido, address _withdrawalVault, address _withdrawalQueue, - address _elRewardsVault + address _elRewardsVault, + address _burner ) { LIDO = _lido; WITHDRAWAL_VAULT = _withdrawalVault; WITHDRAWAL_QUEUE = _withdrawalQueue; EL_REWARDS_VAULT = _elRewardsVault; + BURNER = _burner; } function lido() external view returns (address) { @@ -80,6 +92,10 @@ contract LidoLocatorStub is ILidoLocator { function elRewardsVault() external view returns (address) { return EL_REWARDS_VAULT; } + + function burner() external view returns (address) { + return BURNER; + } } contract OracleReportSanityCheckerStub { @@ -93,6 +109,7 @@ contract OracleReportSanityCheckerStub { uint256 _postCLBalance, uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, + uint256 _sharesRequestedToBurn, uint256 _preCLValidators, uint256 _postCLValidators ) external view {} @@ -107,7 +124,7 @@ contract OracleReportSanityCheckerStub { uint256 _postTotalPooledEther, uint256 _postTotalShares, uint256 _etherLockedOnWithdrawalQueue, - uint256 _sharesBurntFromWithdrawalQueue, + uint256 _sharesBurntDueToWithdrawals, uint256 _simulatedShareRate ) external view {} @@ -118,11 +135,20 @@ contract OracleReportSanityCheckerStub { uint256, uint256 _withdrawalVaultBalance, uint256 _elRewardsVaultBalance, - uint256 _etherToLockForWithdrawals - ) external view returns (uint256 withdrawals, uint256 elRewards, uint256 sharesToBurnLimit) { + uint256, + uint256 _etherToLockForWithdrawals, + uint256 + ) external view returns ( + uint256 withdrawals, + uint256 elRewards, + uint256 simulatedSharesToBurn, + uint256 sharesToBurn + ) { withdrawals = _withdrawalVaultBalance; elRewards = _elRewardsVaultBalance; - sharesToBurnLimit = _etherToLockForWithdrawals; + + simulatedSharesToBurn = 0; + sharesToBurn = _etherToLockForWithdrawals; } function checkAccountingExtraDataListItemsCount(uint256 _extraDataListItemsCount) external view {} diff --git a/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol b/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol index 0853b7518..b45af74c8 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol @@ -14,6 +14,7 @@ contract MockLidoForAccountingOracle is ILido { uint256 clBalance; uint256 withdrawalVaultBalance; uint256 elRewardsVaultBalance; + uint256 sharesRequestedToBurn; uint256 lastWithdrawalRequestIdToFinalize; uint256 finalizationShareRate; uint256 callCount; @@ -36,6 +37,7 @@ contract MockLidoForAccountingOracle is ILido { uint256 clBalance, uint256 withdrawalVaultBalance, uint256 elRewardsVaultBalance, + uint256 sharesRequestedToBurn, uint256 lastWithdrawalRequestIdToFinalize, uint256 finalizationShareRate ) external { @@ -45,6 +47,7 @@ contract MockLidoForAccountingOracle is ILido { _handleOracleReportLastCall.clBalance = clBalance; _handleOracleReportLastCall.withdrawalVaultBalance = withdrawalVaultBalance; _handleOracleReportLastCall.elRewardsVaultBalance = elRewardsVaultBalance; + _handleOracleReportLastCall.sharesRequestedToBurn = sharesRequestedToBurn; _handleOracleReportLastCall.lastWithdrawalRequestIdToFinalize = lastWithdrawalRequestIdToFinalize; _handleOracleReportLastCall.finalizationShareRate = finalizationShareRate; ++_handleOracleReportLastCall.callCount; diff --git a/contracts/common/interfaces/IBurner.sol b/contracts/common/interfaces/IBurner.sol index 0bd1ff5f8..1e565563a 100644 --- a/contracts/common/interfaces/IBurner.sol +++ b/contracts/common/interfaces/IBurner.sol @@ -11,7 +11,7 @@ interface IBurner { * * NB: The real burn enactment to be invoked after the call (via internal Lido._burnShares()) */ - function commitSharesToBurn(uint256 _stETHSharesToBurnLimit) external returns (uint256 stETHsharesToBurnNow); + function commitSharesToBurn(uint256 _stETHSharesToBurn) external; /** * Request burn shares @@ -21,9 +21,7 @@ interface IBurner { /** * Returns the current amount of shares locked on the contract to be burnt. */ - function getSharesRequestedToBurn() external view returns ( - uint256 coverShares, uint256 nonCoverShares - ); + function getSharesRequestedToBurn() external view returns (uint256 coverShares, uint256 nonCoverShares); /** * Returns the total cover shares ever burnt. diff --git a/lib/abi/AccountingOracle.json b/lib/abi/AccountingOracle.json index 6def379da..020eb6eab 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":"ExtraDataHashCannotBeZeroForNonEmptyData","type":"error"},{"inputs":[],"name":"ExtraDataItemsCountCannotBeZeroForNonEmptyData","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":[],"name":"RefSlotAlreadyProcessing","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":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedExtraDataHash","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_EMPTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"bool","name":"extraDataSubmitted","type":"bool"},{"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":[],"name":"submitReportExtraDataEmpty","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":"ExtraDataHashCannotBeZeroForNonEmptyData","type":"error"},{"inputs":[],"name":"ExtraDataItemsCountCannotBeZeroForNonEmptyData","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":[],"name":"RefSlotAlreadyProcessing","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":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedExtraDataHash","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_EMPTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"bool","name":"extraDataSubmitted","type":"bool"},{"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":"sharesRequestedToBurn","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":[],"name":"submitReportExtraDataEmpty","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/Burner.json b/lib/abi/Burner.json index 07cd2ab43..79487afc0 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":"AppAuthLidoFailed","type":"error"},{"inputs":[],"name":"DirectETHTransfer","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 +[{"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":[{"internalType":"uint256","name":"requestedAmount","type":"uint256"},{"internalType":"uint256","name":"actualAmount","type":"uint256"}],"name":"BurnAmountExceedsActual","type":"error"},{"inputs":[],"name":"DirectETHTransfer","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":"_sharesToBurn","type":"uint256"}],"name":"commitSharesToBurn","outputs":[],"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/ILido.json b/lib/abi/ILido.json index e79a4bf07..fd3694036 100644 --- a/lib/abi/ILido.json +++ b/lib/abi/ILido.json @@ -1 +1 @@ -[{"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 +[{"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":"_sharesRequestedToBurn","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 58ee3388a..6585318ab 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":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":true,"stateMutability":"payable","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":"eip712Domain","outputs":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","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":true,"inputs":[],"name":"getEIP712StETH","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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":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":"getDepositableEther","outputs":[{"name":"","type":"uint256"}],"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":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":true,"stateMutability":"payable","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":"eip712Domain","outputs":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","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":true,"inputs":[],"name":"getEIP712StETH","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","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":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":"_sharesRequestedToBurn","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":true,"inputs":[],"name":"getDepositableEther","outputs":[{"name":"","type":"uint256"}],"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":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 17a81a848..a824c32f6 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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"actualBurnerRequests","type":"uint256"}],"name":"IncorrectBurnerRequests","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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 e27cad4937ef2db08d79145cfdb43c8c248ebef1 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Fri, 24 Feb 2023 17:47:41 +0300 Subject: [PATCH 027/236] test: adopt burner's balance reporting --- test/0.4.24/lido-handle-oracle-report.test.js | 80 +++++++++---------- test/0.4.24/lido.test.js | 4 +- test/0.8.9/burner.test.js | 59 +++++++++++--- .../oracle-report-sanity-checker.test.js | 5 +- .../accounting-oracle-access-control.test.js | 1 + .../oracle/accounting-oracle-deploy.test.js | 3 +- .../accounting-oracle-happy-path.test.js | 1 + ...counting-oracle-submit-report-data.test.js | 1 + ...ng-oracle-submit-report-extra-data.test.js | 1 + test/helpers/oracle.js | 4 +- .../scenario/changing_oracles_during_epoch.js | 1 + 11 files changed, 106 insertions(+), 54 deletions(-) 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 602e4341a..dd4feb85f 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -210,16 +210,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another } it('handleOracleReport access control', async () => { - await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'APP_AUTH_FAILED') + await assert.reverts(lido.handleOracleReport(0, 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') + await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'CONTRACT_IS_STOPPED') }) it('zero report should do nothing', async () => { - const tx = await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -263,7 +263,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit without rewards', async () => { - const tx = await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -293,7 +293,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit with rewards', async () => { - const tx = await lido.handleOracleReport(0, ONE_YEAR, 1, ETH(33), 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, ONE_YEAR, 1, ETH(33), 0, 0, 0, 0, 0, { from: oracle }) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) await checkEvents({ tx, @@ -331,34 +331,34 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('reverts on reported more than deposited', async () => { - await assert.reverts(lido.handleOracleReport(0, 0, 4, 0, 0, 0, 0, 0, { from: oracle }), 'REPORTED_MORE_DEPOSITED') + await assert.reverts(lido.handleOracleReport(0, 0, 4, 0, 0, 0, 0, 0, 0, { from: oracle }), 'REPORTED_MORE_DEPOSITED') }) it('reverts on reported less than reported previously', async () => { - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await assert.reverts( - lido.handleOracleReport(0, 0, 2, 0, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, 0, 2, 0, 0, 0, 0, 0, 0, { from: oracle }), 'REPORTED_LESS_VALIDATORS' ) }) it('withdrawal vault balance check', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, 0, { from: oracle }), 'IncorrectWithdrawalsVaultBalance(0)' ) }) it('withdrawal vault balance check 2', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, 0, { from: oracle }), 'IncorrectWithdrawalsVaultBalance(0)' ) }) it('does not revert on new total balance stay the same', async () => { - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) + let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -384,7 +384,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0 }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) + tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 3, @@ -419,7 +419,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) + let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -445,7 +445,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0 }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, 0, { from: oracle }) + tx = await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 3, @@ -481,7 +481,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -492,7 +492,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0 }) await assert.reverts( - lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, 0, 0, { from: oracle }), 'IncorrectCLBalanceDecrease(101)' ) }) @@ -506,7 +506,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -516,7 +516,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0 }) - const tx = await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0, 0, { from: oracle }) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.96), 10, 100, ETH(100), ETH(100.96)) await checkEvents({ tx, @@ -555,7 +555,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -566,7 +566,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0 }) await assert.reverts( - lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0, 0, { from: oracle }), 'IncorrectCLBalanceIncrease(101)' ) }) @@ -582,7 +582,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 100, ETH(3200), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 100, ETH(3200), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 100, beaconValidators: 100, beaconBalance: ETH(3200) }) }) @@ -597,7 +597,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) await assert.reverts( - lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }), + lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }), 'IncorrectAppearedValidators(101)' ) }) @@ -624,7 +624,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(97) }) }) @@ -635,7 +635,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(100), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(100), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(100) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(4), @@ -657,7 +657,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -680,7 +680,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1.1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -704,7 +704,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1), 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -729,7 +729,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { 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 lido.handleOracleReport(0, ONE_YEAR, 3, ETH(95.5), 0, ETH(1.5), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.5) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -753,7 +753,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1.1), 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -776,7 +776,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { 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 lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(0.9), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ @@ -801,7 +801,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { 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 lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -838,7 +838,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(1.1), 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -858,7 +858,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.0027), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.0027), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.0027) }) }) @@ -870,7 +870,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96 + 0.0028), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96 + 0.0028), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96 + clIncrease) }) assert( 0.00014 + 0.0028 * 0.9 * 0.3 + 0.0028 * 0.9 * 0.69 + 0.0028 * 0.01 * 0.9 + 0.00014 === clIncrease, @@ -896,7 +896,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -919,7 +919,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1.1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -943,7 +943,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1), 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -968,7 +968,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(95.5), 0, ETH(1.5), 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(95.5), 0, ETH(1.5), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.5) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -992,7 +992,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1.1), 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -1015,7 +1015,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(0.9), 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(0.9), 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index be070bce2..d4a14b516 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -967,14 +967,14 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await checkStat({ depositedValidators: 1, beaconValidators: 0, beaconBalance: ETH(0) }) await assertRevert( - app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(30), 0, 0, 0, 0, 0, { from: appManager }), + app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(30), 0, 0, 0, 0, 0, 0, { from: appManager }), 'APP_AUTH_FAILED' ) await pushReport(1, ETH(30)) await checkStat({ depositedValidators: 1, beaconValidators: 1, beaconBalance: ETH(30) }) - await assertRevert(app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(29), 0, 0, 0, 0, 0, { from: nobody }), 'APP_AUTH_FAILED') + await assertRevert(app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(29), 0, 0, 0, 0, 0, 0, { from: nobody }), 'APP_AUTH_FAILED') await pushReport(1, ETH(100)) // stale data await checkStat({ depositedValidators: 1, beaconValidators: 1, beaconBalance: ETH(100) }) diff --git a/test/0.8.9/burner.test.js b/test/0.8.9/burner.test.js index 14da006d8..6c3be4c1f 100644 --- a/test/0.8.9/burner.test.js +++ b/test/0.8.9/burner.test.js @@ -143,6 +143,44 @@ contract('Burner', ([deployer, _, anotherAccount]) => { assert.equals(await lido.balanceOf(deployer), StETH(22)) }) + it(`reverts on attempt to burn more then requested`, async () => { + // provide allowance and request burn for cover + const sharesAmount8StETH = await lido.getSharesByPooledEth(StETH(8)) + await lido.approve(burner.address, StETH(8), { from: voting }) + let receipt = await burner.requestBurnMyStETHForCover(StETH(8), { from: voting }) + + assert.emits(receipt, `StETHBurnRequested`, { + isCover: true, + requestedBy: voting, + amountOfStETH: StETH(8), + amountOfShares: sharesAmount8StETH + }) + + // check stETH balances + assert.equals(await lido.balanceOf(burner.address), StETH(8)) + assert.equals(await lido.balanceOf(voting), StETH(16)) + + const sharesAmount12 = sharesAmount8StETH.mul(bn(3)).div(bn(2)) + await lido.approve(burner.address, StETH(13), { from: voting }) + receipt = await burner.requestBurnMyStETH(StETH(12), { from: voting }) + + assert.emits(receipt, `StETHBurnRequested`, { + isCover: false, + requestedBy: voting, + amountOfStETH: StETH(12), + amountOfShares: sharesAmount12 + }) + + // check stETH balances again, we didn't execute the actual burn + assert.equals(await lido.balanceOf(burner.address), StETH(20)) + assert.equals(await lido.balanceOf(voting), StETH(4)) + + await assert.revertsWithCustomError( + burner.commitSharesToBurn(StETH(100), { from: lido.address }), + `BurnAmountExceedsActual(${StETH(100)}, ${StETH(20)})` + ) + }) + it(`request shares burn for cover works`, async () => { // allowance should be set explicitly to request burning await assert.reverts( @@ -195,7 +233,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { ) // mimic the Lido for the callback invocation - const receipt = await burner.commitSharesToBurn(ETH(10), { from: lido.address }) + const receipt = await burner.commitSharesToBurn(ETH(0), { from: lido.address }) // no burn requests => zero events assert.emitsNumberOfEvents(receipt, `StETHBurnt`, 0) @@ -229,7 +267,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { `AppAuthLidoFailed()` ) - const receipt = await burner.commitSharesToBurn(ETH(10), { from: lido.address }) + const receipt = await burner.commitSharesToBurn(ETH(6), { from: lido.address }) assert.emits(receipt, `StETHBurnt`, { isCover: false, amountOfStETH: StETH(6), amountOfShares: sharesToBurn }) @@ -284,7 +322,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { `AppAuthLidoFailed()` ) - const receipt = await burner.commitSharesToBurn(ETH(3), { from: lido.address }) + const receipt = await burner.commitSharesToBurn(ETH(2), { from: lido.address }) assert.emits(receipt, `StETHBurnt`, { isCover: true, amountOfStETH: StETH(1.5), amountOfShares: sharesAmount1_5StETH @@ -333,7 +371,8 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await burner.requestBurnMyStETHForCover(coverStETHAmountToBurn, { from: voting }) await burner.requestBurnMyStETH(nonCoverStETHAmountToBurn, { from: voting }) - await burner.commitSharesToBurn(ETH(1), { from: lido.address }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + await burner.commitSharesToBurn(coverShares.add(nonCoverShares), { from: lido.address }) // accumulate burnt shares expectedCoverSharesBurnt = expectedCoverSharesBurnt.add(currentCoverSharesAmount) @@ -354,7 +393,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { assert.equals(await lido.balanceOf(anotherAccount), StETH(20)) assert.equals(await lido.balanceOf(deployer), StETH(30)) - await burner.commitSharesToBurn(ETH(50), { from: lido.address }) + await burner.commitSharesToBurn(ETH(24), { from: lido.address }) await lido.burnShares(burner.address, await lido.getPooledEthByShares(StETH(24))) @@ -377,7 +416,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await burner.requestBurnMyStETHForCover(StETH(0.9), { from: voting }) assert.equals(await lido.sharesOf(burner.address), stETHShares(0.9)) - const receipt = await burner.commitSharesToBurn(StETH(100), { from: lido.address }) + const receipt = await burner.commitSharesToBurn(StETH(0.9), { from: lido.address }) assert.emits( receipt, `StETHBurnt`, { @@ -391,7 +430,9 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await burner.requestBurnMyStETHForCover(await lido.getPooledEthByShares(stETHShares(0.1)), { from: voting }) assert.equals(bnRound10(await lido.sharesOf(burner.address)), bnRound10(stETHShares(0.1))) - await burner.commitSharesToBurn(ETH(1), { from: lido.address }) + + let {coverShares, nonCoverShares} = await burner.getSharesRequestedToBurn() + await burner.commitSharesToBurn(coverShares.add(nonCoverShares), { from: lido.address }) await lido.burnShares(burner.address, await lido.sharesOf(burner.address)) assert.equals(await lido.sharesOf(burner.address), stETHShares(0)) @@ -473,7 +514,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { assert.equals(await burner.getCoverSharesBurnt(), stETHShares(0.1)) assert.equals(await burner.getNonCoverSharesBurnt(), stETHShares(0.4)) - const receipt2 = await burner.commitSharesToBurn(ETH(0.5), { from: lido.address }) + const receipt2 = await burner.commitSharesToBurn(ETH(0.4), { from: lido.address }) assert.emits(receipt2, `StETHBurnt`, { isCover: false, amountOfStETH: StETH(0.4), amountOfShares: stETHShares(0.4) }) @@ -501,7 +542,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { assert.equals(await burner.getCoverSharesBurnt(), stETHShares(0.1)) assert.equals(await burner.getNonCoverSharesBurnt(), stETHShares(0.4)) - const receipt2 = await burner.commitSharesToBurn(ETH(0.5), { from: lido.address }) + const receipt2 = await burner.commitSharesToBurn(ETH(0.4), { from: lido.address }) assert.emits(receipt2, `StETHBurnt`, { isCover: false, amountOfStETH: StETH(0.4), amountOfShares: stETHShares(0.4) }) 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 c464de2f9..6e3fe0112 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -8,6 +8,7 @@ const LidoStub = hre.artifacts.require(`${mocksFilePath}:LidoStub`) const OracleReportSanityChecker = hre.artifacts.require('OracleReportSanityChecker') const LidoLocatorStub = hre.artifacts.require(`${mocksFilePath}:LidoLocatorStub`) const WithdrawalQueueStub = hre.artifacts.require(`${mocksFilePath}:WithdrawalQueueStub`) +const BurnerStub = hre.artifacts.require(`${mocksFilePath}:BurnerStub`) function wei(number, units = 'wei') { switch (units.toLowerCase()) { @@ -51,6 +52,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa postCLBalance: ETH(100_001), withdrawalVaultBalance: 0, elRewardsVaultBalance: 0, + sharesRequestedToBurn: 0, preCLValidators: 0, postCLValidators: 0, } @@ -60,8 +62,9 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa 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 }) + burnerMock = await BurnerStub.new({ from: deployer }) lidoLocatorMock = await LidoLocatorStub.new( - lidoMock.address, withdrawalVault, withdrawalQueueMock.address, elRewardsVault, + lidoMock.address, withdrawalVault, withdrawalQueueMock.address, elRewardsVault, burnerMock.address, { from: deployer } ) diff --git a/test/0.8.9/oracle/accounting-oracle-access-control.test.js b/test/0.8.9/oracle/accounting-oracle-access-control.test.js index adb8f9ae5..519662633 100644 --- a/test/0.8.9/oracle/accounting-oracle-access-control.test.js +++ b/test/0.8.9/oracle/accounting-oracle-access-control.test.js @@ -53,6 +53,7 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra numExitedValidatorsByStakingModule: [3], withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), + sharesRequestedToBurn: e18(3), lastWithdrawalRequestIdToFinalize: 1, finalizationShareRate: e27(1), isBunkerMode: true, diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index 6bd5abb21..daf2a2da0 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -56,6 +56,7 @@ function getReportDataItems(r) { r.numExitedValidatorsByStakingModule, r.withdrawalVaultBalance, r.elRewardsVaultBalance, + r.sharesRequestedToBurn, r.lastWithdrawalRequestIdToFinalize, r.finalizationShareRate, r.isBunkerMode, @@ -68,7 +69,7 @@ function getReportDataItems(r) { function calcReportDataHash(reportItems) { const data = web3.eth.abi.encodeParameters( [ - '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)' + '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)' ], [reportItems] ) diff --git a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js index d76ed1733..68c6dc145 100644 --- a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js +++ b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js @@ -123,6 +123,7 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { numExitedValidatorsByStakingModule: [3], withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), + sharesRequestedToBurn: e18(3), lastWithdrawalRequestIdToFinalize: 1, finalizationShareRate: e27(1), isBunkerMode: true, diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js index fe272762a..a6dc22d41 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js @@ -45,6 +45,7 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra numExitedValidatorsByStakingModule: [3], withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), + sharesRequestedToBurn: e18(3), lastWithdrawalRequestIdToFinalize: 1, finalizationShareRate: e27(1), isBunkerMode: true, diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js index f1f9a3c71..a4a8b57b4 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js @@ -36,6 +36,7 @@ const getDefaultReportFields = (overrides) => ({ numExitedValidatorsByStakingModule: [3], withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), + sharesRequestedToBurn: e18(3), lastWithdrawalRequestIdToFinalize: 1, finalizationShareRate: e27(1), isBunkerMode: true, diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index 704abed4a..97035f57a 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -11,6 +11,7 @@ function getReportDataItems(r) { r.numExitedValidatorsByStakingModule, r.withdrawalVaultBalance, r.elRewardsVaultBalance, + r.requestedToBurnShares, r.lastWithdrawalRequestIdToFinalize, r.finalizationShareRate, r.isBunkerMode, @@ -23,7 +24,7 @@ function getReportDataItems(r) { function calcReportDataHash(reportItems) { const data = web3.eth.abi.encodeParameters( [ - '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)' + '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)' ], [reportItems] ) @@ -50,6 +51,7 @@ async function pushOracleReport(consensus, oracle, numValidators, clBalance, elR numExitedValidatorsByStakingModule: [], withdrawalVaultBalance: 0, elRewardsVaultBalance: elRewards || 0, + requestedToBurnShares: 0, lastWithdrawalRequestIdToFinalize: 0, finalizationShareRate: 0, isBunkerMode: false, diff --git a/test/scenario/changing_oracles_during_epoch.js b/test/scenario/changing_oracles_during_epoch.js index 53d8495be..da38197b0 100644 --- a/test/scenario/changing_oracles_during_epoch.js +++ b/test/scenario/changing_oracles_during_epoch.js @@ -35,6 +35,7 @@ contract('AccountingOracle', ([appManager, voting, malicious1, malicious2, membe numExitedValidatorsByStakingModule: [], withdrawalVaultBalance: 0, elRewardsVaultBalance: 0, + sharesRequestedToBurn: 0, lastWithdrawalRequestIdToFinalize: 0, finalizationShareRate: 0, isBunkerMode: false, From bfe55861001e05ba580c0b97da325b129f1792d2 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Fri, 24 Feb 2023 19:48:01 +0300 Subject: [PATCH 028/236] fix: review fixes --- contracts/0.8.9/Burner.sol | 2 +- contracts/0.8.9/oracle/AccountingOracle.sol | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/Burner.sol b/contracts/0.8.9/Burner.sol index b40b88d28..82b9faf43 100644 --- a/contracts/0.8.9/Burner.sol +++ b/contracts/0.8.9/Burner.sol @@ -311,7 +311,7 @@ contract Burner is IBurner, AccessControlEnumerable { coverSharesBurnRequested -= sharesToBurnNowForCover; sharesToBurnNow += sharesToBurnNowForCover; } - if ((memNonCoverSharesBurnRequested > 0) && (sharesToBurnNow < _sharesToBurn)) { + if (memNonCoverSharesBurnRequested > 0 && sharesToBurnNow < _sharesToBurn) { uint256 sharesToBurnNowForNonCover = Math.min( _sharesToBurn - sharesToBurnNow, memNonCoverSharesBurnRequested diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index b3c41a076..f16269397 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -234,7 +234,9 @@ contract AccountingOracle is BaseOracle { uint256 elRewardsVaultBalance; /// @dev The shares amount requested to burn through Burner as observed - /// at the reference slot. + /// at the reference slot. The value can be obtained in the following way: + /// `(coverSharesToBurn, nonCoverSharesToBurn) = IBurner(burner).getSharesRequestedToBurn() + /// sharesRequestedToBurn = coverSharesToBurn + nonCoverSharesToBurn` uint256 sharesRequestedToBurn; /// From 07db1697dc898c33b7617a4c75bc2ef5eb954964 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Fri, 24 Feb 2023 20:40:36 +0200 Subject: [PATCH 029/236] accounting oracle: pass array of finalization batches instead of a single req id --- contracts/0.8.9/oracle/AccountingOracle.sol | 18 ++++----- .../test_helpers/AccountingOracleMock.sol | 37 ++----------------- .../oracle/MockLidoForAccountingOracle.sol | 12 +++--- .../accounting-oracle-access-control.test.js | 4 +- .../oracle/accounting-oracle-deploy.test.js | 8 ++-- .../accounting-oracle-happy-path.test.js | 14 +++---- ...counting-oracle-submit-report-data.test.js | 14 +++---- ...ng-oracle-submit-report-extra-data.test.js | 4 +- test/helpers/oracle.js | 10 ++--- .../changing_oracles_during_epoch.test.js | 4 +- ...tion_layer_rewards_after_the_merge.test.js | 4 +- 11 files changed, 51 insertions(+), 78 deletions(-) diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index f16269397..f1d8478dd 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -23,7 +23,7 @@ interface ILido { uint256 _elRewardsVaultBalance, uint256 _sharesRequestedToBurn, // Decision about withdrawals processing - uint256 _lastFinalizableRequestId, + uint256[] calldata _withdrawalFinalizationBatches, uint256 _simulatedShareRate ) external; } @@ -243,15 +243,15 @@ contract AccountingOracle is BaseOracle { /// Decision /// - /// @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 lastFinalizableWithdrawalRequestId; + /// @dev The ascendingly-sorted array of withdrawal request IDs obtained by calling + /// WithdrawalQueue.calculateFinalizationBatches. Empty array means that no withdrawal + /// requests should be finalized. + uint256[] withdrawalFinalizationBatches; /// @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. + /// in ETH where one ETH is denominated as 10^27) that would be effective as the result of + /// applying this oracle report at the reference slot, with withdrawalFinalizationBatches + /// set to empty array and simulatedShareRate set to 0. uint256 simulatedShareRate; /// @dev Whether, based on the state observed at the reference slot, the protocol should @@ -618,7 +618,7 @@ contract AccountingOracle is BaseOracle { data.withdrawalVaultBalance, data.elRewardsVaultBalance, data.sharesRequestedToBurn, - data.lastFinalizableWithdrawalRequestId, + data.withdrawalFinalizationBatches, data.simulatedShareRate ); diff --git a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol index d3ef4f356..e50c43872 100644 --- a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol +++ b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol @@ -7,23 +7,6 @@ pragma solidity 0.8.9; import {AccountingOracle, ILido} from "../oracle/AccountingOracle.sol"; -// TODO: remove and use ILido -interface ILidoTemporary { - function handleOracleReport( - // CL values - uint256 _clValidators, - uint256 _clBalance, - // EL values - uint256 _withdrawalVaultBalance, - uint256 _elRewardsVaultBalance, - uint256 _sharesRequestedToBurn, - // decision - uint256 _requestIdToFinalizeUpTo, - uint256 _finalizationShareRate - ) external returns (uint256, uint256); -} - - contract AccountingOracleMock { address public immutable LIDO; uint256 public immutable SECONDS_PER_SLOT; @@ -39,30 +22,18 @@ contract AccountingOracleMock { AccountingOracle.ReportData calldata data, uint256 /* contractVersion */ ) external { - // TODO: remove the line below - // solhint-disable-next-line uint256 slotsElapsed = data.refSlot - _lastRefSlot; _lastRefSlot = data.refSlot; - // TODO: update to use the actual signature - // ILido(LIDO).handleOracleReport( - // slotsElapsed * SECONDS_PER_SLOT, - // data.numValidators, - // data.clBalanceGwei * 1e9, - // data.withdrawalVaultBalance, - // data.elRewardsVaultBalance, - // data.lastFinalizableWithdrawalRequestId, - // data.simulatedShareRate, - // data.isBunkerMode - // ); - - ILidoTemporary(LIDO).handleOracleReport( + ILido(LIDO).handleOracleReport( + data.refSlot * SECONDS_PER_SLOT, + slotsElapsed * SECONDS_PER_SLOT, data.numValidators, data.clBalanceGwei * 1e9, data.withdrawalVaultBalance, data.elRewardsVaultBalance, data.sharesRequestedToBurn, - data.lastFinalizableWithdrawalRequestId, + data.withdrawalFinalizationBatches, data.simulatedShareRate ); } diff --git a/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol b/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol index b45af74c8..c8e2117e9 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockLidoForAccountingOracle.sol @@ -15,8 +15,8 @@ contract MockLidoForAccountingOracle is ILido { uint256 withdrawalVaultBalance; uint256 elRewardsVaultBalance; uint256 sharesRequestedToBurn; - uint256 lastWithdrawalRequestIdToFinalize; - uint256 finalizationShareRate; + uint256[] withdrawalFinalizationBatches; + uint256 simulatedShareRate; uint256 callCount; } @@ -38,8 +38,8 @@ contract MockLidoForAccountingOracle is ILido { uint256 withdrawalVaultBalance, uint256 elRewardsVaultBalance, uint256 sharesRequestedToBurn, - uint256 lastWithdrawalRequestIdToFinalize, - uint256 finalizationShareRate + uint256[] calldata withdrawalFinalizationBatches, + uint256 simulatedShareRate ) external { _handleOracleReportLastCall.currentReportTimestamp = currentReportTimestamp; _handleOracleReportLastCall.secondsElapsedSinceLastReport = secondsElapsedSinceLastReport; @@ -48,8 +48,8 @@ contract MockLidoForAccountingOracle is ILido { _handleOracleReportLastCall.withdrawalVaultBalance = withdrawalVaultBalance; _handleOracleReportLastCall.elRewardsVaultBalance = elRewardsVaultBalance; _handleOracleReportLastCall.sharesRequestedToBurn = sharesRequestedToBurn; - _handleOracleReportLastCall.lastWithdrawalRequestIdToFinalize = lastWithdrawalRequestIdToFinalize; - _handleOracleReportLastCall.finalizationShareRate = finalizationShareRate; + _handleOracleReportLastCall.withdrawalFinalizationBatches = withdrawalFinalizationBatches; + _handleOracleReportLastCall.simulatedShareRate = simulatedShareRate; ++_handleOracleReportLastCall.callCount; } } diff --git a/test/0.8.9/oracle/accounting-oracle-access-control.test.js b/test/0.8.9/oracle/accounting-oracle-access-control.test.js index ac30fca1a..e50690bbf 100644 --- a/test/0.8.9/oracle/accounting-oracle-access-control.test.js +++ b/test/0.8.9/oracle/accounting-oracle-access-control.test.js @@ -55,8 +55,8 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), sharesRequestedToBurn: e18(3), - lastWithdrawalRequestIdToFinalize: 1, - finalizationShareRate: e27(1), + withdrawalFinalizationBatches: [1], + simulatedShareRate: e27(1), isBunkerMode: true, extraDataFormat: emptyExtraData ? EXTRA_DATA_FORMAT_EMPTY : EXTRA_DATA_FORMAT_LIST, extraDataHash: emptyExtraData ? ZERO_HASH : extraDataHash, diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index e3f976788..b9247a007 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -57,8 +57,8 @@ function getReportDataItems(r) { r.withdrawalVaultBalance, r.elRewardsVaultBalance, r.sharesRequestedToBurn, - r.lastWithdrawalRequestIdToFinalize, - r.finalizationShareRate, + r.withdrawalFinalizationBatches, + r.simulatedShareRate, r.isBunkerMode, r.extraDataFormat, r.extraDataHash, @@ -69,7 +69,7 @@ function getReportDataItems(r) { function calcReportDataHash(reportItems) { const data = web3.eth.abi.encodeParameters( [ - '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)', + '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256[],uint256,bool,uint256,bytes32,uint256)', ], [reportItems] ) @@ -100,6 +100,7 @@ function packExtraDataList(extraDataItems) { function calcExtraDataListHash(packedExtraDataList) { return web3.utils.keccak256(packedExtraDataList) } + async function deployOracleReportSanityCheckerForAccounting(lidoLocator, admin) { const churnValidatorsPerDayLimit = 100 const limitsList = [churnValidatorsPerDayLimit, 0, 0, 0, 32 * 12, 15, 16, 0, 0] @@ -158,6 +159,7 @@ module.exports = { packExtraDataList, calcExtraDataListHash, } + async function deployMockLegacyOracle({ epochsPerFrame = EPOCHS_PER_FRAME, slotsPerEpoch = SLOTS_PER_EPOCH, diff --git a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js index f1294d893..b3a0b3cf6 100644 --- a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js +++ b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js @@ -1,6 +1,6 @@ const { contract } = require('hardhat') const { assert } = require('../../helpers/assert') -const { e9, e18, e27, hex } = require('../../helpers/utils') +const { e9, e18, e27, hex, toNum } = require('../../helpers/utils') const { SECONDS_PER_SLOT, @@ -120,8 +120,8 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), sharesRequestedToBurn: e18(3), - lastWithdrawalRequestIdToFinalize: 1, - finalizationShareRate: e27(1), + withdrawalFinalizationBatches: [1], + simulatedShareRate: e27(1), isBunkerMode: true, extraDataFormat: EXTRA_DATA_FORMAT_LIST, extraDataHash, @@ -219,11 +219,11 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { assert.equals(lastOracleReportCall.clBalance, e9(reportFields.clBalanceGwei)) assert.equals(lastOracleReportCall.withdrawalVaultBalance, reportFields.withdrawalVaultBalance) assert.equals(lastOracleReportCall.elRewardsVaultBalance, reportFields.elRewardsVaultBalance) - assert.equals( - lastOracleReportCall.lastWithdrawalRequestIdToFinalize, - reportFields.lastWithdrawalRequestIdToFinalize + assert.sameOrderedMembers( + toNum(lastOracleReportCall.withdrawalFinalizationBatches), + toNum(reportFields.withdrawalFinalizationBatches) ) - assert.equals(lastOracleReportCall.finalizationShareRate, reportFields.finalizationShareRate) + assert.equals(lastOracleReportCall.simulatedShareRate, reportFields.simulatedShareRate) }) it(`withdrawal queue got bunker mode report`, async () => { diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js index 2f62861a5..f5ce518de 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js @@ -1,6 +1,6 @@ const { contract, web3 } = require('hardhat') const { assert } = require('../../helpers/assert') -const { e9, e18, e27 } = require('../../helpers/utils') +const { e9, e18, e27, toNum } = require('../../helpers/utils') const AccountingOracleAbi = require('../../../lib/abi/AccountingOracle.json') @@ -47,8 +47,8 @@ contract('AccountingOracle', ([admin, member1]) => { withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), sharesRequestedToBurn: e18(3), - lastWithdrawalRequestIdToFinalize: 1, - finalizationShareRate: e27(1), + withdrawalFinalizationBatches: [1], + simulatedShareRate: e27(1), isBunkerMode: true, extraDataFormat: EXTRA_DATA_FORMAT_LIST, extraDataHash, @@ -439,11 +439,11 @@ contract('AccountingOracle', ([admin, member1]) => { assert.equals(lastOracleReportToLido.clBalance, reportFields.clBalanceGwei + '000000000') assert.equals(lastOracleReportToLido.withdrawalVaultBalance, reportFields.withdrawalVaultBalance) assert.equals(lastOracleReportToLido.elRewardsVaultBalance, reportFields.elRewardsVaultBalance) - assert.equals( - lastOracleReportToLido.lastWithdrawalRequestIdToFinalize, - reportFields.lastWithdrawalRequestIdToFinalize + assert.sameOrderedMembers( + toNum(lastOracleReportToLido.withdrawalFinalizationBatches), + toNum(reportFields.withdrawalFinalizationBatches) ) - assert.equals(lastOracleReportToLido.finalizationShareRate, reportFields.finalizationShareRate) + assert.equals(lastOracleReportToLido.simulatedShareRate, reportFields.simulatedShareRate) }) it('should call updateExitedValidatorsCountByStakingModule on StakingRouter', async () => { diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js index e0cf6f254..998e36e0f 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js @@ -38,8 +38,8 @@ const getDefaultReportFields = (overrides) => ({ withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), sharesRequestedToBurn: e18(3), - lastWithdrawalRequestIdToFinalize: 1, - finalizationShareRate: e27(1), + withdrawalFinalizationBatches: [1], + simulatedShareRate: e27(1), isBunkerMode: true, extraDataFormat: EXTRA_DATA_FORMAT_LIST, // required override: refSlot, diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index dbdb52598..dbf434c87 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -14,8 +14,8 @@ function getReportDataItems(r) { r.withdrawalVaultBalance, r.elRewardsVaultBalance, r.requestedToBurnShares, - r.lastWithdrawalRequestIdToFinalize, - r.finalizationShareRate, + r.withdrawalFinalizationBatches, + r.simulatedShareRate, r.isBunkerMode, r.extraDataFormat, r.extraDataHash, @@ -26,7 +26,7 @@ function getReportDataItems(r) { function calcReportDataHash(reportItems) { const data = web3.eth.abi.encodeParameters( [ - '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)', + '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256[],uint256,bool,uint256,bytes32,uint256)', ], [reportItems] ) @@ -54,8 +54,8 @@ async function pushOracleReport(consensus, oracle, numValidators, clBalance, elR withdrawalVaultBalance: 0, elRewardsVaultBalance: elRewards || 0, requestedToBurnShares: 0, - lastWithdrawalRequestIdToFinalize: 0, - finalizationShareRate: 0, + withdrawalFinalizationBatches: [], + simulatedShareRate: 0, isBunkerMode: false, extraDataFormat: 0, extraDataHash: ZERO_BYTES32, diff --git a/test/scenario/changing_oracles_during_epoch.test.js b/test/scenario/changing_oracles_during_epoch.test.js index 88b8347b3..83398a073 100644 --- a/test/scenario/changing_oracles_during_epoch.test.js +++ b/test/scenario/changing_oracles_during_epoch.test.js @@ -34,8 +34,8 @@ contract('AccountingOracle', ([voting, malicious1, malicious2, member1, member2, withdrawalVaultBalance: 0, elRewardsVaultBalance: 0, sharesRequestedToBurn: 0, - lastWithdrawalRequestIdToFinalize: 0, - finalizationShareRate: 0, + withdrawalFinalizationBatches: [], + simulatedShareRate: 0, isBunkerMode: false, extraDataFormat: 0, extraDataHash: ZERO_HASH, diff --git a/test/scenario/execution_layer_rewards_after_the_merge.test.js b/test/scenario/execution_layer_rewards_after_the_merge.test.js index 951372ef2..2ea2726d7 100644 --- a/test/scenario/execution_layer_rewards_after_the_merge.test.js +++ b/test/scenario/execution_layer_rewards_after_the_merge.test.js @@ -25,8 +25,8 @@ const makeAccountingReport = ({ refSlot, numValidators, clBalanceGwei, elRewards numExitedValidatorsByStakingModule: [], withdrawalVaultBalance: 0, elRewardsVaultBalance, - lastWithdrawalRequestIdToFinalize: 0, - finalizationShareRate: 0, + withdrawalFinalizationBatches: [], + simulatedShareRate: 0, isBunkerMode: false, extraDataFormat: 0, extraDataHash: ZERO_HASH, From 9c03b32d56762e6f174018e8c174739e56e043c0 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Sat, 25 Feb 2023 15:33:03 +0300 Subject: [PATCH 030/236] test: add ACL tests for Burner --- test/0.8.9/burner.test.js | 108 +++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/test/0.8.9/burner.test.js b/test/0.8.9/burner.test.js index 3f1f72479..70d1969d5 100644 --- a/test/0.8.9/burner.test.js +++ b/test/0.8.9/burner.test.js @@ -40,6 +40,112 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await snapshot.rollback() }) + describe('Burner ACL correctness', () => { + it(`REQUEST_BURN_MY_STETH_ROLE works`, async () => { + await web3.eth.sendTransaction({ from: anotherAccount, to: lido.address, value: ETH(2) }) + await lido.approve(burner.address, StETH(2), { from: anotherAccount }) + + assert.isFalse(await burner.hasRole(await burner.REQUEST_BURN_MY_STETH_ROLE(), anotherAccount)) + + await assert.revertsOZAccessControl( + burner.requestBurnMyStETH(StETH(1), { from: anotherAccount }), + anotherAccount, + `REQUEST_BURN_MY_STETH_ROLE` + ) + + await assert.revertsOZAccessControl( + burner.requestBurnMyStETHForCover(StETH(1), { from: anotherAccount }), + anotherAccount, + `REQUEST_BURN_MY_STETH_ROLE` + ) + + await burner.grantRole(await burner.REQUEST_BURN_MY_STETH_ROLE(), anotherAccount, { from: appManager }) + assert.isTrue(await burner.hasRole(await burner.REQUEST_BURN_MY_STETH_ROLE(), anotherAccount)) + + await burner.requestBurnMyStETH(StETH(1), { from: anotherAccount }) + await burner.requestBurnMyStETHForCover(StETH(1), { from: anotherAccount }) + }) + + it(`RECOVER_ASSETS_ROLE works`, async () => { + const nft1 = bn(666) + const totalERC20Supply = bn(1000000) + const mockERC20Token = await ERC20OZMock.new(totalERC20Supply, { from: deployer }) + const mockNFT = await ERC721OZMock.new({ from: deployer }) + await mockNFT.mintToken(nft1, { from: deployer }) + await web3.eth.sendTransaction({ from: anotherAccount, to: lido.address, value: ETH(2) }) + + await mockERC20Token.transfer(burner.address, bn(600000), { from: deployer }) + await mockNFT.transferFrom(deployer, burner.address, nft1, { from: deployer }) + await lido.transfer(burner.address, StETH(1), { from: anotherAccount }) + + assert.isFalse(await burner.hasRole(await burner.RECOVER_ASSETS_ROLE(), anotherAccount)) + + await assert.revertsOZAccessControl( + burner.recoverERC20(mockERC20Token.address, bn(600000), { from: anotherAccount }), + anotherAccount, + `RECOVER_ASSETS_ROLE` + ) + await assert.revertsOZAccessControl( + burner.recoverERC721(mockNFT.address, nft1, { from: anotherAccount }), + anotherAccount, + `RECOVER_ASSETS_ROLE` + ) + await assert.revertsOZAccessControl( + burner.recoverExcessStETH({ from: anotherAccount }), + anotherAccount, + `RECOVER_ASSETS_ROLE` + ) + + await burner.grantRole(await burner.RECOVER_ASSETS_ROLE(), anotherAccount, { from: appManager }) + assert.isTrue(await burner.hasRole(await burner.RECOVER_ASSETS_ROLE(), anotherAccount)) + + await burner.recoverERC20(mockERC20Token.address, bn(600000), { from: anotherAccount }) + await burner.recoverERC721(mockNFT.address, nft1, { from: anotherAccount }) + await burner.recoverExcessStETH({ from: anotherAccount }) + }) + + it(`REQUEST_BURN_SHARES_ROLE works`, async () => { + await web3.eth.sendTransaction({ from: anotherAccount, to: lido.address, value: ETH(2) }) + await lido.approve(burner.address, StETH(2), { from: anotherAccount }) + + assert.isFalse(await burner.hasRole(await burner.REQUEST_BURN_SHARES_ROLE(), anotherAccount)) + + await assert.revertsOZAccessControl( + burner.requestBurnSharesForCover(anotherAccount, stETHShares(1), { from: anotherAccount }), + anotherAccount, + `REQUEST_BURN_SHARES_ROLE` + ) + + await assert.revertsOZAccessControl( + burner.requestBurnShares(anotherAccount, stETHShares(1), { from: anotherAccount }), + anotherAccount, + `REQUEST_BURN_SHARES_ROLE` + ) + + await burner.grantRole(await burner.REQUEST_BURN_SHARES_ROLE(), anotherAccount, { from: appManager }) + assert.isTrue(await burner.hasRole(await burner.REQUEST_BURN_SHARES_ROLE(), anotherAccount)) + + await burner.requestBurnSharesForCover(anotherAccount, stETHShares(1), { from: anotherAccount }) + await burner.requestBurnShares(anotherAccount, stETHShares(1), { from: anotherAccount }) + }) + + it(`only Lido can commit shares to burn`, async () => { + assert.revertsWithCustomError( + burner.commitSharesToBurn(0, { from: anotherAccount }), + `AppAuthLidoFailed('${anotherAccount}')` + ) + + await burner.commitSharesToBurn(0, { from: lido.address }) + }) + + it(`permissionless view functions are available for anyone`, async () => { + await burner.getSharesRequestedToBurn({ from: anotherAccount }) + await burner.getCoverSharesBurnt({ from: anotherAccount }) + await burner.getNonCoverSharesBurnt({ from: anotherAccount }) + await burner.getExcessStETH({ from: anotherAccount }) + }) + }) + describe('Requests and burn invocation', () => { const bnRound10 = (value) => bn(value).add(bn(5)).div(bn(10)).mul(bn(10)) @@ -115,7 +221,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { await lido.approve(burner.address, StETH(8), { from: deployer }) - // event deployer can't place burn request + // even deployer can't place burn request await assert.revertsOZAccessControl( burner.requestBurnMyStETH(StETH(8), { from: deployer }), deployer, From 897112bc4feb22cae51077f7806419dcd0590b95 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Sun, 26 Feb 2023 15:15:52 +0100 Subject: [PATCH 031/236] fix: reward distrib.: modules without active keys --- contracts/0.8.9/StakingRouter.sol | 3 ++- test/0.8.9/staking-router.test.js | 43 ++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 1ec148083..e35d8c831 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -874,7 +874,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint96 stakingModuleFee; for (uint256 i; i < stakingModulesCount; ) { - stakingModuleIds[i] = stakingModulesCache[i].stakingModuleId; + stakingModuleIds[rewardedStakingModulesCount] = stakingModulesCache[i].stakingModuleId; /// @dev skip staking modules which have no active validators if (stakingModulesCache[i].activeValidatorsCount > 0) { stakingModuleValidatorsShare = ((stakingModulesCache[i].activeValidatorsCount * precisionPoints) / totalActiveValidators); @@ -907,6 +907,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version if (rewardedStakingModulesCount < stakingModulesCount) { uint256 trim = stakingModulesCount - rewardedStakingModulesCount; assembly { + mstore(stakingModuleIds, sub(mload(stakingModuleIds), trim)) mstore(recipients, sub(mload(recipients), trim)) mstore(stakingModuleFees, sub(mload(stakingModuleFees), trim)) } diff --git a/test/0.8.9/staking-router.test.js b/test/0.8.9/staking-router.test.js index fd7e1fe3f..0454d3ad6 100644 --- a/test/0.8.9/staking-router.test.js +++ b/test/0.8.9/staking-router.test.js @@ -5,7 +5,7 @@ const { BN } = require('bn.js') const { assert } = require('../helpers/assert') const { EvmSnapshot } = require('../helpers/blockchain') const { newDao, newApp } = require('../helpers/dao') -const { ETH } = require('../helpers/utils') +const { ETH, toBN } = require('../helpers/utils') const DepositContractMock = artifacts.require('DepositContractMock') const StakingRouter = artifacts.require('StakingRouter.sol') @@ -258,20 +258,45 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ) }) - it('getStakingModuleActiveValidatorsCount', async () => { - await stakingModule.setActiveValidatorsCount(200, { from: deployer }) + it('getStakingRewardsDistribution - only one module has active keys', async () => { + await stakingModule.setActiveValidatorsCount(40, { from: deployer }) - assert.equals(await app.getStakingModuleActiveValidatorsCount(1), 200) - }) - - it('getStakingRewardsDistribution', async () => { + // no active keys for second module const anotherStakingModule = await StakingModuleMock.new({ from: deployer }) - await app.addStakingModule('Test module 2', anotherStakingModule.address, 100, 1000, 2000, { from: appManager, }) + await anotherStakingModule.setAvailableKeysCount(50, { from: deployer }) - await app.getStakingRewardsDistribution() + const stakingModuleIds = await app.getStakingModuleIds() + let rewardDistribution = await app.getStakingRewardsDistribution() + + assert.equal(stakingModuleIds.length, 2) + // only one module in distribution + assert.equal(rewardDistribution.stakingModuleIds.length, 1) + assert.deepEqual(rewardDistribution.stakingModuleIds, [stakingModuleIds[0]]) + // expect(rewardDistribution.stakingModuleIds).to.deep.equal([stakingModuleIds[0]]) + const percentPoints = toBN(100) + // 10% = 10% from (100% of active validator) + assert.equal( + rewardDistribution.stakingModuleFees[0].mul(percentPoints).div(rewardDistribution.precisionPoints).toNumber(), + 10 + ) + + // 2nd module has active keys + await anotherStakingModule.setActiveValidatorsCount(10, { from: deployer }) + rewardDistribution = await app.getStakingRewardsDistribution() + assert.deepEqual(rewardDistribution.stakingModuleIds, stakingModuleIds) + // 8% = 10% from (80% of active validator) + assert.equal( + rewardDistribution.stakingModuleFees[0].mul(percentPoints).div(rewardDistribution.precisionPoints).toNumber(), + 8 + ) + // 2% = 10% from (20% of active validator) + assert.equal( + rewardDistribution.stakingModuleFees[1].mul(percentPoints).div(rewardDistribution.precisionPoints).toNumber(), + 2 + ) }) }) From 0af976bb22c0f5fbe4e328389ea5183d1ff756c7 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Sun, 26 Feb 2023 18:28:42 +0200 Subject: [PATCH 032/236] feat: correct finalization for different share rates --- contracts/0.8.9/WithdrawalQueue.sol | 6 +- contracts/0.8.9/WithdrawalQueueBase.sol | 323 +++++++++++------- .../0.8.9/lib/UnstructuredRefStorage.sol | 6 + .../WithdrawalQueueERC721Mock.sol | 2 +- lib/abi/AccountingOracle.json | 2 +- lib/abi/ILido.json | 2 +- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 9 files changed, 221 insertions(+), 126 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 1f190a64d..cf35d4548 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -307,11 +307,11 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } /// @notice Finalize requests from last finalized one up to `_lastRequestIdToFinalize` - /// @dev ether to finalize all the requests should be calculated using `finalizationBatch()` and sent along + /// @dev ether to finalize all the requests should be calculated using `finalizationValue()` and sent along /// /// @param _nextFinalizedRequestId request index in the queue that will be last finalized request in a batch - function finalize(uint256 _nextFinalizedRequestId) external payable whenResumed onlyRole(FINALIZE_ROLE) { - _finalize(_nextFinalizedRequestId, msg.value); + function finalize(uint256 _nextFinalizedRequestId, uint256 _shareRate) external payable whenResumed onlyRole(FINALIZE_ROLE) { + _finalize(_nextFinalizedRequestId, msg.value, _shareRate); } /// @notice Update bunker mode state diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 74487cec4..c62ee9b34 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -7,6 +7,7 @@ pragma solidity 0.8.9; import "@openzeppelin/contracts-v4.4/utils/structs/EnumerableSet.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; +import {Math} from "./lib/Math.sol"; /// @title Queue to store and manage WithdrawalRequests. /// @dev Use an optimizations to store discounts heavily inspired @@ -16,12 +17,15 @@ import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; abstract contract WithdrawalQueueBase { using EnumerableSet for EnumerableSet.UintSet; using UnstructuredStorage for bytes32; + using UnstructuredRefStorage for bytes32; /// @notice precision base for share rate and discounting factor values in the contract uint256 public constant E27_PRECISION_BASE = 1e27; - /// @dev discount factor value that means no discount applying - uint96 internal constant NO_DISCOUNT = uint96(E27_PRECISION_BASE); + uint256 public constant MAX_NUMBER_OF_BATCHES = 36; + uint256 public constant MAX_REQUESTS_PER_CALL = 1000; + + uint256 internal constant SHARE_RATE_UNLIMITED = type(uint256).max; /// @dev return value for the `find...` methods in case of no result uint256 internal constant NOT_FOUND = 0; @@ -41,6 +45,8 @@ abstract contract WithdrawalQueueBase { bytes32 internal constant LOCKED_ETHER_AMOUNT_POSITION = keccak256("lido.WithdrawalQueue.lockedEtherAmount"); /// withdrawal requests mapped to the owners bytes32 internal constant REQUEST_BY_OWNER_POSITION = keccak256("lido.WithdrawalQueue.requestsByOwner"); + /// list of extremum requests for shareRate(request_id) function + bytes32 internal constant EXTREMA_POSITION = keccak256("lido.WithdrawalQueue.extremumRequestId"); /// @notice structure representing a request for withdrawal. struct WithdrawalRequest { @@ -56,13 +62,10 @@ abstract contract WithdrawalQueueBase { bool claimed; } - /// @notice structure to store discount factors for requests in the queue - struct DiscountCheckpoint { - /// @notice first `_requestId` the discount is valid for - /// @dev storing in uint160 to pack into one slot. Overflowing here is unlikely - uint160 fromRequestId; - /// @notice discount factor with 1e27 precision (0 - 100% discount, 1e27 - means no discount) - uint96 discountFactor; + /// @notice structure to store discounts for requests that are affected by negative rebase + struct Checkpoint { + uint256 fromRequestId; + uint256 maxShareRate; } /// @notice output format struct for `_getWithdrawalStatus()` method @@ -103,6 +106,8 @@ abstract contract WithdrawalQueueBase { error NotOwner(address _sender, address _owner); error InvalidRequestId(uint256 _requestId); error InvalidRequestIdRange(uint256 startId, uint256 endId); + error InvalidState(); + error EmptyBatches(); error RequestNotFoundOrNotFinalized(uint256 _requestId); error NotEnoughEther(); error RequestAlreadyClaimed(uint256 _requestId); @@ -140,137 +145,181 @@ abstract contract WithdrawalQueueBase { _getQueue()[getLastRequestId()].cumulativeStETH - _getQueue()[getLastFinalizedRequestId()].cumulativeStETH; } - /// @notice Search for the latest request in the queue in the range of `[startId, endId]`, - /// that has `request.timestamp <= maxTimestamp` - /// - /// @return finalizableRequestId or 0, if there are no requests in a range with requested timestamp - function findLastFinalizableRequestIdByTimestamp(uint256 _maxTimestamp, uint256 _startId, uint256 _endId) - public + // FINALIZATION. + // Process when protocol is fixing the withdrawal request value and lock the required amount of stETH. + // It is driven by the oracle report + // Right now finalization consists of several steps: + // 1. Oracle daemon precalculates finalization batches' boundaries that is valid on oracle report refSlot + // and post it with the report - `calculateFinalizationBatches()` + // 2. Lido contract invokes `onPreRebase()` handler to update ShareRate extremum list + // 3. Lido contract, during the report handling, calculates the value of finalization batchs in eth and shares + // and checks its correctness - `finalizationValue()` + // 4. Lido contract finalize the requests pasing the required ether along with `finalize()` method + + struct CalcState { + uint256 ethBudget; + bool finished; + uint256[] batches; + } + + function calculateFinalizationBatches(uint256 _maxShareRate, uint256 _maxTimestamp, CalcState memory _state) + external view - returns (uint256 finalizableRequestId) + returns (CalcState memory) { - if (_maxTimestamp == 0) revert ZeroTimestamp(); - if (_startId <= getLastFinalizedRequestId() || _endId > getLastRequestId()) { - revert InvalidRequestIdRange(_startId, _endId); + if (_state.finished) revert InvalidState(); + + uint256 requestId; + uint256 prevRequestShareRate; + + if (_state.batches.length == 0) { + requestId = getLastFinalizedRequestId() + 1; + // we'll store batches as a array where [MAX_NUMBER_OF_BATCHES] element is the array's length + _state.batches = new uint256[](MAX_NUMBER_OF_BATCHES + 1); + } else { + uint256 prevIterationEndId = _state.batches[_state.batches[0]]; + requestId = prevIterationEndId + 1; + prevRequestShareRate = _calcShareRate(prevIterationEndId, _maxShareRate); } - if (_startId > _endId) return NOT_FOUND; // we have an empty range to search in + uint256 length = _state.batches[MAX_NUMBER_OF_BATCHES]; + + uint256 lastRequestId = getLastRequestId(); + uint256 postFinalId = Math.min(requestId + MAX_REQUESTS_PER_CALL, lastRequestId + 1); - uint256 min = _startId; - uint256 max = _endId; + while (requestId < postFinalId) { + WithdrawalRequest memory request = _getQueue()[requestId]; - finalizableRequestId = NOT_FOUND; + if (request.timestamp > _maxTimestamp) break; - while (min <= max) { - uint256 mid = (max + min) / 2; - if (_getQueue()[mid].timestamp <= _maxTimestamp) { - finalizableRequestId = mid; + WithdrawalRequest memory prevRequest = _getQueue()[requestId - 1]; - // Ignore left half - min = mid + 1; + (uint256 requestShareRate, uint256 etherRequested) = + _calcShareRateAndEth(prevRequest, request, _maxShareRate); + if (etherRequested > _state.ethBudget) break; + + _state.ethBudget -= etherRequested; + + if (length != 0 && ( + prevRequestShareRate < _maxShareRate && requestShareRate < _maxShareRate || + prevRequestShareRate >= _maxShareRate && requestShareRate >= _maxShareRate + )) { + _state.batches[length - 1] = requestId; } else { - // Ignore right half - max = mid - 1; + if (length == MAX_NUMBER_OF_BATCHES) break; + _state.batches[length] = requestId; + ++length; } + + prevRequestShareRate = requestShareRate; + ++requestId; } - } - /// @notice Search for the latest request in the queue in the range of `[startId, endId]`, - /// that can be finalized within the given `_ethBudget` by `_shareRate` - /// @param _ethBudget amount of ether available for withdrawal fulfillment - /// @param _shareRate share/ETH rate that will be used for fulfillment - /// @param _startId requestId to start search from. Should be > lastFinalizedRequestId - /// @param _endId requestId to search upon to. Should be <= lastRequestId - /// - /// @return finalizableRequestId or 0, if there are no requests finalizable within the given `_ethBudget` - function findLastFinalizableRequestIdByBudget( - uint256 _ethBudget, - uint256 _shareRate, - uint256 _startId, - uint256 _endId - ) public view returns (uint256 finalizableRequestId) { - if (_ethBudget == 0) revert ZeroAmountOfETH(); - if (_shareRate == 0) revert ZeroShareRate(); - if (_startId <= getLastFinalizedRequestId() || _endId > getLastRequestId()) { - revert InvalidRequestIdRange(_startId, _endId); + _state.finished = requestId < postFinalId || requestId == lastRequestId + 1; + + if (_state.finished) { + // TODO: trim array in memory + uint256[] memory result = new uint256[](length); + for (uint256 i = 0; i < length; ++i) { + result[i] = _state.batches[i]; + } + _state.batches = result; + } else { + _state.batches[MAX_NUMBER_OF_BATCHES] = length; } - if (_startId > _endId) return NOT_FOUND; // we have an empty range to search in + return _state; + } - uint256 min = _startId; - uint256 max = _endId; + function onPreRebase() external { + // Populate shareRate extrema array + // Invariants: + // • shareRate(extrema[0]) == shareRate(queue[1]) + // • shareRate(extrema[n]) != shareRate(extrema[n+1]) + // • extrema[last] is minimum => shareRate(lastRequestId) <= shareRate(lastRequestId) + // • extrema[last] is maximum => shareRate(lastRequestId) >= shareRate(lastRequestId) + uint256 lastRequestId = getLastRequestId(); + uint256[] storage extrema = _getExtrema(); + // first request is an extremum + if (extrema.length == 0 && lastRequestId > 0) { + extrema.push(lastRequestId); + } - finalizableRequestId = NOT_FOUND; + uint256 lastExtremumId = extrema[extrema.length - 1]; - while (min <= max) { - uint256 mid = (max + min) / 2; - (uint256 requiredEth,) = finalizationBatch(mid, _shareRate); + if (lastRequestId > lastExtremumId) { + uint256 lastRequestShareRate = _calcShareRate(lastRequestId); + uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId); - if (requiredEth <= _ethBudget) { - finalizableRequestId = mid; + if (lastRequestShareRate == lastExtremumShareRate) return; + // first met request in a sequence with equal shareRate is an extremum - // Ignore left half - min = mid + 1; + if (extrema.length == 1) { + // first two different rates are always extrema + extrema.push(lastRequestId); } else { - // Ignore right half - max = mid - 1; + uint256 prevExtremumShareRate = _calcShareRate(lastExtremumId - 1); + + bool wasGrowing = lastExtremumShareRate > prevExtremumShareRate; + // | • + // |• * + // +-------> + if (wasGrowing && lastRequestShareRate < lastExtremumShareRate) { + extrema.push(lastRequestId); + return; + } + // |• * + // | • + // +-------> + if (!wasGrowing && lastRequestShareRate > lastExtremumShareRate) { + extrema.push(lastRequestId); + return; + } } } } - /// @notice Returns last `requestId` finalizable under given conditions - /// @param _ethBudget max amount of eth to be used for finalization - /// @param _shareRate share rate that will be applied to requests - /// @param _maxTimestamp timestamp that requests should be created before - /// - /// @dev WARNING! OOG is possible if used onchain, contains unbounded loop inside - /// @return finalizableRequestId or 0, if there are no requests finalizable under given conditions - function findLastFinalizableRequestId(uint256 _ethBudget, uint256 _shareRate, uint256 _maxTimestamp) - external - view - returns (uint256 finalizableRequestId) - { - uint256 firstUnfinalizedRequestId = getLastFinalizedRequestId() + 1; - finalizableRequestId = - findLastFinalizableRequestIdByBudget(_ethBudget, _shareRate, firstUnfinalizedRequestId, getLastRequestId()); - return findLastFinalizableRequestIdByTimestamp(_maxTimestamp, firstUnfinalizedRequestId, finalizableRequestId); - } - - /// @notice Calculates the amount of ETH required to finalize the batch of requests in the queue up to - /// `_nextFinalizedRequestId` with given `_shareRate` and the amount of shares that should be burned after - /// @param _nextFinalizedRequestId id of the ending request in the finalization batch (>0 and <=lastRequestId) - /// @param _shareRate share rate that will be used to calculate the batch (1e27 precision, >0) - /// - /// @return ethToLock amount of ETH required to finalize the batch - /// @return sharesToBurn amount of shares that should be burned after the finalization - function finalizationBatch(uint256 _nextFinalizedRequestId, uint256 _shareRate) + function finalizationValue(uint256[] calldata _batches, uint256 _maxShareRate) public view returns (uint256 ethToLock, uint256 sharesToBurn) { - if (_shareRate == 0) revert ZeroShareRate(); - if (_nextFinalizedRequestId > getLastRequestId()) revert InvalidRequestId(_nextFinalizedRequestId); - uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); - if (_nextFinalizedRequestId <= lastFinalizedRequestId) revert InvalidRequestId(_nextFinalizedRequestId); + if (_maxShareRate == 0) revert ZeroShareRate(); + if (_batches.length == 0) revert EmptyBatches(); - WithdrawalRequest memory requestToFinalize = _getQueue()[_nextFinalizedRequestId]; - WithdrawalRequest memory lastFinalizedRequest = _getQueue()[lastFinalizedRequestId]; + _checkFinalizationBatchesIntegrity(_batches); - uint256 amountOfETHRequested = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; - uint256 amountOfShares = requestToFinalize.cumulativeShares - lastFinalizedRequest.cumulativeShares; + uint256 preBatchStartId = getLastFinalizedRequestId(); + uint256 batchIndex; - ethToLock = amountOfETHRequested; - sharesToBurn = amountOfShares; + do { + WithdrawalRequest memory batchStart = _getQueue()[preBatchStartId]; + WithdrawalRequest memory batchEnd = _getQueue()[_batches[batchIndex]]; + + uint256 shares = batchEnd.cumulativeShares - batchStart.cumulativeShares; + uint256 eth = batchEnd.cumulativeStETH - batchStart.cumulativeStETH; + + uint256 batchShareRate = (eth * E27_PRECISION_BASE) / shares; + if (batchShareRate > _maxShareRate) { + ethToLock += shares * _maxShareRate / E27_PRECISION_BASE; + } else { + ethToLock += eth; + } + + sharesToBurn += shares; + + preBatchStartId = _batches[batchIndex]; + ++batchIndex; + } while (batchIndex < _batches.length); + } + + function _checkFinalizationBatchesIntegrity(uint256[] memory _batches) internal view { - uint256 currentValueInETH = (amountOfShares * _shareRate) / E27_PRECISION_BASE; - if (currentValueInETH < amountOfETHRequested) { - ethToLock = currentValueInETH; - } } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` /// Emits WithdrawalBatchFinalized event. - function _finalize(uint256 _nextFinalizedRequestId, uint256 _amountOfETH) internal { + function _finalize(uint256 _nextFinalizedRequestId, uint256 _amountOfETH, uint256 _maxShareRate) internal { if (_nextFinalizedRequestId > getLastRequestId()) revert InvalidRequestId(_nextFinalizedRequestId); uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); uint256 firstUnfinalizedRequestId = lastFinalizedRequestId + 1; @@ -282,18 +331,17 @@ abstract contract WithdrawalQueueBase { uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); - uint256 discountFactor = NO_DISCOUNT; + uint256 shareRate = SHARE_RATE_UNLIMITED; if (stETHToFinalize > _amountOfETH) { - discountFactor = _amountOfETH * E27_PRECISION_BASE / stETHToFinalize; + shareRate = _maxShareRate; } uint256 lastCheckpointIndex = getLastCheckpointIndex(); - DiscountCheckpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; + Checkpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; - if (discountFactor != lastCheckpoint.discountFactor) { + if (shareRate != lastCheckpoint.maxShareRate) { // add a new discount if it differs from the previous - _getCheckpoints()[lastCheckpointIndex + 1] = - DiscountCheckpoint(uint160(firstUnfinalizedRequestId), uint96(discountFactor)); + _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstUnfinalizedRequestId, shareRate); _setLastCheckpointIndex(lastCheckpointIndex + 1); } @@ -437,21 +485,29 @@ abstract contract WithdrawalQueueBase { uint256 lastCheckpointIndex = getLastCheckpointIndex(); if (_hint > lastCheckpointIndex) revert InvalidHint(_hint); - DiscountCheckpoint memory hintCheckpoint = _getCheckpoints()[_hint]; + Checkpoint memory checkpoint = _getCheckpoints()[_hint]; // ______(>______ // ^ hint - if (_requestId < hintCheckpoint.fromRequestId) revert InvalidHint(_hint); + if (_requestId < checkpoint.fromRequestId) revert InvalidHint(_hint); if (_hint < lastCheckpointIndex) { // ______(>______(>________ // hint hint+1 ^ - DiscountCheckpoint memory nextCheckpoint = _getCheckpoints()[_hint + 1]; + Checkpoint memory nextCheckpoint = _getCheckpoints()[_hint + 1]; if (nextCheckpoint.fromRequestId <= _requestId) { revert InvalidHint(_hint); } } - uint256 ethRequested = _request.cumulativeStETH - _getQueue()[_requestId - 1].cumulativeStETH; - return ethRequested * hintCheckpoint.discountFactor / E27_PRECISION_BASE; + WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; + + uint256 ethRequested = _request.cumulativeStETH - prevRequest.cumulativeStETH; + uint256 shareRequested = _request.cumulativeShares - prevRequest.cumulativeShares; + + if (ethRequested * E27_PRECISION_BASE / shareRequested <= checkpoint.maxShareRate) { + return ethRequested; + } + + return shareRequested * checkpoint.maxShareRate / E27_PRECISION_BASE; } // quazi-constructor @@ -460,7 +516,7 @@ abstract contract WithdrawalQueueBase { // to avoid uint underflows and related if-branches // 0-index is reserved as 'not_found' response in the interface everywhere _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint64(block.number), true); - _getCheckpoints()[getLastCheckpointIndex()] = DiscountCheckpoint(0, 0); + _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, 0); } function _sendValue(address _recipient, uint256 _amount) internal { @@ -471,6 +527,35 @@ abstract contract WithdrawalQueueBase { if (!success) revert CantSendValueRecipientMayHaveReverted(); } + function _calcShareRateAndEth( + WithdrawalRequest memory _prevRequest, + WithdrawalRequest memory _lastRequest, + uint256 maxShareRate + ) internal pure returns (uint256 eth, uint256 shares) { + uint256 ethRequested = _lastRequest.cumulativeStETH - _prevRequest.cumulativeStETH; + uint256 shareRequested = _lastRequest.cumulativeShares - _prevRequest.cumulativeShares; + + if (ethRequested * E27_PRECISION_BASE / shareRequested <= maxShareRate) { + return (ethRequested, shareRequested); + } + + return (shareRequested * maxShareRate / E27_PRECISION_BASE, shareRequested); + } + + function _calcShareRate(uint256 _requestId, uint256 _maxShareRate) internal view returns (uint256) { + WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; + WithdrawalRequest memory lastRequest = _getQueue()[_requestId]; + + uint256 ethRequested = lastRequest.cumulativeStETH - prevRequest.cumulativeStETH; + uint256 shareRequested = lastRequest.cumulativeShares - prevRequest.cumulativeShares; + + return Math.min(ethRequested * E27_PRECISION_BASE / shareRequested, _maxShareRate); + } + + function _calcShareRate(uint256 _requestId) internal view returns (uint256) { + return _calcShareRate(_requestId, SHARE_RATE_UNLIMITED); + } + // // Internal getters and setters // @@ -481,7 +566,7 @@ abstract contract WithdrawalQueueBase { } } - function _getCheckpoints() internal pure returns (mapping(uint256 => DiscountCheckpoint) storage checkpoints) { + function _getCheckpoints() internal pure returns (mapping(uint256 => Checkpoint) storage checkpoints) { bytes32 position = CHECKPOINTS_POSITION; assembly { checkpoints.slot := position @@ -499,6 +584,10 @@ abstract contract WithdrawalQueueBase { } } + function _getExtrema() internal pure returns (uint256[] storage) { + return EXTREMA_POSITION.storageUint256Array(); + } + function _setLastRequestId(uint256 _lastRequestId) internal { LAST_REQUEST_ID_POSITION.setStorageUint256(_lastRequestId); } diff --git a/contracts/0.8.9/lib/UnstructuredRefStorage.sol b/contracts/0.8.9/lib/UnstructuredRefStorage.sol index 322e9e51c..0814c0430 100644 --- a/contracts/0.8.9/lib/UnstructuredRefStorage.sol +++ b/contracts/0.8.9/lib/UnstructuredRefStorage.sol @@ -4,6 +4,12 @@ pragma solidity 0.8.9; library UnstructuredRefStorage { + function storageUint256Array(bytes32 _position) internal pure returns ( + uint256[] storage result + ) { + assembly { result.slot := _position } + } + function storageAddressArray(bytes32 _position) internal pure returns ( address[] storage result ) { diff --git a/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol b/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol index 8ab843d98..4fe82c69e 100644 --- a/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol +++ b/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol @@ -18,7 +18,7 @@ contract WithdrawalQueueERC721Mock is WithdrawalQueueERC721 { return _getQueue()[id]; } - function getCheckpointItem(uint256 id) external view returns (DiscountCheckpoint memory) { + function getCheckpointItem(uint256 id) external view returns (Checkpoint memory) { return _getCheckpoints()[id]; } } diff --git a/lib/abi/AccountingOracle.json b/lib/abi/AccountingOracle.json index 020eb6eab..438fa649d 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":"ExtraDataHashCannotBeZeroForNonEmptyData","type":"error"},{"inputs":[],"name":"ExtraDataItemsCountCannotBeZeroForNonEmptyData","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":[],"name":"RefSlotAlreadyProcessing","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":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedExtraDataHash","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_EMPTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"bool","name":"extraDataSubmitted","type":"bool"},{"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":"sharesRequestedToBurn","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":[],"name":"submitReportExtraDataEmpty","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":"ExtraDataHashCannotBeZeroForNonEmptyData","type":"error"},{"inputs":[],"name":"ExtraDataItemsCountCannotBeZeroForNonEmptyData","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":[],"name":"RefSlotAlreadyProcessing","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":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedExtraDataHash","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_EMPTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"bool","name":"extraDataSubmitted","type":"bool"},{"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":"sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256[]","name":"withdrawalFinalizationBatches","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":[],"name":"submitReportExtraDataEmpty","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/ILido.json b/lib/abi/ILido.json index fd3694036..f79f48b65 100644 --- a/lib/abi/ILido.json +++ b/lib/abi/ILido.json @@ -1 +1 @@ -[{"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":"_sharesRequestedToBurn","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 +[{"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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256[]","name":"_withdrawalFinalizationBatches","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/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 630bba300..ff9012d5d 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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":"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":[],"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":[{"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index bb0aec71d..71af00699 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"NotEnoughEther","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"NotOwner","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"_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":[],"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":[],"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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":[],"name":"onPreRebase","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 728ac3391..807cc00f5 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.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":"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":[],"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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 96adba3489bf8995357c229a86b2edb1ae5355c7 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Sun, 26 Feb 2023 18:29:09 +0200 Subject: [PATCH 033/236] test: partial test fixes --- contracts/0.8.9/WithdrawalQueueBase.sol | 17 +- .../oracle-report-sanity-checker.test.js | 12 +- test/0.8.9/withdrawal-queue-deploy.test.js | 10 +- ...ithdrawal-queue-share-rate-changes.test.js | 9 +- test/0.8.9/withdrawal-queue.test.js | 278 +++++------------- test/0.8.9/withdrawal-request-nft.test.js | 12 +- 6 files changed, 102 insertions(+), 236 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index c62ee9b34..a384d5d4a 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -285,8 +285,6 @@ abstract contract WithdrawalQueueBase { returns (uint256 ethToLock, uint256 sharesToBurn) { if (_maxShareRate == 0) revert ZeroShareRate(); - if (_batches.length == 0) revert EmptyBatches(); - _checkFinalizationBatchesIntegrity(_batches); uint256 preBatchStartId = getLastFinalizedRequestId(); @@ -314,7 +312,14 @@ abstract contract WithdrawalQueueBase { } function _checkFinalizationBatchesIntegrity(uint256[] memory _batches) internal view { + if (_batches.length == 0) revert EmptyBatches(); + uint256 lastIdInBatch = _batches[_batches.length - 1]; + if (lastIdInBatch > getLastRequestId()) revert InvalidRequestId(lastIdInBatch); + uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); + uint256 firstIdInBatch = _batches[0]; + if (firstIdInBatch <= lastFinalizedRequestId) revert InvalidRequestId(firstIdInBatch); + // TODO: check extrema and crossing points } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` @@ -331,17 +336,17 @@ abstract contract WithdrawalQueueBase { uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); - uint256 shareRate = SHARE_RATE_UNLIMITED; + uint256 maxShareRate = SHARE_RATE_UNLIMITED; if (stETHToFinalize > _amountOfETH) { - shareRate = _maxShareRate; + maxShareRate = _maxShareRate; } uint256 lastCheckpointIndex = getLastCheckpointIndex(); Checkpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; - if (shareRate != lastCheckpoint.maxShareRate) { + if (maxShareRate != lastCheckpoint.maxShareRate) { // add a new discount if it differs from the previous - _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstUnfinalizedRequestId, shareRate); + _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstUnfinalizedRequestId, maxShareRate); _setLastCheckpointIndex(lastCheckpointIndex + 1); } 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 e899e6c70..e78914ec8 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -1,14 +1,14 @@ -const { hre, contract, ethers } = require('hardhat') +const { artifacts, contract, ethers } = require('hardhat') const { ETH } = require('../helpers/utils') const { assert } = require('../helpers/assert') const { getCurrentBlockTimestamp } = require('../helpers/blockchain') const mocksFilePath = 'contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol' -const LidoStub = hre.artifacts.require(`${mocksFilePath}:LidoStub`) -const OracleReportSanityChecker = hre.artifacts.require('OracleReportSanityChecker') -const LidoLocatorStub = hre.artifacts.require(`${mocksFilePath}:LidoLocatorStub`) -const WithdrawalQueueStub = hre.artifacts.require(`${mocksFilePath}:WithdrawalQueueStub`) -const BurnerStub = hre.artifacts.require(`${mocksFilePath}:BurnerStub`) +const LidoStub = artifacts.require(`${mocksFilePath}:LidoStub`) +const OracleReportSanityChecker = artifacts.require('OracleReportSanityChecker') +const LidoLocatorStub = artifacts.require(`${mocksFilePath}:LidoLocatorStub`) +const WithdrawalQueueStub = artifacts.require(`${mocksFilePath}:WithdrawalQueueStub`) +const BurnerStub = artifacts.require(`${mocksFilePath}:BurnerStub`) function wei(number, units = 'wei') { switch (units.toLowerCase()) { diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 84b884e45..9bebf602f 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -1,5 +1,5 @@ const { artifacts, contract } = require('hardhat') -const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') +const { ZERO_ADDRESS } = require('../helpers/constants') const { ETH } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') @@ -113,13 +113,13 @@ contract( const checkpointIndex = await withdrawalQueue.getLastCheckpointIndex() const checkpointItem = await withdrawalQueue.getCheckpointItem(checkpointIndex) - assert.equals(+queueItem.cumulativeStETH, 0) - assert.equals(+queueItem.cumulativeShares, 0) + assert.equals(queueItem.cumulativeStETH, 0) + assert.equals(queueItem.cumulativeShares, 0) assert.equals(queueItem.owner, ZERO_ADDRESS) assert.equals(queueItem.claimed, true) - assert.equals(+checkpointItem.fromRequestId, 0) - assert.equals(+checkpointItem.discountFactor, 0) + assert.equals(checkpointItem.fromRequestId, 0) + assert.equals(checkpointItem.maxShareRate, 0) }) it('check if pauser is zero', async () => { diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index b860af6bc..db9c29608 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -2,7 +2,7 @@ const { contract, ethers } = require('hardhat') const { assert } = require('../helpers/assert') const { e18, e27, toBN, getFirstEventArgs } = require('../helpers/utils') -const { MAX_UINT256 } = require('../0.6.12/helpers/constants') +const { MAX_UINT256 } = require('../helpers/constants') const { EvmSnapshot } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') @@ -74,7 +74,10 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`both requests can be finalized with 2 ETH`, async () => { - const batch = await queue.finalizationBatch(requestIds[1], e27(1)) + const result = await queue.calculateFinalizationBatches(e27(1), MAX_UINT256, [e18(2), false, []]) + assert.isTrue(result.finished) + + const batch = await queue.finalizationValue(result.batches, e27(1)) assert.equals(batch.ethToLock, e18(2)) assert.equals(batch.sharesToBurn, e18(2)) }) @@ -82,7 +85,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { let claimableEther it(`requests get finalized`, async () => { - await queue.finalize(requestIds[1], { from: finalizer, value: e18(2) }) + await queue.finalize(requestIds[1], e27(1), { from: finalizer, value: e18(2) }) assert.equals(await queue.getLastFinalizedRequestId(), requestIds[1]) const hints = await queue.findCheckpointHintsUnbounded(requestIds) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index f8b3c12f8..a2316d44d 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -14,6 +14,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const snapshot = new EvmSnapshot(ethers.provider) + const currentRate = async () => + bn(await steth.getTotalPooledEther()) + .mul(bn(10).pow(bn(27))) + .div(await steth.getTotalShares()) + before('Deploy', async () => { const deployed = await deployWithdrawalQueue({ stethOwner: owner, @@ -83,7 +88,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, withdrawalQueue.requestWithdrawalsWstETHWithPermit([ETH(1)], owner, stubPermit, { from: user }), 'ResumedExpected()' ) - await assert.reverts(withdrawalQueue.finalize(1, { from: owner }), 'ResumedExpected()') + await assert.reverts(withdrawalQueue.finalize(1, 0, { from: owner }), 'ResumedExpected()') }) it('cant resume if not paused', async () => { @@ -306,19 +311,12 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) }) - it('Calculate one request batch', async () => { - const batch = await withdrawalQueue.finalizationBatch(1, shareRate(300)) - - assert.equals(batch.ethToLock, ETH(300)) - assert.equals(batch.sharesToBurn, shares(1)) - }) - it('Finalizer can finalize a request', async () => { await assert.reverts( - withdrawalQueue.finalize(1, { from: stranger }), + withdrawalQueue.finalize(1, 0, { from: stranger }), `AccessControl: account ${stranger.toLowerCase()} is missing role ${await withdrawalQueue.FINALIZE_ROLE()}` ) - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, 1, { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), amount) assert.equals( @@ -328,7 +326,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('One can finalize requests with discount', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(150) }) + await withdrawalQueue.finalize(1, shareRate(150), { from: steth.address, value: ETH(150) }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(150)) assert.equals( @@ -342,11 +340,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.mintShares(user, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(10) }) + await withdrawalQueue.finalize(1, shareRate(10), { from: steth.address, value: ETH(10) }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(10) }) + await withdrawalQueue.finalize(2, shareRate(10), { from: steth.address, value: ETH(10) }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) }) @@ -357,8 +355,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - const batch = await withdrawalQueue.finalizationBatch(2, shareRate(300)) - await withdrawalQueue.finalize(2, { from: steth.address, value: batch.ethToLock }) + const batch = await withdrawalQueue.finalizationValue([2], shareRate(300)) + await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: batch.ethToLock }) assert.equals(batch.sharesToBurn, shares(2)) assert.equals(await withdrawalQueue.getLastRequestId(), 2) @@ -377,7 +375,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 1) @@ -387,7 +385,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await ethers.provider.getBalance(withdrawalQueue.address) ) - await withdrawalQueue.finalize(2, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 2) @@ -399,30 +397,30 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('batch reverts if share rate is zero', async () => { - await assert.reverts(withdrawalQueue.finalizationBatch(1, shareRate(0)), 'ZeroShareRate()') + await assert.reverts(withdrawalQueue.finalizationValue([1], shareRate(0)), 'ZeroShareRate()') }) it('reverts if request with given id did not even created', async () => { const idAhead = +(await withdrawalQueue.getLastRequestId()) + 1 await assert.reverts( - withdrawalQueue.finalize(idAhead, { from: steth.address, value: amount }), + withdrawalQueue.finalize(idAhead, shareRate(300), { from: steth.address, value: amount }), `InvalidRequestId(${idAhead})` ) - await assert.reverts(withdrawalQueue.finalizationBatch(idAhead, shareRate(300)), `InvalidRequestId(${idAhead})`) + await assert.reverts(withdrawalQueue.finalizationValue([idAhead], shareRate(300)), `InvalidRequestId(${idAhead})`) }) it('reverts if request with given id was finalized already', async () => { const id = +(await withdrawalQueue.getLastRequestId()) - await withdrawalQueue.finalize(id, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amount }) await assert.reverts( - withdrawalQueue.finalize(id, { from: steth.address, value: amount }), + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amount }), `InvalidRequestId(${id})` ) - await assert.reverts(withdrawalQueue.finalizationBatch(id, shareRate(300)), `InvalidRequestId(${id})`) + await assert.reverts(withdrawalQueue.finalizationValue([id], shareRate(300)), `InvalidRequestId(${id})`) }) it('reverts if given amount to finalize exceeds requested', async () => { @@ -430,7 +428,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const amountExceeded = bn(ETH(400)) await assert.reverts( - withdrawalQueue.finalize(id, { from: steth.address, value: amountExceeded }), + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amountExceeded }), `TooMuchEtherToFinalize(${+amountExceeded}, ${+amount})` ) }) @@ -443,16 +441,16 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('works', async () => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: ETH(1) }) assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(1)) }) it('reverts if last hint checkpoint is ahead of requestId', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(0.5) }) + await withdrawalQueue.finalize(1, shareRate(0.5), { from: steth.address, value: ETH(0.5) }) await withdrawalQueue.requestWithdrawals([ETH(2)], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(0.5) }) + await withdrawalQueue.finalize(2, shareRate(0.5), { from: steth.address, value: ETH(0.5) }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') }) @@ -463,7 +461,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('return 0 for claimed request', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: ETH(1) }) await withdrawalQueue.claimWithdrawals([1], [1], { from: owner }) assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(0)) @@ -474,7 +472,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts(withdrawalQueue.getClaimableEther([0], [1]), 'InvalidRequestId(0)') await assert.reverts(withdrawalQueue.getClaimableEther([2], [1]), 'InvalidRequestId(2)') - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: ETH(1) }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') await assert.reverts(withdrawalQueue.getClaimableEther([1], [0]), 'InvalidHint(0)') @@ -482,8 +480,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') await withdrawalQueue.requestWithdrawals([ETH(1), ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(0.99) }) - await withdrawalQueue.finalize(3, { from: steth.address, value: ETH(0.98) }) + await withdrawalQueue.finalize(2, shareRate(0.99), { from: steth.address, value: ETH(0.99) }) + await withdrawalQueue.finalize(3, shareRate(0.98), { from: steth.address, value: ETH(0.98) }) await assert.reverts(withdrawalQueue.getClaimableEther([3], [1]), 'InvalidHint(1)') }) @@ -496,7 +494,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('Owner can claim a finalized request to recipient address', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) const balanceBefore = bn(await ethers.provider.getBalance(user)) @@ -518,7 +516,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts if sender is not owner', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) await assert.reverts( withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: stranger }), `NotOwner("${stranger}", "${owner}")` @@ -526,14 +524,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts if there is not enough balance', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) await setBalance(withdrawalQueue.address, ETH(200)) await assert.reverts(withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: owner }), 'NotEnoughEther()') }) }) it('Owner can claim a finalized request without hint', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) @@ -561,20 +559,20 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: amount }) await assert.reverts(withdrawalQueue.claimWithdrawals([1], [0], { from: owner }), 'InvalidHint(0)') await assert.reverts(withdrawalQueue.claimWithdrawals([1], [2], { from: owner }), 'InvalidHint(2)') }) it('Cant withdraw token two times', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(1, { from: owner }) await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: owner }), 'RequestAlreadyClaimed(1)') }) it('Discounted withdrawals produce less eth', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(150) }) + await withdrawalQueue.finalize(1, shareRate(150), { from: steth.address, value: ETH(150) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(150)) @@ -586,18 +584,19 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.almostEqual(bn(await ethers.provider.getBalance(owner)).sub(balanceBefore), ETH(150), tx.receipt.gasUsed) }) - it('One can claim a lot of withdrawals with different discounts', async () => { + it.skip('One can claim a lot of withdrawals with different discounts', async () => { await steth.setTotalPooledEther(ETH(22)) await steth.mintShares(user, shares(21)) await steth.approve(withdrawalQueue.address, StETH(21), { from: user }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 0) - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: amount }) for (let i = 1; i <= 20; i++) { assert.equals(await withdrawalQueue.getLastCheckpointIndex(), i) await withdrawalQueue.requestWithdrawals([StETH(1)], ZERO_ADDRESS, { from: user }) - await withdrawalQueue.finalize(i + 1, { from: steth.address, value: bn(ETH(1)).sub(bn(i * 1000)) }) + const amount = bn(ETH(1)).subn(i * 1000) + await withdrawalQueue.finalize(i + 1, amount.muln(1e6).muln(1e3), { from: steth.address, value: amount }) } assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 21) @@ -626,7 +625,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('direct', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, { from: steth.address, value: total }) + await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -638,7 +637,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('reverse', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, { from: steth.address, value: total }) + await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) for (let index = requestIds.length - 1; index >= 0; index--) { const requestId = requestIds[index] @@ -652,7 +651,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const randomIds = [...requestIds].sort(() => 0.5 - Math.random()) const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, { from: steth.address, value: total }) + await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) for (let index = 0; index < randomIds.length; index++) { const requestId = randomIds[index] @@ -667,11 +666,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const totalDistributedEth = bn(0) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(1 / (index + 1)) }) + await withdrawalQueue.finalize(requestId, await currentRate(), { + from: steth.address, + value: ETH(1 / (index + 1)), + }) totalDistributedEth.iadd(bn(ETH(1 / (index + 1)))) } const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, { from: steth.address, value: total }) + await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -681,171 +683,27 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) - context('findLastFinalizableRequestIdByTimestamp()', async () => { - const numOfRequests = 10 - - beforeEach(async () => { - for (let i = 1; i <= numOfRequests; i++) { - await withdrawalQueue.requestWithdrawals([ETH(20)], owner, { from: user }) - } - }) - - it('works', async () => { - for (let i = 1; i <= numOfRequests; i++) { - const timestamp = (await withdrawalQueue.getWithdrawalStatus([i]))[0].timestamp - assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 1, 10), i) - } - }) - - it('returns zero on empty range', async () => { - assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByTimestamp(1, 2, 1), 0) - }) - - it('return zero if no unfinalized request found', async () => { - const timestamp = (await withdrawalQueue.getWithdrawalStatus([1]))[0].timestamp - - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH[10] }) - assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 2, 10), 0) - }) - - it('checks params', async () => { - await assert.reverts(withdrawalQueue.findLastFinalizableRequestIdByTimestamp(0, 0, 10), 'ZeroTimestamp()') - - const timestamp = (await withdrawalQueue.getWithdrawalStatus([2]))[0].timestamp - - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 0, 10), - 'InvalidRequestIdRange(0, 10)' - ) - - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 0, 11), - 'InvalidRequestIdRange(0, 11)' - ) - - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(20) }) - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 1, 10), - 'InvalidRequestIdRange(1, 10)' - ) - - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 2, 1000), - 'InvalidRequestIdRange(2, 1000)' - ) - }) - }) - - context('findLastFinalizableRequestIdByBudget()', async () => { - const numOfRequests = 10 - - beforeEach(async () => { - for (let i = 1; i <= numOfRequests; i++) { - await withdrawalQueue.requestWithdrawals([ETH(20)], owner, { from: user }) - } - }) - - it('works', async () => { - // 1e18 shares is 300e18 ether, let's discount to 150 - const rate = shareRate(150) - - for (let i = 1; i <= numOfRequests; i++) { - const budget = ETH(i * 10 + 5) - assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByBudget(budget, rate, 1, 10), i) - } - }) - - it('return zero if no unfinalized request found', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH[10] }) - assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 2, 10), 0) - }) - - it('returns zero on empty range', async () => { - assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 2, 1), 0) - }) - - it('checks params', async () => { - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(0), shareRate(300), 0, 10), - 'ZeroAmountOfETH()' - ) - - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(0), 0, 10), - 'ZeroShareRate()' - ) - - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 0, 10), - 'InvalidRequestIdRange(0, 10)' - ) - - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 0, 11), - 'InvalidRequestIdRange(0, 11)' - ) - - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(20) }) - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 1, 10), - 'InvalidRequestIdRange(1, 10)' - ) - - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 1, 10), - 'InvalidRequestIdRange(1, 10)' - ) - await assert.reverts( - withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 2, 1000), - 'InvalidRequestIdRange(2, 1000)' - ) - }) - }) - - context('findLastFinalizableRequestId()', async () => { - const numOfRequests = 10 - - beforeEach(async () => { - for (let i = 1; i <= numOfRequests + 1; i++) { - await withdrawalQueue.requestWithdrawals([ETH(20)], owner, { from: user }) - } - }) - + context('caclulateFinalizationBatches()', () => { it('works', async () => { - for (let i = 1; i <= numOfRequests; i++) { - const budget = ETH(i * 10 + 5) - const timestamp = (await withdrawalQueue.getWithdrawalStatus([i]))[0].timestamp - assert.equals(await withdrawalQueue.findLastFinalizableRequestId(budget, shareRate(150), timestamp), i) - } - }) - - it('returns zero if no unfinalized requests', async () => { - await withdrawalQueue.finalize(10, { from: steth.address, value: ETH[10] }) + await withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }) + const batch = await withdrawalQueue.finalizationValue([1], shareRate(300)) - const timestamp = (await withdrawalQueue.getWithdrawalStatus([10]))[0].timestamp - assert.equals(await withdrawalQueue.findLastFinalizableRequestId(ETH(100), shareRate(100), timestamp), 0) - }) - - it('checks params', async () => { - await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(0), shareRate(300), 1), 'ZeroAmountOfETH()') - - await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(1), shareRate(0), 1), 'ZeroShareRate()') - - await assert.reverts(withdrawalQueue.findLastFinalizableRequestId(ETH(1), shareRate(1), 0), 'ZeroTimestamp()') + assert.equals(batch.ethToLock, ETH(300)) + assert.equals(batch.sharesToBurn, shares(1)) }) }) - context('findCheckpointsHint()', async () => { + context('findCheckpointHints()', async () => { const numOfRequests = 10 const requests = Array(numOfRequests).fill(ETH(20)) const discountedPrices = Array(numOfRequests) .fill() - .map((_, i) => ETH(i)) + .map((_, i) => i) beforeEach(async () => { await withdrawalQueue.requestWithdrawals(requests, owner, { from: user }) for (let i = 1; i <= numOfRequests; i++) { - await withdrawalQueue.finalize(i, { from: steth.address, value: discountedPrices[i] }) + await withdrawalQueue.finalize(i, { from: steth.address, value: ETH(discountedPrices[i]) }) } assert.equals(await withdrawalQueue.getLastCheckpointIndex(), numOfRequests) assert.equals( @@ -948,8 +806,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns not found when indexes have negative overlap', async () => { - const batch = await withdrawalQueue.finalizationBatch(requestId, shareRate(300)) - await withdrawalQueue.finalize(requestId, { from: steth.address, value: batch.ethToLock }) + const batch = await withdrawalQueue.finalizationValue([requestId], shareRate(300)) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: batch.ethToLock }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints( [requestId], @@ -961,8 +819,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns hints array with one item for list from single request id', async () => { - const batch = await withdrawalQueue.finalizationBatch(requestId, shareRate(300)) - await withdrawalQueue.finalize(requestId, { from: steth.address, value: batch.ethToLock }) + const batch = await withdrawalQueue.finalizationValue([requestId], shareRate(300)) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: batch.ethToLock }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints([requestId], 1, lastCheckpointIndex) assert.equal(hints.length, 1) @@ -970,7 +828,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns correct hints array for given request ids', async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(20) }) + await withdrawalQueue.finalize([requestId], shareRate(20), { from: steth.address, value: ETH(20) }) await steth.mintShares(owner, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) @@ -983,7 +841,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) const thirdRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(thirdRequestId, { from: steth.address, value: ETH(40) }) + await withdrawalQueue.finalize(thirdRequestId, shareRate(20), { from: steth.address, value: ETH(40) }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints( @@ -998,7 +856,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts with RequestIdsNotSorted error when request ids not in ascending order', async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(20) }) + await withdrawalQueue.finalize([requestId], shareRate(20), { from: steth.address, value: ETH(20) }) await steth.mintShares(owner, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) @@ -1011,7 +869,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) const thirdRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(thirdRequestId, { from: steth.address, value: ETH(40) }) + await withdrawalQueue.finalize(thirdRequestId, shareRate(20), { from: steth.address, value: ETH(40) }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() await assert.reverts( @@ -1031,7 +889,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns correct hints array for given request ids', async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(20) }) + await withdrawalQueue.finalize(requestId, shareRate(20), { from: steth.address, value: ETH(20) }) await steth.mintShares(owner, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) @@ -1044,7 +902,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) const thirdRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(thirdRequestId, { from: steth.address, value: ETH(40) }) + await withdrawalQueue.finalize(thirdRequestId, shareRate(20), { from: steth.address, value: ETH(40) }) const hints = await withdrawalQueue.findCheckpointHintsUnbounded([requestId, secondRequestId, thirdRequestId]) assert.equal(hints.length, 3) @@ -1068,7 +926,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const secondRequestAmount = ETH(10) await withdrawalQueue.requestWithdrawals([secondRequestAmount], owner, { from: owner }) const secondRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(secondRequestId, { from: steth.address, value: ETH(30) }) + await withdrawalQueue.finalize(secondRequestId, shareRate(30), { from: steth.address, value: ETH(30) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) const tx = await withdrawalQueue.claimWithdrawals([1, 2], [1, 1], { from: owner }) @@ -1258,7 +1116,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it("One can't change claimed request", async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(requestId, { from: user }) await assert.reverts( diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index 747f3c7e6..c452071cb 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -242,8 +242,8 @@ contract('WithdrawalNFT', (addresses) => { }) it('reverts with error "RequestAlreadyClaimed()" when called on claimed request', async () => { - const batch = await withdrawalQueueERC721.finalizationBatch(3, shareRate(1)) - await withdrawalQueueERC721.finalize(3, { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.finalizationValue([3], shareRate(1)) + await withdrawalQueueERC721.finalize(3, shareRate(1), { from: deployer, value: batch.ethToLock }) const ownerETHBefore = await ethers.provider.getBalance(nftHolderStETH) const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { from: nftHolderStETH, @@ -297,8 +297,8 @@ contract('WithdrawalNFT', (addresses) => { }) assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - const batch = await withdrawalQueueERC721.finalizationBatch(3, shareRate(1)) - await withdrawalQueueERC721.finalize(3, { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.finalizationValue([3], shareRate(1)) + await withdrawalQueueERC721.finalize(3, shareRate(1), { from: deployer, value: batch.ethToLock }) const recipientETHBefore = await ethers.provider.getBalance(recipient) const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { @@ -322,8 +322,8 @@ contract('WithdrawalNFT', (addresses) => { it('balanceOf decreases after claim', async () => { const balanceBefore = await withdrawalQueueERC721.balanceOf(nftHolderStETH) - const batch = await withdrawalQueueERC721.finalizationBatch(3, shareRate(1)) - await withdrawalQueueERC721.finalize(3, { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.finalizationValue([3], shareRate(1)) + await withdrawalQueueERC721.finalize(3, shareRate(1), { from: deployer, value: batch.ethToLock }) await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { from: nftHolderStETH, From 8a87e277b57e5cfb2241076c3c8ae7672b81cac3 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Sun, 26 Feb 2023 20:03:56 +0200 Subject: [PATCH 034/236] fix: a bit of optimizations to save contract size --- contracts/0.8.9/WithdrawalQueueBase.sol | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index a384d5d4a..3f449c753 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -212,18 +212,16 @@ abstract contract WithdrawalQueueBase { } prevRequestShareRate = requestShareRate; - ++requestId; + unchecked{ ++requestId; } } _state.finished = requestId < postFinalId || requestId == lastRequestId + 1; if (_state.finished) { - // TODO: trim array in memory - uint256[] memory result = new uint256[](length); - for (uint256 i = 0; i < length; ++i) { - result[i] = _state.batches[i]; + uint256[] memory batches = _state.batches; + assembly { + mstore(batches, length) } - _state.batches = result; } else { _state.batches[MAX_NUMBER_OF_BATCHES] = length; } @@ -307,7 +305,7 @@ abstract contract WithdrawalQueueBase { sharesToBurn += shares; preBatchStartId = _batches[batchIndex]; - ++batchIndex; + unchecked{ ++batchIndex; } } while (batchIndex < _batches.length); } From 25803d81f2a33a7fe75af75d7d5728fffbc1d1fb Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 27 Feb 2023 04:30:14 +0700 Subject: [PATCH 035/236] fix staking router tests, typos --- ...iginigKyesMock.sol => SigningKeysMock.sol} | 2 - contracts/0.8.9/StakingRouter.sol | 4 +- .../0.8.9/test_helpers/StakingModuleMock.sol | 96 +++- lib/abi/StakingRouter.json | 2 +- test/0.8.9/staking-router-deposits.test.js | 124 ---- test/0.8.9/staking-router/digest.test.js | 238 ++++++++ .../rewards-distribution.test.js | 391 +++++++++++++ ...ing-router-allocation-combinations.test.js | 2 +- ...staking-router-deposits-allocation.test.js | 2 +- .../staking-router-deposits.test.js | 255 +++++++++ .../staking-router-keys-reporting.test.js | 241 +++++++- .../staking-router.test.js | 529 +++++++++++++----- test/helpers/staking-modules.js | 7 + 13 files changed, 1601 insertions(+), 292 deletions(-) rename contracts/0.4.24/test_helpers/{SiginigKyesMock.sol => SigningKeysMock.sol} (98%) delete mode 100644 test/0.8.9/staking-router-deposits.test.js create mode 100644 test/0.8.9/staking-router/digest.test.js create mode 100644 test/0.8.9/staking-router/rewards-distribution.test.js rename test/0.8.9/{ => staking-router}/staking-router-allocation-combinations.test.js (99%) rename test/0.8.9/{ => staking-router}/staking-router-deposits-allocation.test.js (99%) create mode 100644 test/0.8.9/staking-router/staking-router-deposits.test.js rename test/0.8.9/{ => staking-router}/staking-router-keys-reporting.test.js (74%) rename test/0.8.9/{ => staking-router}/staking-router.test.js (54%) diff --git a/contracts/0.4.24/test_helpers/SiginigKyesMock.sol b/contracts/0.4.24/test_helpers/SigningKeysMock.sol similarity index 98% rename from contracts/0.4.24/test_helpers/SiginigKyesMock.sol rename to contracts/0.4.24/test_helpers/SigningKeysMock.sol index 4b2da4ab8..b83ef641f 100644 --- a/contracts/0.4.24/test_helpers/SiginigKyesMock.sol +++ b/contracts/0.4.24/test_helpers/SigningKeysMock.sol @@ -6,8 +6,6 @@ pragma solidity 0.4.24; import {SigningKeys} from "../lib/SigningKeys.sol"; -import "hardhat/console.sol"; - contract SigningKeysMock { using SigningKeys for bytes32; diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 1ec148083..564cba20d 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -49,7 +49,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 currentNodeOpExitedValidatorsCount, uint256 currentNodeOpStuckValidatorsCount ); - error InvalidDepositsValue(uint256 etherValue); + error InvalidDepositsValue(uint256 etherValue, uint256 depositsCount); error StakingModuleAddressExists(); enum StakingModuleStatus { @@ -965,7 +965,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 depositsValue = msg.value; if (depositsValue == 0 || depositsValue != _depositsCount * DEPOSIT_SIZE) { - revert InvalidDepositsValue(depositsValue); + revert InvalidDepositsValue(depositsValue, _depositsCount); } bytes32 withdrawalCredentials = getWithdrawalCredentials(); diff --git a/contracts/0.8.9/test_helpers/StakingModuleMock.sol b/contracts/0.8.9/test_helpers/StakingModuleMock.sol index 00d1227ad..59ae38f0f 100644 --- a/contracts/0.8.9/test_helpers/StakingModuleMock.sol +++ b/contracts/0.8.9/test_helpers/StakingModuleMock.sol @@ -4,6 +4,7 @@ /* See contracts/COMPILERS.md */ pragma solidity 0.8.9; +import {Math256} from "../../common/lib/Math256.sol"; import {IStakingModule} from "../interfaces/IStakingModule.sol"; contract StakingModuleMock is IStakingModule { @@ -11,6 +12,7 @@ contract StakingModuleMock is IStakingModule { uint256 private _activeValidatorsCount; uint256 private _availableValidatorsCount; uint256 private _nonce; + uint256 private nodeOperatorsCount; function getActiveValidatorsCount() public view returns (uint256) { return _activeValidatorsCount; @@ -32,6 +34,17 @@ contract StakingModuleMock is IStakingModule { depositableValidatorsCount = _availableValidatorsCount; } + struct NodeOperatorSummary { + bool isTargetLimitActive; + uint256 targetValidatorsCount; + uint256 stuckValidatorsCount; + uint256 refundedValidatorsCount; + uint256 stuckPenaltyEndTimestamp; + uint256 totalExitedValidators; + uint256 totalDepositedValidators; + uint256 depositableValidatorsCount; + } + mapping(uint256 => NodeOperatorSummary) internal nodeOperatorsSummary; function getNodeOperatorSummary(uint256 _nodeOperatorId) external view returns ( bool isTargetLimitActive, uint256 targetValidatorsCount, @@ -41,7 +54,28 @@ contract StakingModuleMock is IStakingModule { uint256 totalExitedValidators, uint256 totalDepositedValidators, uint256 depositableValidatorsCount - ) {} + ) { + NodeOperatorSummary storage _summary = nodeOperatorsSummary[_nodeOperatorId]; + isTargetLimitActive = _summary.isTargetLimitActive; + targetValidatorsCount = _summary.targetValidatorsCount; + stuckValidatorsCount = _summary.stuckValidatorsCount; + refundedValidatorsCount = _summary.refundedValidatorsCount; + stuckPenaltyEndTimestamp = _summary.stuckPenaltyEndTimestamp; + totalExitedValidators = _summary.totalExitedValidators; + totalDepositedValidators = _summary.totalDepositedValidators; + depositableValidatorsCount = _summary.depositableValidatorsCount; + } + function setNodeOperatorSummary(uint256 _nodeOperatorId, NodeOperatorSummary memory _summary) external { + NodeOperatorSummary storage summary = nodeOperatorsSummary[_nodeOperatorId]; + summary.isTargetLimitActive = _summary.isTargetLimitActive; + summary.targetValidatorsCount = _summary.targetValidatorsCount; + summary.stuckValidatorsCount = _summary.stuckValidatorsCount; + summary.refundedValidatorsCount = _summary.refundedValidatorsCount; + summary.stuckPenaltyEndTimestamp = _summary.stuckPenaltyEndTimestamp; + summary.totalExitedValidators = _summary.totalExitedValidators; + summary.totalDepositedValidators = _summary.totalDepositedValidators; + summary.depositableValidatorsCount = _summary.depositableValidatorsCount; + } function getNonce() external view returns (uint256) { return _nonce; @@ -51,7 +85,11 @@ contract StakingModuleMock is IStakingModule { _nonce = _newNonce; } - function getNodeOperatorsCount() external view returns (uint256) {} + function getNodeOperatorsCount() public view returns (uint256) { return nodeOperatorsCount; } + + function testing__setNodeOperatorsCount(uint256 _count) external { + nodeOperatorsCount = _count; + } function getActiveNodeOperatorsCount() external view returns (uint256) {} @@ -60,9 +98,27 @@ contract StakingModuleMock is IStakingModule { function getNodeOperatorIds(uint256 _offset, uint256 _limit) external view - returns (uint256[] memory nodeOperatorIds) {} + returns (uint256[] memory nodeOperatorIds) { + uint256 nodeOperatorsCount = getNodeOperatorsCount(); + if (_offset < nodeOperatorsCount && _limit != 0) { + nodeOperatorIds = new uint256[](Math256.min(_limit, nodeOperatorsCount - _offset)); + for (uint256 i = 0; i < nodeOperatorIds.length; ++i) { + nodeOperatorIds[i] = _offset + i; + } + } + + } - function onRewardsMinted(uint256 _totalShares) external {} + /// @dev onRewardsMinted mock + struct Call_onRewardsMinted { + uint256 callCount; + uint256 totalShares; + } + Call_onRewardsMinted public lastCall_onRewardsMinted; + function onRewardsMinted(uint256 _totalShares) external { + lastCall_onRewardsMinted.totalShares += _totalShares; + ++lastCall_onRewardsMinted.callCount; + } struct Call_updateValidatorsCount { bytes nodeOperatorIds; @@ -91,7 +147,17 @@ contract StakingModuleMock is IStakingModule { ++lastCall_updateExitedValidatorsCount.callCount; } - function updateRefundedValidatorsCount(uint256 _nodeOperatorId, uint256 _refundedValidatorsCount) external {} + struct Call_updateRefundedValidatorsCount { + uint256 nodeOperatorId; + uint256 refundedValidatorsCount; + uint256 callCount; + } + Call_updateRefundedValidatorsCount public lastCall_updateRefundedValidatorsCount; + function updateRefundedValidatorsCount(uint256 _nodeOperatorId, uint256 _refundedValidatorsCount) external { + lastCall_updateRefundedValidatorsCount.nodeOperatorId = _nodeOperatorId; + lastCall_updateRefundedValidatorsCount.refundedValidatorsCount = _refundedValidatorsCount; + ++lastCall_updateRefundedValidatorsCount.callCount; + } uint256 public callCount_onExitedAndStuckValidatorsCountsUpdated; @@ -99,11 +165,23 @@ contract StakingModuleMock is IStakingModule { ++callCount_onExitedAndStuckValidatorsCountsUpdated; } + struct Call_unsafeUpdateValidatorsCount { + uint256 nodeOperatorId; + uint256 exitedValidatorsKeysCount; + uint256 stuckValidatorsKeysCount; + uint256 callCount; + } + Call_unsafeUpdateValidatorsCount public lastCall_unsafeUpdateValidatorsCount; function unsafeUpdateValidatorsCount( - uint256 /* _nodeOperatorId */, - uint256 /* _exitedValidatorsKeysCount */, - uint256 /* _stuckValidatorsKeysCount */ - ) external {} + uint256 _nodeOperatorId, + uint256 _exitedValidatorsKeysCount, + uint256 _stuckValidatorsKeysCount + ) external { + lastCall_unsafeUpdateValidatorsCount.nodeOperatorId = _nodeOperatorId; + lastCall_unsafeUpdateValidatorsCount.exitedValidatorsKeysCount = _exitedValidatorsKeysCount; + lastCall_unsafeUpdateValidatorsCount.stuckValidatorsKeysCount = _stuckValidatorsKeysCount; + ++lastCall_unsafeUpdateValidatorsCount.callCount; + } function onWithdrawalCredentialsChanged() external { _availableValidatorsCount = _activeValidatorsCount; diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index 756ae6ed7..1f4227201 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":[{"internalType":"uint256","name":"etherValue","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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.8.9/staking-router-deposits.test.js b/test/0.8.9/staking-router-deposits.test.js deleted file mode 100644 index 51b7c3811..000000000 --- a/test/0.8.9/staking-router-deposits.test.js +++ /dev/null @@ -1,124 +0,0 @@ -const { contract, ethers, web3 } = require('hardhat') - -const { EvmSnapshot } = require('../helpers/blockchain') -const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') -const { deployProtocol } = require('../helpers/protocol') - -const { ETH, genKeys, toBN } = require('../helpers/utils') -const { assert } = require('../helpers/assert') - -const ADDRESS_1 = '0x0000000000000000000000000000000000000001' -const ADDRESS_2 = '0x0000000000000000000000000000000000000002' - -contract('StakingRouter', ([depositor, stranger]) => { - let snapshot - let depositContract, stakingRouter - let lido, operators, voting - - before(async () => { - const deployed = await deployProtocol({ - depositSecurityModuleFactory: async () => { - return { address: depositor } - }, - }) - - lido = deployed.pool - stakingRouter = deployed.stakingRouter - operators = await setupNodeOperatorsRegistry(deployed, true) - voting = deployed.voting.address - depositContract = deployed.depositContract - snapshot = new EvmSnapshot(ethers.provider) - await snapshot.make() - }) - - afterEach(async () => { - await snapshot.rollback() - }) - - describe('Make deposit', () => { - beforeEach(async () => { - await stakingRouter.addStakingModule( - 'Curated', - operators.address, - 10_000, // 100 % _targetShare - 1_000, // 10 % _moduleFee - 5_000, // 50 % _treasuryFee - { from: voting } - ) - }) - - it('Lido.deposit() :: check permissioness', async () => { - const maxDepositsCount = 150 - - await web3.eth.sendTransaction({ value: ETH(maxDepositsCount * 32), to: lido.address, from: stranger }) - assert.equals(await lido.getBufferedEther(), ETH(maxDepositsCount * 32 + 1)) - - const [curated] = await stakingRouter.getStakingModules() - - await assert.reverts(lido.deposit(maxDepositsCount, curated.id, '0x', { from: stranger }), 'APP_AUTH_DSM_FAILED') - await assert.reverts(lido.deposit(maxDepositsCount, curated.id, '0x', { from: voting }), 'APP_AUTH_DSM_FAILED') - - await assert.reverts( - stakingRouter.deposit(maxDepositsCount, curated.id, '0x', { from: voting }), - 'AppAuthLidoFailed()' - ) - }) - - it('Lido.deposit() :: check deposit with keys', async () => { - // balance are initial - assert.equals(await web3.eth.getBalance(lido.address), ETH(1)) - assert.equals(await web3.eth.getBalance(stakingRouter.address), 0) - - const sendEthForKeys = ETH(101 * 32 - 1) - const totalPooledEther = ETH(101 * 32) - const maxDepositsCount = 100 - - await web3.eth.sendTransaction({ value: sendEthForKeys, to: lido.address, from: stranger }) - assert.equals(await lido.getBufferedEther(), totalPooledEther) - - // updated balance are lido 100 && sr 0 - assert.equals(await web3.eth.getBalance(lido.address), totalPooledEther) - assert.equals(await web3.eth.getBalance(stakingRouter.address), 0) - - const [curated] = await stakingRouter.getStakingModules() - - // prepare node operators - await operators.addNodeOperator('1', ADDRESS_1, { from: voting }) - await operators.addNodeOperator('2', ADDRESS_2, { from: voting }) - - // add 150 keys to module - const keysAmount = 50 - const keys1 = genKeys(keysAmount) - await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) - await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) - await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) - - await operators.setNodeOperatorStakingLimit(0, 100000, { from: voting }) - await operators.setNodeOperatorStakingLimit(1, 100000, { from: voting }) - - const receipt = await lido.methods[`deposit(uint256,uint256,bytes)`](maxDepositsCount, curated.id, '0x', { - from: depositor, - }) - - assert.equals(await depositContract.totalCalls(), 100, 'invalid deposits count') - - // on deposit we return balance to Lido - assert.equals(await web3.eth.getBalance(lido.address), ETH(32), 'invalid lido balance') - assert.equals(await web3.eth.getBalance(stakingRouter.address), 0, 'invalid staking_router balance') - - assert.equals(await lido.getBufferedEther(), ETH(32), 'invalid total buffer') - - assert.emits(receipt, 'Unbuffered', { amount: ETH(maxDepositsCount * 32) }) - }) - - it('Lido.deposit() :: revert if stakingModuleId more than uint24', async () => { - const maxDepositsCount = 100 - const maxModuleId = toBN(2).pow(toBN(24)) - - await assert.reverts( - lido.methods[`deposit(uint256,uint256,bytes)`](maxDepositsCount, maxModuleId, '0x', { from: depositor }), - 'StakingModuleIdTooLarge()' - ) - }) - }) -}) diff --git a/test/0.8.9/staking-router/digest.test.js b/test/0.8.9/staking-router/digest.test.js new file mode 100644 index 000000000..75c53bb63 --- /dev/null +++ b/test/0.8.9/staking-router/digest.test.js @@ -0,0 +1,238 @@ +const { artifacts, contract, ethers } = require('hardhat') +const { MaxUint256 } = require('@ethersproject/constants') +const { assert } = require('../../helpers/assert') +const { EvmSnapshot } = require('../../helpers/blockchain') +const { toNum } = require('../../helpers/utils') + +const OssifiableProxy = artifacts.require('OssifiableProxy.sol') +const DepositContractMock = artifacts.require('DepositContractMock') +const StakingRouter = artifacts.require('StakingRouter.sol') +const StakingModuleMock = artifacts.require('StakingModuleMock.sol') + +let depositContract, router +let module1, module2 + +contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { + const evmSnapshot = new EvmSnapshot(ethers.provider) + + const snapshot = () => evmSnapshot.make() + const revert = () => evmSnapshot.revert() + + before(async () => { + depositContract = await DepositContractMock.new({ from: deployer }) + + const impl = await StakingRouter.new(depositContract.address, { from: deployer }) + const proxy = await OssifiableProxy.new(impl.address, deployer, '0x') + router = await StakingRouter.at(proxy.address) + ;[module1, module2] = await Promise.all([ + StakingModuleMock.new({ from: deployer }), + StakingModuleMock.new({ from: deployer }), + ]) + + const wc = '0x'.padEnd(66, '1234') + await router.initialize(admin, lido, wc, { from: deployer }) + }) + + describe('getNodeOperatorDigests() by module id and list of nopIds', async () => { + before(snapshot) + after(revert) + + let module1Id, module2Id + const nodeOperator1 = 0 + let StakingModuleDigest, StakingModuleDigest2 + + it('reverts if moduleId does not exists', async () => { + await assert.reverts(router.getNodeOperatorDigests(0, []), 'StakingModuleUnregistered()') + }) + + it('add one module', async () => { + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await router.addStakingModule( + 'module 1', + module1.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: admin } + ) + module1Id = +(await router.getStakingModuleIds())[0] + }) + + it('add second module', async () => { + await router.addStakingModule( + 'module 2', + module2.address, + 9_000, // 100 % _targetShare + 2_000, // 10 % _moduleFee + 3_000, // 50 % _treasuryFee + { from: admin } + ) + module2Id = +(await router.getStakingModuleIds())[1] + }) + + it('get digest with empty nodeOperators', async () => { + const digests = await router.getNodeOperatorDigests(module1Id, []) + assert.equal(digests.length, 0) + }) + + it('add first node operator summary', async () => { + const summary = { + isTargetLimitActive: true, + targetValidatorsCount: 1, + stuckValidatorsCount: 2, + refundedValidatorsCount: 3, + stuckPenaltyEndTimestamp: 4, + totalExitedValidators: 5, + totalDepositedValidators: 6, + depositableValidatorsCount: 7, + } + await module1.setNodeOperatorSummary(nodeOperator1, summary) + + await module1.testing__setNodeOperatorsCount(1) + }) + + it('get digest with one nodeOperator', async () => { + const digests = await router.getNodeOperatorDigests(module1Id, [nodeOperator1]) + assert.equal(digests.length, 1) + + assert.equal(digests[0].id, 0) + assert.equal(digests[0].isActive, false) + assert.sameOrderedMembers(toNum(digests[0].summary), [1, 1, 2, 3, 4, 5, 6, 7]) + }) + + it('get digest with one nodeOperator and one non existi g', async () => { + const digests = await router.getNodeOperatorDigests(module1Id, [nodeOperator1, 123]) + assert.equal(digests.length, 2) + + assert.equal(digests[0].id, 0) + assert.equal(digests[0].isActive, false) + assert.sameOrderedMembers(toNum(digests[0].summary), [1, 1, 2, 3, 4, 5, 6, 7]) + + assert.equal(digests[1].id, 123) + assert.equal(digests[1].isActive, false) + assert.sameOrderedMembers(toNum(digests[1].summary), [0, 0, 0, 0, 0, 0, 0, 0]) + }) + + it('getNodeOperatorDigests(uint256,uint256,uint256) - reverts module unregistered', async () => { + await assert.reverts( + router.methods[`getNodeOperatorDigests(uint256,uint256,uint256)`](0, 0, 0), + 'StakingModuleUnregistered()' + ) + }) + it('getNodeOperatorDigests(uint256,uint256,uint256) - module2 without operators', async () => { + let digests = await router.methods[`getNodeOperatorDigests(uint256,uint256,uint256)`](module2Id, 0, 0) + assert.equal(digests.length, 0) + + digests = await router.methods[`getNodeOperatorDigests(uint256,uint256,uint256)`](module2Id, 0, 1) + assert.equal(digests.length, 0) + + digests = await router.methods[`getNodeOperatorDigests(uint256,uint256,uint256)`](module2Id, 0, MaxUint256) + assert.equal(digests.length, 0) + + digests = await router.methods[`getNodeOperatorDigests(uint256,uint256,uint256)`]( + module2Id, + MaxUint256, + MaxUint256 + ) + assert.equal(digests.length, 0) + }) + + it('getNodeOperatorDigests(uint256,uint256,uint256) - module1 with node operators', async () => { + let digests = await router.methods[`getNodeOperatorDigests(uint256,uint256,uint256)`](module1Id, 0, 0) + assert.equal(digests.length, 0) + + digests = await router.methods[`getNodeOperatorDigests(uint256,uint256,uint256)`](module1Id, 0, MaxUint256) + assert.equal(digests.length, 1) + + assert.equal(digests[0].id, 0) + assert.equal(digests[0].isActive, false) + assert.sameOrderedMembers(toNum(digests[0].summary), [1, 1, 2, 3, 4, 5, 6, 7]) + }) + + it('getAllNodeOperatorDigests(uint256) - module unregistered', async () => { + await assert.reverts(router.getAllNodeOperatorDigests(999), 'StakingModuleUnregistered()') + }) + it('getAllNodeOperatorDigests(uint256) - digests works', async () => { + const digests = await router.getAllNodeOperatorDigests(module1Id) + assert.equal(digests.length, 1) + + assert.equal(digests[0].id, 0) + assert.equal(digests[0].isActive, false) + assert.sameOrderedMembers(toNum(digests[0].summary), [1, 1, 2, 3, 4, 5, 6, 7]) + }) + + it('reverts getAllNodeOperatorDigests module unregistered', async () => { + await assert.reverts(router.getAllNodeOperatorDigests(0), 'StakingModuleUnregistered()') + }) + it('getStakingModuleDigests([]uint256) - reverts modules unregistered', async () => { + await assert.reverts(router.getStakingModuleDigests([0, 999]), 'StakingModuleUnregistered()') + }) + it('getStakingModuleDigests([]uint256) - digests works', async () => { + await module1.setTotalExitedValidatorsCount(11) + await module1.setActiveValidatorsCount(22) + await module1.setAvailableKeysCount(33) + + const digests = await router.getStakingModuleDigests([module1Id, module2Id]) + assert.equal(digests.length, 2) + + StakingModuleDigest = { + nodeOperatorsCount: '1', + activeNodeOperatorsCount: '0', + state: Object.values({ + id: module1Id.toString(), + stakingModuleAddress: module1.address, + stakingModuleFee: '1000', + treasuryFee: '5000', + targetShare: '10000', + status: '0', + name: 'module 1', + lastDepositAt: '0', + lastDepositBlock: '0', + exitedValidatorsCount: '0', + }), + summary: Object.values({ + totalExitedValidators: '11', + totalDepositedValidators: '22', + depositableValidatorsCount: '33', + }), + } + + assert.deepEqual(digests[0], Object.values(StakingModuleDigest)) + + StakingModuleDigest2 = { + nodeOperatorsCount: '0', + activeNodeOperatorsCount: '0', + state: Object.values({ + id: module2Id.toString(), + stakingModuleAddress: module2.address, + stakingModuleFee: '2000', + treasuryFee: '3000', + targetShare: '9000', + status: '0', + name: 'module 2', + lastDepositAt: '0', + lastDepositBlock: '0', + exitedValidatorsCount: '0', + }), + summary: Object.values({ + totalExitedValidators: '0', + totalDepositedValidators: '0', + depositableValidatorsCount: '0', + }), + } + assert.deepEqual(digests[1], Object.values(StakingModuleDigest2)) + + const digests2 = await router.getStakingModuleDigests([module1Id, module2Id]) + assert.equal(digests2.length, 2) + }) + + it('getAllStakingModuleDigests() works', async () => { + // + const digests2 = await router.getAllStakingModuleDigests() + assert.equal(digests2.length, 2) + + assert.deepEqual(digests2[0], Object.values(StakingModuleDigest)) + assert.deepEqual(digests2[1], Object.values(StakingModuleDigest2)) + }) + }) +}) diff --git a/test/0.8.9/staking-router/rewards-distribution.test.js b/test/0.8.9/staking-router/rewards-distribution.test.js new file mode 100644 index 000000000..73808dd49 --- /dev/null +++ b/test/0.8.9/staking-router/rewards-distribution.test.js @@ -0,0 +1,391 @@ +const { contract, ethers } = require('hardhat') +const { BN } = require('bn.js') + +const { assert } = require('../../helpers/assert') +const { EvmSnapshot } = require('../../helpers/blockchain') +const { toNum } = require('../../helpers/utils') +const { deployProtocol } = require('../../helpers/protocol') + +const { setupNodeOperatorsRegistry } = require('../../helpers/staking-modules') + +const ADDRESS_1 = '0x0000000000000000000000000000000000000001' +const ADDRESS_2 = '0x0000000000000000000000000000000000000002' +const ADDRESS_3 = '0x0000000000000000000000000000000000000003' + +const StakingModuleStatus = { + Active: 0, // deposits and rewards allowed + DepositsPaused: 1, // deposits NOT allowed, rewards allowed + Stopped: 2, // deposits and rewards NOT allowed +} + +let router +let operators, solo1, solo2, solo3 +let module1Id, module2Id, module3Id, module4Id +let config + +contract('StakingRouter', ([deployer, admin, depositor, stranger]) => { + const evmSnapshot = new EvmSnapshot(ethers.provider) + + const snapshot = () => evmSnapshot.make() + const revert = () => evmSnapshot.revert() + + before(async () => { + const deployed = await deployProtocol({ + depositSecurityModuleFactory: async () => { + return { address: depositor } + }, + }) + + router = deployed.stakingRouter + operators = await setupNodeOperatorsRegistry(deployed, true) + solo1 = await setupNodeOperatorsRegistry(deployed, true) + solo2 = await setupNodeOperatorsRegistry(deployed, true) + solo3 = await setupNodeOperatorsRegistry(deployed, true) + }) + + describe('getNodeOperatorDigests() by module id and list of nopIds', async () => { + before(snapshot) + after(revert) + + it('getStakingRewardsDistribution() - without modules', async () => { + const distribution = await router.getStakingRewardsDistribution() + + const lengthShouldBe = distribution.stakingModuleFees.length + assert.equal(distribution.recipients.length, lengthShouldBe) + assert.equal(distribution.stakingModuleIds.length, lengthShouldBe) + assert.equal(distribution.stakingModuleFees.length, lengthShouldBe) + + assert.equal(distribution.totalFee, 0) + assert.equal(+distribution.precisionPoints, new BN(10).pow(new BN(20))) // 100 * 10^18 + }) + + it('add one module', async () => { + await router.addStakingModule( + 'Curated', + operators.address, + 10_000, // 100 % _targetShare + 5000, // 50 % _moduleFee + 5000, // 50 % _treasuryFee + { from: admin } + ) + module1Id = +(await router.getStakingModuleIds())[0] + }) + + it('getStakingRewardsDistribution() - one module - no validators', async () => { + const distribution = await router.getStakingRewardsDistribution() + + const lengthShouldBe = distribution.stakingModuleFees.length + assert.equal(distribution.recipients.length, lengthShouldBe) + assert.equal(distribution.stakingModuleIds.length, lengthShouldBe) + assert.equal(distribution.stakingModuleFees.length, lengthShouldBe) + + assert.equal(distribution.totalFee, 0) + assert.equal(+distribution.precisionPoints, new BN(10).pow(new BN(20))) // 100 * 10^18 + }) + + it('prepare node operators', async () => { + const config = { + name: 'test', + rewardAddress: ADDRESS_1, + totalSigningKeysCount: 13, + vettedSigningKeysCount: 4, + depositedSigningKeysCount: 7, + exitedSigningKeysCount: 5, + } + + await operators.testing_addNodeOperator( + config.name, + config.rewardAddress, + config.totalSigningKeysCount, + config.vettedSigningKeysCount, + config.depositedSigningKeysCount, + config.exitedSigningKeysCount + ) + }) + + it('getStakingRewardsDistribution() - reverts if total fee >= 100%', async () => { + await assert.reverts(router.getStakingRewardsDistribution(), 'ValueOver100Percent("totalFee")') + }) + + it('update module - set fee and treasury fee', async () => { + await router.updateStakingModule(module1Id, 10_000, 500, 500, { from: admin }) + }) + + it('getStakingRewardsDistribution() - works for one module', async () => { + const distribution = await router.getStakingRewardsDistribution() + + const lengthShouldBe = distribution.stakingModuleFees.length + assert.equal(distribution.recipients.length, lengthShouldBe) + assert.equal(distribution.stakingModuleIds.length, lengthShouldBe) + assert.equal(distribution.stakingModuleFees.length, lengthShouldBe) + + assert.deepEqual(distribution.recipients, [operators.address]) + assert.deepEqual(toNum(distribution.stakingModuleIds), [1]) + assert.deepEqual(toNum(distribution.stakingModuleFees), [5 * 10 ** 18]) + assert.equal(toNum(distribution.totalFee), 10 * 10 ** 18) + }) + + it('add 2 modules', async () => { + await router.addStakingModule( + 'Solo1', + solo1.address, + 3000, // 30 % _targetShare + 500, // 50 % _moduleFee + 500, // 50 % _treasuryFee + { from: admin } + ) + module2Id = +(await router.getStakingModuleIds())[1] + + await router.addStakingModule( + 'Solo2', + solo2.address, + 2000, // 20 % _targetShare + 500, // 40 % _moduleFee + 500, // 40 % _treasuryFee + { from: admin } + ) + module3Id = +(await router.getStakingModuleIds())[2] + + await router.addStakingModule( + 'Solo3', + solo3.address, + 2000, // 20 % _targetShare + 700, // 40 % _moduleFee + 300, // 40 % _treasuryFee + { from: admin } + ) + module4Id = +(await router.getStakingModuleIds())[3] + }) + + it('prepare node operators for 3d module', async () => { + config = { + name: 'test3', + rewardAddress: ADDRESS_2, + totalSigningKeysCount: 10, + vettedSigningKeysCount: 10, + depositedSigningKeysCount: 7, + exitedSigningKeysCount: 1, + } + + await solo2.testing_addNodeOperator( + config.name, + config.rewardAddress, + config.totalSigningKeysCount, + config.vettedSigningKeysCount, + config.depositedSigningKeysCount, + config.exitedSigningKeysCount + ) + + config = { + name: 'test4', + rewardAddress: ADDRESS_3, + totalSigningKeysCount: 13, + vettedSigningKeysCount: 4, + depositedSigningKeysCount: 7, + exitedSigningKeysCount: 5, + } + + await solo3.testing_addNodeOperator( + config.name, + config.rewardAddress, + config.totalSigningKeysCount, + config.vettedSigningKeysCount, + config.depositedSigningKeysCount, + config.exitedSigningKeysCount + ) + }) + + it('getStakingRewardsDistribution() - skip one module without active validators', async () => { + await router.setStakingModuleStatus(module4Id, StakingModuleStatus.Stopped, { from: admin }) + + const distribution = await router.getStakingRewardsDistribution() + + const lengthShouldBe = distribution.stakingModuleFees.length + assert.equal(distribution.recipients.length, lengthShouldBe) + assert.equal(distribution.stakingModuleIds.length, lengthShouldBe) + assert.equal(distribution.stakingModuleFees.length, lengthShouldBe) + + assert.deepEqual(distribution.recipients, [operators.address, solo2.address, solo3.address]) + assert.deepEqual(toNum(distribution.stakingModuleIds), [module1Id, module2Id, module3Id]) + assert.deepEqual(toNum(distribution.stakingModuleFees), [1 * 10 ** 18, 3 * 10 ** 18, 0]) + assert.equal(toNum(distribution.totalFee), 10 * 10 ** 18) + }) + }) + + describe('getStakingFeeAggregateDistribution()', async () => { + before(snapshot) + after(revert) + + it('works with empty modules', async () => { + const distribution = await router.getStakingFeeAggregateDistribution() + + assert.equal(+distribution.modulesFee, 0) + assert.equal(+distribution.treasuryFee, 0) + assert.equal(+distribution.basePrecision, new BN(10).pow(new BN(20))) + }) + + it('add one module', async () => { + await router.addStakingModule( + 'Curated', + operators.address, + 10_000, // 100 % _targetShare + 500, // 50 % _moduleFee + 500, // 50 % _treasuryFee + { from: admin } + ) + module1Id = +(await router.getStakingModuleIds())[0] + }) + + it('prepare node operators', async () => { + const config = { + name: 'test', + rewardAddress: ADDRESS_1, + totalSigningKeysCount: 13, + vettedSigningKeysCount: 4, + depositedSigningKeysCount: 7, + exitedSigningKeysCount: 5, + } + + await operators.testing_addNodeOperator( + config.name, + config.rewardAddress, + config.totalSigningKeysCount, + config.vettedSigningKeysCount, + config.depositedSigningKeysCount, + config.exitedSigningKeysCount + ) + }) + + it('works with empty modules', async () => { + const distribution = await router.getStakingFeeAggregateDistribution() + + assert.equal(+distribution.modulesFee, 5 * 10 ** 18) + assert.equal(+distribution.treasuryFee, 5 * 10 ** 18) + assert.equal(+distribution.basePrecision, new BN(10).pow(new BN(20))) + }) + + it('add next module', async () => { + await router.addStakingModule( + 'Solo1', + solo1.address, + 10_000, // 100 % _targetShare + 500, // 50 % _moduleFee + 500, // 50 % _treasuryFee + { from: admin } + ) + module2Id = +(await router.getStakingModuleIds())[1] + + const config = { + name: 'test', + rewardAddress: ADDRESS_1, + totalSigningKeysCount: 13, + vettedSigningKeysCount: 4, + depositedSigningKeysCount: 7, + exitedSigningKeysCount: 5, + } + + await operators.testing_addNodeOperator( + config.name, + config.rewardAddress, + config.totalSigningKeysCount, + config.vettedSigningKeysCount, + config.depositedSigningKeysCount, + config.exitedSigningKeysCount + ) + }) + + it('works 2 active modules', async () => { + const distribution = await router.getStakingFeeAggregateDistribution() + + assert.equal(+distribution.modulesFee, 5 * 10 ** 18) + assert.equal(+distribution.treasuryFee, 5 * 10 ** 18) + assert.equal(+distribution.basePrecision, new BN(10).pow(new BN(20))) + }) + + it('add next module', async () => { + await router.addStakingModule( + 'Solo2', + solo2.address, + 2000, // 20 % _targetShare + 500, // 40 % _moduleFee + 500, // 40 % _treasuryFee + { from: admin } + ) + module3Id = +(await router.getStakingModuleIds())[2] + + await router.addStakingModule( + 'Solo3', + solo3.address, + 2000, // 20 % _targetShare + 500, // 40 % _moduleFee + 500, // 40 % _treasuryFee + { from: admin } + ) + module4Id = +(await router.getStakingModuleIds())[3] + }) + + it('prepare node operators for 3d module', async () => { + config = { + name: 'test3', + rewardAddress: ADDRESS_3, + totalSigningKeysCount: 10, + vettedSigningKeysCount: 10, + depositedSigningKeysCount: 7, + exitedSigningKeysCount: 5, + } + + await solo2.testing_addNodeOperator( + config.name, + config.rewardAddress, + config.totalSigningKeysCount, + config.vettedSigningKeysCount, + config.depositedSigningKeysCount, + config.exitedSigningKeysCount + ) + + config = { + name: 'test4', + rewardAddress: ADDRESS_3, + totalSigningKeysCount: 13, + vettedSigningKeysCount: 4, + depositedSigningKeysCount: 7, + exitedSigningKeysCount: 5, + } + + await solo3.testing_addNodeOperator( + config.name, + config.rewardAddress, + config.totalSigningKeysCount, + config.vettedSigningKeysCount, + config.depositedSigningKeysCount, + config.exitedSigningKeysCount + ) + }) + + it('works 2 active modules and 1 stopped and 1 without active validators', async () => { + await router.setStakingModuleStatus(module4Id, StakingModuleStatus.Stopped, { from: admin }) + let distribution = await router.getStakingRewardsDistribution() + + const lengthShouldBe = distribution.stakingModuleFees.length + assert.equal(distribution.recipients.length, lengthShouldBe) + assert.equal(distribution.stakingModuleIds.length, lengthShouldBe) + assert.equal(distribution.stakingModuleFees.length, lengthShouldBe) + + assert.deepEqual(distribution.recipients, [operators.address, solo2.address, solo3.address]) + assert.deepEqual(toNum(distribution.stakingModuleIds), [module1Id, module2Id, module3Id]) + assert.deepEqual(toNum(distribution.stakingModuleFees), [2.5 * 10 ** 18, 1.25 * 10 ** 18, 0]) + assert.equal(toNum(distribution.totalFee), 10 * 10 ** 18) + + distribution = await router.getStakingFeeAggregateDistribution() + assert.equal(+distribution.modulesFee, 3.75 * 10 ** 18) + assert.equal(+distribution.treasuryFee, 6.25 * 10 ** 18) + assert.equal(+distribution.basePrecision, new BN(10).pow(new BN(20))) + }) + + it('getTotalFeeE4Precision', async () => { + const totalFeeE4 = await router.getTotalFeeE4Precision() + const fee = await router.getStakingFeeAggregateDistributionE4Precision() + assert.equal(+totalFeeE4, +fee.modulesFee + +fee.treasuryFee) + }) + }) +}) diff --git a/test/0.8.9/staking-router-allocation-combinations.test.js b/test/0.8.9/staking-router/staking-router-allocation-combinations.test.js similarity index 99% rename from test/0.8.9/staking-router-allocation-combinations.test.js rename to test/0.8.9/staking-router/staking-router-allocation-combinations.test.js index 5913aa52b..2c31f922a 100644 --- a/test/0.8.9/staking-router-allocation-combinations.test.js +++ b/test/0.8.9/staking-router/staking-router-allocation-combinations.test.js @@ -1,5 +1,5 @@ const { artifacts, contract, ethers } = require('hardhat') -const { assert } = require('../helpers/assert') +const { assert } = require('../../helpers/assert') const { BigNumber } = require('ethers') const StakingRouter = artifacts.require('StakingRouterMock.sol') const StakingModuleMock = artifacts.require('StakingModuleMock.sol') diff --git a/test/0.8.9/staking-router-deposits-allocation.test.js b/test/0.8.9/staking-router/staking-router-deposits-allocation.test.js similarity index 99% rename from test/0.8.9/staking-router-deposits-allocation.test.js rename to test/0.8.9/staking-router/staking-router-deposits-allocation.test.js index 8cffae23a..630a54445 100644 --- a/test/0.8.9/staking-router-deposits-allocation.test.js +++ b/test/0.8.9/staking-router/staking-router-deposits-allocation.test.js @@ -1,5 +1,5 @@ const { artifacts, contract, ethers } = require('hardhat') -const { assert } = require('../helpers/assert') +const { assert } = require('../../helpers/assert') const StakingRouter = artifacts.require('StakingRouterMock.sol') const StakingModuleMock = artifacts.require('StakingModuleMock.sol') diff --git a/test/0.8.9/staking-router/staking-router-deposits.test.js b/test/0.8.9/staking-router/staking-router-deposits.test.js new file mode 100644 index 000000000..9739aa446 --- /dev/null +++ b/test/0.8.9/staking-router/staking-router-deposits.test.js @@ -0,0 +1,255 @@ +const { contract, ethers, web3 } = require('hardhat') + +const { EvmSnapshot } = require('../../helpers/blockchain') +const { setupNodeOperatorsRegistry } = require('../../helpers/staking-modules') +const { deployProtocol } = require('../../helpers/protocol') + +const { ETH, genKeys, toBN } = require('../../helpers/utils') +const { assert } = require('../../helpers/assert') +const { ZERO_BYTES32 } = require('../../helpers/constants') + +const ADDRESS_1 = '0x0000000000000000000000000000000000000001' +const ADDRESS_2 = '0x0000000000000000000000000000000000000002' + +contract('StakingRouter', ([depositor, stranger]) => { + const evmSnapshot = new EvmSnapshot(ethers.provider) + let depositContract, router + let lido, operators, voting + let curatedModuleId + + const snapshot = () => evmSnapshot.make() + const revert = () => evmSnapshot.revert() + + before(async () => { + const deployed = await deployProtocol({ + depositSecurityModuleFactory: async () => { + return { address: depositor } + }, + }) + + lido = deployed.pool + router = deployed.stakingRouter + operators = await setupNodeOperatorsRegistry(deployed, true) + voting = deployed.voting.address + depositContract = deployed.depositContract + + // add role + await router.grantRole(await router.MANAGE_WITHDRAWAL_CREDENTIALS_ROLE(), depositor, { from: depositor }) + }) + + describe('Make deposit', () => { + before(snapshot) + after(revert) + + it('add module', async () => { + await router.addStakingModule( + 'Curated', + operators.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: voting } + ) + curatedModuleId = +(await router.getStakingModuleIds())[0] + }) + + it('reverts if no DSM role', async () => { + const depositsCount = 150 + + await assert.reverts( + lido.deposit(depositsCount, curatedModuleId, '0x', { from: stranger }), + 'APP_AUTH_DSM_FAILED' + ) + await assert.reverts(lido.deposit(depositsCount, curatedModuleId, '0x', { from: voting }), 'APP_AUTH_DSM_FAILED') + }) + + it('reverts if deposit() not from lido address', async () => { + const depositsCount = 150 + await assert.reverts( + router.deposit(depositsCount, curatedModuleId, '0x', { from: voting }), + 'AppAuthLidoFailed()' + ) + }) + + it('reverts if stakingModuleId more than uint24', async () => { + const depositsCount = 100 + const maxModuleId = toBN(2).pow(toBN(24)) + + await assert.reverts( + lido.methods[`deposit(uint256,uint256,bytes)`](depositsCount, maxModuleId, '0x', { from: depositor }), + 'StakingModuleIdTooLarge()' + ) + }) + + it('add initial balance and keys', async () => { + // balance are initial + assert.equals(await web3.eth.getBalance(lido.address), ETH(1)) + assert.equals(await web3.eth.getBalance(router.address), 0) + + const sendEthForKeys = ETH(101 * 32 - 1) + const totalPooledEther = ETH(101 * 32) + + await web3.eth.sendTransaction({ value: sendEthForKeys, to: lido.address, from: stranger }) + assert.equals(await lido.getBufferedEther(), totalPooledEther) + + // updated balance are lido 100 && sr 0 + assert.equals(await web3.eth.getBalance(lido.address), totalPooledEther) + assert.equals(await web3.eth.getBalance(router.address), 0) + + // prepare node operators + await operators.addNodeOperator('1', ADDRESS_1, { from: voting }) + await operators.addNodeOperator('2', ADDRESS_2, { from: voting }) + + // add 150 keys to module + const keysAmount = 50 + const keys1 = genKeys(keysAmount) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + + await operators.setNodeOperatorStakingLimit(0, 100000, { from: voting }) + await operators.setNodeOperatorStakingLimit(1, 100000, { from: voting }) + }) + + it('can not deposit with unset withdrawalCredentials', async () => { + // old WC + const wcBefore = await router.getWithdrawalCredentials() + + // unset WC + const newWC = '0x' + const tx = await router.setWithdrawalCredentials(newWC, { from: voting }) + await assert.emits(tx, 'WithdrawalCredentialsSet', { withdrawalCredentials: ZERO_BYTES32 }) + assert.equal(await router.getWithdrawalCredentials(), ZERO_BYTES32) + + // add 150 keys to module + const keysAmount = 1 + const keys1 = genKeys(keysAmount) + await operators.addNodeOperator('1', ADDRESS_1, { from: voting }) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + await operators.setNodeOperatorStakingLimit(0, 100000, { from: voting }) + + const depositsCount = 100 + await assert.reverts( + lido.deposit(depositsCount, curatedModuleId, '0x', { from: depositor }), + `EmptyWithdrawalsCredentials()` + ) + + const tx2 = await router.setWithdrawalCredentials(wcBefore, { from: voting }) + const wcAfter = await router.getWithdrawalCredentials() + await assert.emits(tx2, 'WithdrawalCredentialsSet', { withdrawalCredentials: wcBefore }) + assert.equal(await router.getWithdrawalCredentials(), wcBefore) + assert.equal(wcBefore, wcAfter) + }) + + it('Lido.deposit() :: check deposit with keys', async () => { + // prepare node operators + await operators.addNodeOperator('1', ADDRESS_1, { from: voting }) + await operators.addNodeOperator('2', ADDRESS_2, { from: voting }) + + // add 150 keys to module + const keysAmount = 50 + const keys1 = genKeys(keysAmount) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + + await operators.setNodeOperatorStakingLimit(0, 100000, { from: voting }) + await operators.setNodeOperatorStakingLimit(1, 100000, { from: voting }) + + const depositsCount = 100 + + const receipt = await lido.deposit(depositsCount, curatedModuleId, '0x', { + from: depositor, + }) + const currentBlockNumber = await web3.eth.getBlockNumber() + + assert.equals(await depositContract.totalCalls(), 100, 'invalid deposits count') + + // on deposit we return balance to Lido + assert.equals(await web3.eth.getBalance(lido.address), ETH(32), 'invalid lido balance') + assert.equals(await web3.eth.getBalance(router.address), 0, 'invalid staking_router balance') + + assert.equals(await lido.getBufferedEther(), ETH(32), 'invalid total buffer') + + assert.emits(receipt, 'Unbuffered', { amount: ETH(depositsCount * 32) }) + + const lastModuleBlock = await router.getStakingModuleLastDepositBlock(curatedModuleId) + assert.equal(currentBlockNumber, +lastModuleBlock) + }) + }) + + // the check for depositsValue == 0 occurs above in Lido.deposit(), so perhaps this check is redundant in SR. + // But if we untie the Lido contract from the StarkingRouter, we will need this check + describe('test deposit from staking router directly', async () => { + before(snapshot) + after(revert) + + it('add module', async () => { + await router.addStakingModule( + 'Curated', + operators.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: voting } + ) + curatedModuleId = +(await router.getStakingModuleIds())[0] + }) + + it('prepare node operators', async () => { + // balance are initial + assert.equals(await web3.eth.getBalance(lido.address), ETH(1)) + assert.equals(await web3.eth.getBalance(router.address), 0) + + const sendEthForKeys = ETH(101 * 32 - 1) + const totalPooledEther = ETH(101 * 32) + + await web3.eth.sendTransaction({ value: sendEthForKeys, to: lido.address, from: stranger }) + assert.equals(await lido.getBufferedEther(), totalPooledEther) + + // updated balance are lido 100 && sr 0 + assert.equals(await web3.eth.getBalance(lido.address), totalPooledEther) + assert.equals(await web3.eth.getBalance(router.address), 0) + + // prepare node operators + await operators.addNodeOperator('1', ADDRESS_1, { from: voting }) + await operators.addNodeOperator('2', ADDRESS_2, { from: voting }) + + // add 150 keys to module + const keysAmount = 50 + const keys1 = genKeys(keysAmount) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + await operators.addSigningKeys(0, keysAmount, keys1.pubkeys, keys1.sigkeys, { from: voting }) + + await operators.setNodeOperatorStakingLimit(0, 100000, { from: voting }) + await operators.setNodeOperatorStakingLimit(1, 100000, { from: voting }) + }) + + it('deposits not work if depositValue == 0', async () => { + const depositsCount = 100 + + // allow tx `StakingRouter.deposit()` from the Lido contract addr + await ethers.provider.send('hardhat_impersonateAccount', [lido.address]) + + const value = ETH(0) + await assert.reverts( + router.deposit(depositsCount, curatedModuleId, '0x', { from: lido.address, value }), + `InvalidDepositsValue(${value}, ${depositsCount})` + ) + }) + + it('deposits not work if depositValue != depositsCount * 32 ', async () => { + const depositsCount = 100 + + // allow tx `StakingRouter.deposit()` from the Lido contract addr + await ethers.provider.send('hardhat_impersonateAccount', [lido.address]) + + const value = ETH(1) + await assert.reverts( + router.deposit(depositsCount, curatedModuleId, '0x', { from: lido.address, value }), + `InvalidDepositsValue(${value}, ${depositsCount})` + ) + }) + }) +}) diff --git a/test/0.8.9/staking-router-keys-reporting.test.js b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js similarity index 74% rename from test/0.8.9/staking-router-keys-reporting.test.js rename to test/0.8.9/staking-router/staking-router-keys-reporting.test.js index c2ee02f16..437b76fa0 100644 --- a/test/0.8.9/staking-router-keys-reporting.test.js +++ b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js @@ -1,13 +1,13 @@ const { artifacts, contract, ethers } = require('hardhat') -const { EvmSnapshot } = require('../helpers/blockchain') -const { assert } = require('../helpers/assert') -const { hex, hexConcat, toNum } = require('../helpers/utils') +const { EvmSnapshot } = require('../../helpers/blockchain') +const { assert } = require('../../helpers/assert') +const { hex, hexConcat, toNum } = require('../../helpers/utils') const StakingRouter = artifacts.require('StakingRouterMock.sol') const StakingModuleMock = artifacts.require('StakingModuleMock.sol') const DepositContractMock = artifacts.require('DepositContractMock.sol') -contract('StakingRouter', ([deployer, lido, admin]) => { +contract('StakingRouter', ([deployer, lido, admin, stranger]) => { const evmSnapshot = new EvmSnapshot(ethers.provider) let depositContract, router @@ -82,6 +82,14 @@ contract('StakingRouter', ([deployer, lido, admin]) => { assert.equals(totalExited, 0) }) + it('reverts total exited validators without REPORT_EXITED_VALIDATORS_ROLE', async () => { + await assert.revertsOZAccessControl( + router.updateExitedValidatorsCountByStakingModule([module1Id + 1], [1], { from: stranger }), + stranger, + 'REPORT_EXITED_VALIDATORS_ROLE' + ) + }) + it('reporting total exited validators of a non-existent module reverts', async () => { await assert.reverts( router.updateExitedValidatorsCountByStakingModule([module1Id + 1], [1], { from: admin }), @@ -114,6 +122,14 @@ contract('StakingRouter', ([deployer, lido, admin]) => { assert.equal(callInfo.onExitedAndStuckValidatorsCountsUpdated.callCount, 0) }) + it('reverts without role onValidatorsCountsByNodeOperatorReportingFinished', async () => { + await assert.revertsOZAccessControl( + router.onValidatorsCountsByNodeOperatorReportingFinished({ from: stranger }), + stranger, + 'REPORT_EXITED_VALIDATORS_ROLE' + ) + }) + it(`calling onValidatorsCountsByNodeOperatorReportingFinished doesn't call anything on the module`, async () => { await router.onValidatorsCountsByNodeOperatorReportingFinished({ from: admin }) @@ -123,6 +139,22 @@ contract('StakingRouter', ([deployer, lido, admin]) => { assert.equal(callInfo.onExitedAndStuckValidatorsCountsUpdated.callCount, 0) }) + it('reverts without role reportStakingModuleStuckValidatorsCountByNodeOperator()', async () => { + const nonExistentModuleId = module1Id + 1 + const nodeOpIdsData = hexConcat(hex(1, 8)) + const validatorsCountsData = hexConcat(hex(1, 16)) + await assert.revertsOZAccessControl( + router.reportStakingModuleStuckValidatorsCountByNodeOperator( + nonExistentModuleId, + nodeOpIdsData, + validatorsCountsData, + { from: stranger } + ), + stranger, + 'REPORT_EXITED_VALIDATORS_ROLE' + ) + }) + it('reporting stuck validators by node op of a non-existent module reverts', async () => { const nonExistentModuleId = module1Id + 1 const nodeOpIdsData = hexConcat(hex(1, 8)) @@ -287,6 +319,14 @@ contract('StakingRouter', ([deployer, lido, admin]) => { ) }) + it('reverts reportStakingModuleExitedValidatorsCountByNodeOperator() without REPORT_EXITED_VALIDATORS_ROLE', async () => { + await assert.revertsOZAccessControl( + router.reportStakingModuleExitedValidatorsCountByNodeOperator(module1Id, '0x', '0x', { from: stranger }), + stranger, + 'REPORT_EXITED_VALIDATORS_ROLE' + ) + }) + it('passing empty data while reporting exited validators by node operator reverts', async () => { await assert.reverts( router.reportStakingModuleExitedValidatorsCountByNodeOperator(module1Id, '0x', '0x', { from: admin }), @@ -481,6 +521,38 @@ contract('StakingRouter', ([deployer, lido, admin]) => { assert.equals(totalExited, 5) }) + it('revert on decreased exited keys for modules', async () => { + await assert.reverts( + router.updateExitedValidatorsCountByStakingModule(moduleIds, [2, 1], { from: admin }), + `ExitedValidatorsCountCannotDecrease()` + ) + }) + + it('emit StakingModuleExitedValidatorsIncompleteReporting() if module not update', async () => { + const { exitedValidatorsCount: prevReportedExitedValidatorsCount1 } = await router.getStakingModule( + moduleIds[0] + ) + const { exitedValidatorsCount: prevReportedExitedValidatorsCount2 } = await router.getStakingModule( + moduleIds[1] + ) + + assert.equal(prevReportedExitedValidatorsCount1, 3) + assert.equal(prevReportedExitedValidatorsCount2, 2) + + const { totalExitedValidators: totalExitedValidators1 } = await module1.getStakingModuleSummary() + const { totalExitedValidators: totalExitedValidators2 } = await module2.getStakingModuleSummary() + + const tx = await router.updateExitedValidatorsCountByStakingModule(moduleIds, [3, 2], { from: admin }) + assert.emits(tx, 'StakingModuleExitedValidatorsIncompleteReporting', { + stakingModuleId: moduleIds[0], + unreportedExitedValidatorsCount: prevReportedExitedValidatorsCount1 - totalExitedValidators1, + }) + assert.emits(tx, 'StakingModuleExitedValidatorsIncompleteReporting', { + stakingModuleId: moduleIds[1], + unreportedExitedValidatorsCount: prevReportedExitedValidatorsCount2 - totalExitedValidators2, + }) + }) + it('no functions were called on any module', async () => { const callInfo1 = await getCallInfo(module1) assert.equal(callInfo1.updateStuckValidatorsCount.callCount, 0) @@ -730,4 +802,165 @@ contract('StakingRouter', ([deployer, lido, admin]) => { ) }) }) + + describe('unsafeSetExitedValidatorsCount()', async () => { + before(snapshot) + after(revert) + + let module1Id + + it('adding the only module', async () => { + await router.addStakingModule( + 'module 1', + module1.address, + 10_000, // target share 100 % + 1_000, // module fee 10 % + 5_000, // treasury fee 5 % + { from: admin } + ) + module1Id = +(await router.getStakingModuleIds())[0] + }) + + it('reverts without UNSAFE_SET_EXITED_VALIDATORS_ROLE role', async () => { + await assert.revertsOZAccessControl( + router.unsafeSetExitedValidatorsCount(0, 0, 0, [0, 0, 0, 0, 0, 0], { from: stranger }), + stranger, + 'UNSAFE_SET_EXITED_VALIDATORS_ROLE' + ) + }) + + it('reverts if module not exists', async () => { + await router.grantRole(await router.UNSAFE_SET_EXITED_VALIDATORS_ROLE(), admin, { from: admin }) + await assert.reverts( + router.unsafeSetExitedValidatorsCount(0, 0, 0, [0, 0, 0, 0, 0, 0], { from: admin }), + 'StakingModuleUnregistered()' + ) + }) + + it('reverts with UnexpectedCurrentValidatorsCount(0, 0, 0)', async () => { + await router.grantRole(await router.UNSAFE_SET_EXITED_VALIDATORS_ROLE(), admin, { from: admin }) + + const nodeOperatorId = 0 + const ValidatorsCountsCorrection = { + currentModuleExitedValidatorsCount: 0, + currentNodeOperatorExitedValidatorsCount: 0, + currentNodeOperatorStuckValidatorsCount: 0, + newModuleExitedValidatorsCount: 0, + newNodeOperatorExitedValidatorsCount: 0, + newNodeOperatorStuckValidatorsCount: 0, + } + + const summary = { + isTargetLimitActive: false, + targetValidatorsCount: 0, + stuckValidatorsCount: 0, + refundedValidatorsCount: 0, + stuckPenaltyEndTimestamp: 0, + totalExitedValidators: 0, + totalDepositedValidators: 0, + depositableValidatorsCount: 0, + } + + // first correction + await router.updateExitedValidatorsCountByStakingModule([module1Id], [10], { from: admin }) + await assert.reverts( + router.unsafeSetExitedValidatorsCount(module1Id, nodeOperatorId, false, ValidatorsCountsCorrection, { + from: admin, + }), + `UnexpectedCurrentValidatorsCount(10, 0, 0)` + ) + + ValidatorsCountsCorrection.currentModuleExitedValidatorsCount = 10 + ValidatorsCountsCorrection.newModuleExitedValidatorsCount = 11 + await router.unsafeSetExitedValidatorsCount(module1Id, 0, false, ValidatorsCountsCorrection, { from: admin }) + + let lastCall = await module1.lastCall_unsafeUpdateValidatorsCount() + assert.equal(+lastCall.callCount, 1) + assert.equal(+lastCall.nodeOperatorId, 0) + assert.equal(+lastCall.exitedValidatorsKeysCount, 0) + assert.equal(+lastCall.stuckValidatorsKeysCount, 0) + + let stats1 = await router.getStakingModule(module1Id) + assert.equal(+stats1.exitedValidatorsCount, 11) + + // second correction + ValidatorsCountsCorrection.currentModuleExitedValidatorsCount = 11 + ValidatorsCountsCorrection.newModuleExitedValidatorsCount = 11 + + ValidatorsCountsCorrection.currentNodeOperatorExitedValidatorsCount = 20 + summary.totalExitedValidators = 21 + await module1.setNodeOperatorSummary(nodeOperatorId, summary) + await assert.reverts( + router.unsafeSetExitedValidatorsCount(module1Id, 0, false, ValidatorsCountsCorrection, { from: admin }), + `UnexpectedCurrentValidatorsCount(11, 21, 0)` + ) + + ValidatorsCountsCorrection.currentModuleExitedValidatorsCount = 11 + ValidatorsCountsCorrection.newModuleExitedValidatorsCount = 11 + + ValidatorsCountsCorrection.currentNodeOperatorExitedValidatorsCount = 21 + ValidatorsCountsCorrection.newNodeOperatorExitedValidatorsCount = 22 + + await router.unsafeSetExitedValidatorsCount(module1Id, 0, false, ValidatorsCountsCorrection, { from: admin }) + lastCall = await module1.lastCall_unsafeUpdateValidatorsCount() + assert.equal(+lastCall.callCount, 2) + assert.equal(+lastCall.nodeOperatorId, 0) + assert.equal(+lastCall.exitedValidatorsKeysCount, 22) + assert.equal(+lastCall.stuckValidatorsKeysCount, 0) + + stats1 = await router.getStakingModule(module1Id) + assert.equal(+stats1.exitedValidatorsCount, 11) + + // // //check 3d condition + ValidatorsCountsCorrection.currentNodeOperatorExitedValidatorsCount = 22 + ValidatorsCountsCorrection.newNodeOperatorExitedValidatorsCount = 22 + + ValidatorsCountsCorrection.currentNodeOperatorStuckValidatorsCount = 30 + ValidatorsCountsCorrection.newNodeOperatorStuckValidatorsCount = 32 + + summary.totalExitedValidators = 22 + summary.stuckValidatorsCount = 31 + await module1.setNodeOperatorSummary(nodeOperatorId, summary) + await assert.reverts( + router.unsafeSetExitedValidatorsCount(module1Id, 0, false, ValidatorsCountsCorrection, { from: admin }), + `UnexpectedCurrentValidatorsCount(11, 22, 31)` + ) + + ValidatorsCountsCorrection.currentNodeOperatorStuckValidatorsCount = 31 + ValidatorsCountsCorrection.newNodeOperatorStuckValidatorsCount = 32 + + await router.unsafeSetExitedValidatorsCount(module1Id, 0, false, ValidatorsCountsCorrection, { from: admin }) + lastCall = await module1.lastCall_unsafeUpdateValidatorsCount() + assert.equal(+lastCall.callCount, 3) + assert.equal(+lastCall.nodeOperatorId, 0) + assert.equal(+lastCall.exitedValidatorsKeysCount, 22) + assert.equal(+lastCall.stuckValidatorsKeysCount, 32) + + assert.equal(+(await module1.callCount_onExitedAndStuckValidatorsCountsUpdated()), 0) + await router.unsafeSetExitedValidatorsCount(module1Id, 0, true, ValidatorsCountsCorrection, { from: admin }) + assert.equal(+(await module1.callCount_onExitedAndStuckValidatorsCountsUpdated()), 1) + }) + + // it('reverts UnexpectedCurrentValidatorsCount()', async () => { + // let currentModuleExitedValidatorsCount=0 + // let currentNodeOperatorExitedValidatorsCount=0 + // let currentNodeOperatorStuckValidatorsCount=0 + // let newModuleExitedValidatorsCount=0 + // let newNodeOperatorExitedValidatorsCount=0 + // let newNodeOperatorStuckValidatorsCount=0 + + // let ValidatorsCountsCorrection = [ + // currentModuleExitedValidatorsCount, + // currentNodeOperatorExitedValidatorsCount, + // currentNodeOperatorStuckValidatorsCount, + // newModuleExitedValidatorsCount, + // newNodeOperatorExitedValidatorsCount, + // newNodeOperatorStuckValidatorsCount, + // ] + + // await router.grantRole(await router.UNSAFE_SET_EXITED_VALIDATORS_ROLE(), admin, { from: admin }) + + // await router.unsafeSetExitedValidatorsCount(module1Id,0,false,ValidatorsCountsCorrection, {from: admin}) + // }) + }) }) diff --git a/test/0.8.9/staking-router.test.js b/test/0.8.9/staking-router/staking-router.test.js similarity index 54% rename from test/0.8.9/staking-router.test.js rename to test/0.8.9/staking-router/staking-router.test.js index fd7e1fe3f..ce27f02c9 100644 --- a/test/0.8.9/staking-router.test.js +++ b/test/0.8.9/staking-router/staking-router.test.js @@ -2,11 +2,11 @@ const { artifacts, contract, ethers } = require('hardhat') const { MaxUint256 } = require('@ethersproject/constants') const { utils } = require('web3') const { BN } = require('bn.js') -const { assert } = require('../helpers/assert') -const { EvmSnapshot } = require('../helpers/blockchain') -const { newDao, newApp } = require('../helpers/dao') -const { ETH } = require('../helpers/utils') +const { assert } = require('../../helpers/assert') +const { EvmSnapshot } = require('../../helpers/blockchain') +const { ETH } = require('../../helpers/utils') +const OssifiableProxy = artifacts.require('OssifiableProxy.sol') const DepositContractMock = artifacts.require('DepositContractMock') const StakingRouter = artifacts.require('StakingRouter.sol') const StakingModuleMock = artifacts.require('StakingModuleMock.sol') @@ -28,66 +28,82 @@ const StakingModuleStatus = { } contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { - let depositContract, app + const evmSnapshot = new EvmSnapshot(ethers.provider) + + const snapshot = () => evmSnapshot.make() + const revert = () => evmSnapshot.revert() + + let depositContract, router + let initialTx + let module1, module2 const wc = '0x'.padEnd(66, '1234') - const snapshot = new EvmSnapshot(ethers.provider) + + before(async () => { + depositContract = await DepositContractMock.new({ from: deployer }) + + const impl = await StakingRouter.new(depositContract.address, { from: deployer }) + const proxy = await OssifiableProxy.new(impl.address, deployer, '0x') + router = await StakingRouter.at(proxy.address) + ;[module1, module2] = await Promise.all([ + StakingModuleMock.new({ from: deployer }), + StakingModuleMock.new({ from: deployer }), + ]) + + const wc = '0x'.padEnd(66, '1234') + initialTx = await router.initialize(admin, lido, wc, { from: deployer }) + + // await router.grantRole(await router.MANAGE_WITHDRAWAL_CREDENTIALS_ROLE(), admin, { from: admin }) + // await router.grantRole(await router.STAKING_MODULE_PAUSE_ROLE(), admin, { from: admin }) + // await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + // await router.grantRole(await router.REPORT_EXITED_VALIDATORS_ROLE(), admin, { from: admin }) + }) describe('setup env', async () => { - before(async () => { - const { dao } = await newDao(appManager) - depositContract = await DepositContractMock.new() - const appBase = await StakingRouter.new(depositContract.address) - const proxyAddress = await newApp(dao, 'lido-pool', appBase.address, appManager) - app = await StakingRouter.at(proxyAddress) + it('initialized correctly', async () => { + assert.equals(await router.getContractVersion(), 1) + assert.equals(await router.getWithdrawalCredentials(), wc) + assert.equals(await router.getLido(), lido) + assert.equals(await router.getStakingModulesCount(), 0) + + assert.equals(await router.getRoleMemberCount(DEFAULT_ADMIN_ROLE), 1) + assert.equals(await router.hasRole(DEFAULT_ADMIN_ROLE, admin), true) + + assert.equals(initialTx.logs.length, 3) + + await assert.emits(initialTx, 'ContractVersionSet', { version: 1 }) + await assert.emits(initialTx, 'RoleGranted', { role: DEFAULT_ADMIN_ROLE, account: admin, sender: deployer }) + await assert.emits(initialTx, 'WithdrawalCredentialsSet', { withdrawalCredentials: wc }) }) it('init fails on wrong input', async () => { await assert.revertsWithCustomError( - app.initialize(ZERO_ADDRESS, lido, wc, { from: deployer }), + router.initialize(ZERO_ADDRESS, lido, wc, { from: deployer }), 'ZeroAddress("_admin")' ) await assert.revertsWithCustomError( - app.initialize(admin, ZERO_ADDRESS, wc, { from: deployer }), + router.initialize(admin, ZERO_ADDRESS, wc, { from: deployer }), 'ZeroAddress("_lido")' ) }) - it('initialized correctly', async () => { - const tx = await app.initialize(admin, lido, wc, { from: deployer }) - - assert.equals(await app.getContractVersion(), 1) - assert.equals(await app.getWithdrawalCredentials(), wc) - assert.equals(await app.getLido(), lido) - assert.equals(await app.getStakingModulesCount(), 0) - - assert.equals(await app.getRoleMemberCount(DEFAULT_ADMIN_ROLE), 1) - assert.equals(await app.hasRole(DEFAULT_ADMIN_ROLE, admin), true) - - assert.equals(tx.logs.length, 3) - - await assert.emits(tx, 'ContractVersionSet', { version: 1 }) - await assert.emits(tx, 'RoleGranted', { role: DEFAULT_ADMIN_ROLE, account: admin, sender: deployer }) - await assert.emits(tx, 'WithdrawalCredentialsSet', { withdrawalCredentials: wc }) - }) - it('second initialize reverts', async () => { await assert.revertsWithCustomError( - app.initialize(admin, lido, wc, { from: deployer }), + router.initialize(admin, lido, wc, { from: deployer }), 'NonZeroContractVersionOnInit()' ) }) it('stranger is not allowed to grant roles', async () => { await assert.reverts( - app.grantRole(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, appManager, { from: stranger }), + router.grantRole(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, appManager, { from: stranger }), `AccessControl: account ${stranger.toLowerCase()} is missing role ${DEFAULT_ADMIN_ROLE}` ) }) it('grant role MANAGE_WITHDRAWAL_CREDENTIALS_ROLE', async () => { - const tx = await app.grantRole(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, appManager, { from: admin }) - assert.equals(await app.getRoleMemberCount(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE), 1) - assert.equals(await app.hasRole(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, appManager), true) + const tx = await router.grantRole(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, appManager, { from: admin }) + assert.equals(await router.getRoleMemberCount(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE), 1) + assert.equals(await router.hasRole(MANAGE_WITHDRAWAL_CREDENTIALS_ROLE, appManager), true) assert.equals(tx.logs.length, 1) await assert.emits(tx, 'RoleGranted', { @@ -98,45 +114,45 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('grant role STAKING_MODULE_PAUSE_ROLE', async () => { - const tx = await app.grantRole(STAKING_MODULE_PAUSE_ROLE, appManager, { from: admin }) - assert.equals(await app.getRoleMemberCount(STAKING_MODULE_PAUSE_ROLE), 1) - assert.equals(await app.hasRole(STAKING_MODULE_PAUSE_ROLE, appManager), true) + const tx = await router.grantRole(STAKING_MODULE_PAUSE_ROLE, appManager, { from: admin }) + assert.equals(await router.getRoleMemberCount(STAKING_MODULE_PAUSE_ROLE), 1) + assert.equals(await router.hasRole(STAKING_MODULE_PAUSE_ROLE, appManager), true) assert.equals(tx.logs.length, 1) await assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_PAUSE_ROLE, account: appManager, sender: admin }) }) it('grant role STAKING_MODULE_RESUME_ROLE', async () => { - const tx = await app.grantRole(STAKING_MODULE_RESUME_ROLE, appManager, { from: admin }) - assert.equals(await app.getRoleMemberCount(STAKING_MODULE_RESUME_ROLE), 1) - assert.equals(await app.hasRole(STAKING_MODULE_RESUME_ROLE, appManager), true) + const tx = await router.grantRole(STAKING_MODULE_RESUME_ROLE, appManager, { from: admin }) + assert.equals(await router.getRoleMemberCount(STAKING_MODULE_RESUME_ROLE), 1) + assert.equals(await router.hasRole(STAKING_MODULE_RESUME_ROLE, appManager), true) assert.equals(tx.logs.length, 1) await assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_RESUME_ROLE, account: appManager, sender: admin }) }) it('grant role STAKING_MODULE_MANAGE_ROLE', async () => { - const tx = await app.grantRole(STAKING_MODULE_MANAGE_ROLE, appManager, { from: admin }) - assert.equals(await app.getRoleMemberCount(STAKING_MODULE_MANAGE_ROLE), 1) - assert.equals(await app.hasRole(STAKING_MODULE_MANAGE_ROLE, appManager), true) + const tx = await router.grantRole(STAKING_MODULE_MANAGE_ROLE, appManager, { from: admin }) + assert.equals(await router.getRoleMemberCount(STAKING_MODULE_MANAGE_ROLE), 1) + assert.equals(await router.hasRole(STAKING_MODULE_MANAGE_ROLE, appManager), true) assert.equals(tx.logs.length, 1) await assert.emits(tx, 'RoleGranted', { role: STAKING_MODULE_MANAGE_ROLE, account: appManager, sender: admin }) }) it('public constants', async () => { - assert.equals(await app.FEE_PRECISION_POINTS(), new BN('100000000000000000000')) - assert.equals(await app.TOTAL_BASIS_POINTS(), 10000) - assert.equals(await app.DEPOSIT_CONTRACT(), depositContract.address) - assert.equals(await app.DEFAULT_ADMIN_ROLE(), DEFAULT_ADMIN_ROLE) - assert.equals(await app.MANAGE_WITHDRAWAL_CREDENTIALS_ROLE(), MANAGE_WITHDRAWAL_CREDENTIALS_ROLE) - assert.equals(await app.STAKING_MODULE_PAUSE_ROLE(), STAKING_MODULE_PAUSE_ROLE) - assert.equals(await app.STAKING_MODULE_RESUME_ROLE(), STAKING_MODULE_RESUME_ROLE) - assert.equals(await app.STAKING_MODULE_MANAGE_ROLE(), STAKING_MODULE_MANAGE_ROLE) + assert.equals(await router.FEE_PRECISION_POINTS(), new BN('100000000000000000000')) + assert.equals(await router.TOTAL_BASIS_POINTS(), 10000) + assert.equals(await router.DEPOSIT_CONTRACT(), depositContract.address) + assert.equals(await router.DEFAULT_ADMIN_ROLE(), DEFAULT_ADMIN_ROLE) + assert.equals(await router.MANAGE_WITHDRAWAL_CREDENTIALS_ROLE(), MANAGE_WITHDRAWAL_CREDENTIALS_ROLE) + assert.equals(await router.STAKING_MODULE_PAUSE_ROLE(), STAKING_MODULE_PAUSE_ROLE) + assert.equals(await router.STAKING_MODULE_RESUME_ROLE(), STAKING_MODULE_RESUME_ROLE) + assert.equals(await router.STAKING_MODULE_MANAGE_ROLE(), STAKING_MODULE_MANAGE_ROLE) }) it('getDepositsAllocation', async () => { - const keysAllocation = await app.getDepositsAllocation(1000) + const keysAllocation = await router.getDepositsAllocation(1000) assert.equals(keysAllocation.allocated, 0) assert.equals(keysAllocation.allocations, []) @@ -147,12 +163,12 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { let stakingRouterImplementation before(async () => { - await snapshot.make() + await snapshot() stakingRouterImplementation = await StakingRouter.new(depositContract.address, { from: deployer }) }) after(async () => { - await snapshot.revert() + await revert() }) it('contract version is max uint256', async () => { @@ -180,7 +196,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await stakingRouterImplementation.getStakingModulesCount(), 0) }) - it('deposit fails', async () => { + it('deposit fails without role', async () => { await assert.revertsWithCustomError( stakingRouterImplementation.deposit(100, 0, '0x00', { from: stranger }), `AppAuthLidoFailed()` @@ -191,11 +207,11 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { describe('staking router', async () => { let stakingModule before(async () => { - await snapshot.make() + await snapshot() stakingModule = await StakingModuleMock.new({ from: deployer }) - await app.addStakingModule('Test module', stakingModule.address, 100, 1000, 2000, { + await router.addStakingModule('Test module', stakingModule.address, 100, 1000, 2000, { from: appManager, }) @@ -205,12 +221,12 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) after(async () => { - await snapshot.revert() + await revert() }) it('reverts if module address exists', async () => { await assert.revertsWithCustomError( - app.addStakingModule('Test', stakingModule.address, 100, 1000, 2000, { from: appManager }), + router.addStakingModule('Test', stakingModule.address, 100, 1000, 2000, { from: appManager }), 'StakingModuleAddressExists()' ) }) @@ -218,14 +234,14 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('set withdrawal credentials does not allowed without role', async () => { const newWC = '0x'.padEnd(66, '5678') await assert.reverts( - app.setWithdrawalCredentials(newWC, { from: stranger }), + router.setWithdrawalCredentials(newWC, { from: stranger }), `AccessControl: account ${stranger.toLowerCase()} is missing role ${MANAGE_WITHDRAWAL_CREDENTIALS_ROLE}` ) }) it('set withdrawal credentials', async () => { const newWC = '0x'.padEnd(66, '5678') - const tx = await app.setWithdrawalCredentials(newWC, { from: appManager }) + const tx = await router.setWithdrawalCredentials(newWC, { from: appManager }) await assert.emits(tx, 'WithdrawalCredentialsSet', { withdrawalCredentials: newWC }) @@ -234,26 +250,29 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('direct transfer fails', async () => { const value = 100 - await assert.revertsWithCustomError(app.sendTransaction({ value, from: deployer }), `DirectETHTransfer()`) + await assert.revertsWithCustomError(router.sendTransaction({ value, from: deployer }), `DirectETHTransfer()`) }) it('getStakingModuleNonce', async () => { await stakingModule.setNonce(100, { from: deployer }) - assert.equals(await app.getStakingModuleNonce(1), 100) + assert.equals(await router.getStakingModuleNonce(1), 100) }) it('getStakingModuleNonce reverts when staking module id too large', async () => { - await assert.revertsWithCustomError(app.getStakingModuleNonce(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError(router.getStakingModuleNonce(UINT24_MAX), 'StakingModuleIdTooLarge()') }) it('getStakingModuleLastDepositBlock reverts when staking module id too large', async () => { - await assert.revertsWithCustomError(app.getStakingModuleLastDepositBlock(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError( + router.getStakingModuleLastDepositBlock(UINT24_MAX), + 'StakingModuleIdTooLarge()' + ) }) it('getStakingModuleActiveValidatorsCount reverts when staking module id too large', async () => { await assert.revertsWithCustomError( - app.getStakingModuleActiveValidatorsCount(UINT24_MAX), + router.getStakingModuleActiveValidatorsCount(UINT24_MAX), 'StakingModuleIdTooLarge()' ) }) @@ -261,37 +280,33 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('getStakingModuleActiveValidatorsCount', async () => { await stakingModule.setActiveValidatorsCount(200, { from: deployer }) - assert.equals(await app.getStakingModuleActiveValidatorsCount(1), 200) + assert.equals(await router.getStakingModuleActiveValidatorsCount(1), 200) }) it('getStakingRewardsDistribution', async () => { const anotherStakingModule = await StakingModuleMock.new({ from: deployer }) - await app.addStakingModule('Test module 2', anotherStakingModule.address, 100, 1000, 2000, { + await router.addStakingModule('Test module 2', anotherStakingModule.address, 100, 1000, 2000, { from: appManager, }) - await app.getStakingRewardsDistribution() + // await router.getStakingRewardsDistribution() }) }) describe('staking modules limit', async () => { - before(async () => { - await snapshot.make() - }) + before(snapshot) + after(revert) - after(async () => { - await snapshot.revert() - }) it('staking modules limit is 32', async () => { for (let i = 0; i < 32; i++) { const stakingModule = await StakingModuleMock.new({ from: deployer }) - await app.addStakingModule('Test module', stakingModule.address, 100, 100, 100, { from: appManager }) + await router.addStakingModule('Test module', stakingModule.address, 100, 100, 100, { from: appManager }) } const oneMoreStakingModule = await StakingModuleMock.new({ from: deployer }) await assert.revertsWithCustomError( - app.addStakingModule('Test module', oneMoreStakingModule.address, 100, 100, 100, { from: appManager }), + router.addStakingModule('Test module', oneMoreStakingModule.address, 100, 100, 100, { from: appManager }), `StakingModulesLimitExceeded()` ) }) @@ -320,7 +335,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ] before(async () => { - await snapshot.make() + await snapshot() stakingModule1 = await StakingModuleMock.new({ from: deployer }) stakingModule2 = await StakingModuleMock.new({ from: deployer }) @@ -329,13 +344,11 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { stakingModulesParams[1].address = stakingModule2.address }) - after(async () => { - await snapshot.revert() - }) + after(revert) it('addStakingModule call is not allowed from stranger', async () => { await assert.reverts( - app.addStakingModule( + router.addStakingModule( stakingModulesParams[0].name, stakingModule1.address, stakingModulesParams[0].targetShare, @@ -349,7 +362,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('addStakingModule fails on share > 100%', async () => { await assert.revertsWithCustomError( - app.addStakingModule( + router.addStakingModule( stakingModulesParams[0].name, stakingModule1.address, 10001, @@ -363,7 +376,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('addStakingModule fails on fees > 100%', async () => { await assert.revertsWithCustomError( - app.addStakingModule( + router.addStakingModule( stakingModulesParams[0].name, stakingModule1.address, stakingModulesParams[0].targetShare, @@ -379,7 +392,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('addStakingModule fails on zero address', async () => { await assert.revertsWithCustomError( - app.addStakingModule( + router.addStakingModule( stakingModulesParams[0].name, ZERO_ADDRESS, stakingModulesParams[0].targetShare, @@ -396,7 +409,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('addStakingModule fails on incorrect module name', async () => { // check zero length await assert.revertsWithCustomError( - app.addStakingModule( + router.addStakingModule( '', stakingModule1.address, stakingModulesParams[0].targetShare, @@ -411,7 +424,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { // check length > 32 symbols await assert.revertsWithCustomError( - app.addStakingModule( + router.addStakingModule( '#'.repeat(33), stakingModule1.address, stakingModulesParams[0].targetShare, @@ -426,7 +439,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('add staking module', async () => { - const tx = await app.addStakingModule( + const tx = await router.addStakingModule( stakingModulesParams[0].name, stakingModule1.address, stakingModulesParams[0].targetShare, @@ -455,22 +468,25 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { setBy: appManager, }) - assert.equals(await app.getStakingModulesCount(), 1) + assert.equals(await router.getStakingModulesCount(), 1) assert.equals( - await app.getStakingModuleStatus(stakingModulesParams[0].expectedModuleId), + await router.getStakingModuleStatus(stakingModulesParams[0].expectedModuleId), StakingModuleStatus.Active ) - assert.equals(await app.getStakingModuleIsStopped(stakingModulesParams[0].expectedModuleId), false) - assert.equals(await app.getStakingModuleIsDepositsPaused(stakingModulesParams[0].expectedModuleId), false) - assert.equals(await app.getStakingModuleIsActive(stakingModulesParams[0].expectedModuleId), true) + assert.equals(await router.getStakingModuleIsStopped(stakingModulesParams[0].expectedModuleId), false) + assert.equals(await router.getStakingModuleIsDepositsPaused(stakingModulesParams[0].expectedModuleId), false) + assert.equals(await router.getStakingModuleIsActive(stakingModulesParams[0].expectedModuleId), true) - 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()') + await assert.revertsWithCustomError(router.getStakingModule(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError(router.getStakingModuleStatus(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError(router.getStakingModuleIsStopped(UINT24_MAX), 'StakingModuleIdTooLarge()') + await assert.revertsWithCustomError( + router.getStakingModuleIsDepositsPaused(UINT24_MAX), + 'StakingModuleIdTooLarge()' + ) + await assert.revertsWithCustomError(router.getStakingModuleIsActive(UINT24_MAX), 'StakingModuleIdTooLarge()') - const module = await app.getStakingModule(stakingModulesParams[0].expectedModuleId) + const module = await router.getStakingModule(stakingModulesParams[0].expectedModuleId) assert.equals(module.name, stakingModulesParams[0].name) assert.equals(module.stakingModuleAddress, stakingModule1.address) @@ -483,7 +499,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('add another staking module', async () => { - const tx = await app.addStakingModule( + const tx = await router.addStakingModule( stakingModulesParams[1].name, stakingModule2.address, stakingModulesParams[1].targetShare, @@ -513,16 +529,16 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { setBy: appManager, }) - assert.equals(await app.getStakingModulesCount(), 2) + assert.equals(await router.getStakingModulesCount(), 2) assert.equals( - await app.getStakingModuleStatus(stakingModulesParams[1].expectedModuleId), + await router.getStakingModuleStatus(stakingModulesParams[1].expectedModuleId), StakingModuleStatus.Active ) - assert.equals(await app.getStakingModuleIsStopped(stakingModulesParams[1].expectedModuleId), false) - assert.equals(await app.getStakingModuleIsDepositsPaused(stakingModulesParams[1].expectedModuleId), false) - assert.equals(await app.getStakingModuleIsActive(stakingModulesParams[1].expectedModuleId), true) + assert.equals(await router.getStakingModuleIsStopped(stakingModulesParams[1].expectedModuleId), false) + assert.equals(await router.getStakingModuleIsDepositsPaused(stakingModulesParams[1].expectedModuleId), false) + assert.equals(await router.getStakingModuleIsActive(stakingModulesParams[1].expectedModuleId), true) - const module = await app.getStakingModule(stakingModulesParams[1].expectedModuleId) + const module = await router.getStakingModule(stakingModulesParams[1].expectedModuleId) assert.equals(module.name, stakingModulesParams[1].name) assert.equals(module.stakingModuleAddress, stakingModule2.address) @@ -535,7 +551,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('get staking modules list', async () => { - const stakingModules = await app.getStakingModules() + const stakingModules = await router.getStakingModules() for (let i = 0; i < 2; i++) { assert.equals(stakingModules[i].name, stakingModulesParams[i].name) @@ -550,8 +566,8 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('get staking module ids', async () => { - const stakingModules = await app.getStakingModules() - const stakingModuleIds = await app.getStakingModuleIds() + const stakingModules = await router.getStakingModules() + const stakingModuleIds = await router.getStakingModuleIds() for (let i = 0; i < stakingModules.length; i++) { assert.equals(stakingModules[i].id, stakingModuleIds[i]) @@ -560,7 +576,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('update staking module does not allowed without role', async () => { await assert.reverts( - app.updateStakingModule( + router.updateStakingModule( stakingModulesParams[0].expectedModuleId, stakingModulesParams[0].targetShare + 1, stakingModulesParams[0].stakingModuleFee + 1, @@ -575,7 +591,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('update staking module reverts on large module id', async () => { await assert.revertsWithCustomError( - app.updateStakingModule( + router.updateStakingModule( UINT24_MAX, stakingModulesParams[0].targetShare + 1, stakingModulesParams[0].stakingModuleFee + 1, @@ -590,7 +606,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('update staking module fails on target share > 100%', async () => { await assert.revertsWithCustomError( - app.updateStakingModule( + router.updateStakingModule( stakingModulesParams[0].expectedModuleId, 10001, stakingModulesParams[0].stakingModuleFee + 1, @@ -605,7 +621,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('update staking module fails on fees > 100%', async () => { await assert.revertsWithCustomError( - app.updateStakingModule( + router.updateStakingModule( stakingModulesParams[0].expectedModuleId, stakingModulesParams[0].targetShare + 1, 5000, @@ -626,7 +642,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { treasuryFee: stakingModulesParams[0].treasuryFee + 1, } - const tx = await app.updateStakingModule( + const tx = await router.updateStakingModule( stakingModuleNewParams.id, stakingModuleNewParams.targetShare, stakingModuleNewParams.stakingModuleFee, @@ -653,7 +669,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('set staking module status does not allowed without role', async () => { await assert.reverts( - app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { + router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { from: stranger, }), `AccessControl: account ${stranger.toLowerCase()} is missing role ${STAKING_MODULE_MANAGE_ROLE}` @@ -662,7 +678,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('set staking module status reverts if staking module id too large', async () => { await assert.revertsWithCustomError( - app.setStakingModuleStatus(UINT24_MAX, StakingModuleStatus.Stopped, { + router.setStakingModuleStatus(UINT24_MAX, StakingModuleStatus.Stopped, { from: appManager, }), `StakingModuleIdTooLarge()` @@ -670,9 +686,9 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('set staking module status reverts if status is the same', async () => { - const module = await app.getStakingModule(stakingModulesParams[0].expectedModuleId) + const module = await router.getStakingModule(stakingModulesParams[0].expectedModuleId) await assert.revertsWithCustomError( - app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, module.status, { + router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, module.status, { from: appManager, }), `StakingModuleStatusTheSame()` @@ -680,7 +696,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('set staking module status', async () => { - const tx = await app.setStakingModuleStatus( + const tx = await router.setStakingModuleStatus( stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { @@ -697,7 +713,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('pause staking module does not allowed without role', async () => { await assert.reverts( - app.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { + router.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { from: stranger, }), `AccessControl: account ${stranger.toLowerCase()} is missing role ${STAKING_MODULE_PAUSE_ROLE}` @@ -706,7 +722,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('pause staking module reverts when staking module too large', async () => { await assert.revertsWithCustomError( - app.pauseStakingModule(UINT24_MAX, { + router.pauseStakingModule(UINT24_MAX, { from: appManager, }), `StakingModuleIdTooLarge()` @@ -714,24 +730,28 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('pause staking module does not allowed at not active staking module', async () => { - await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { + await router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { from: appManager, }) - await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { + await router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { from: appManager, }) await assert.revertsWithCustomError( - app.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { + router.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager, }), `StakingModuleNotActive()` ) - await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.DepositsPaused, { - from: appManager, - }) + await router.setStakingModuleStatus( + stakingModulesParams[0].expectedModuleId, + StakingModuleStatus.DepositsPaused, + { + from: appManager, + } + ) await assert.revertsWithCustomError( - app.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { + router.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager, }), `StakingModuleNotActive()` @@ -739,10 +759,10 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('pause staking module', async () => { - await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { + await router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { from: appManager, }) - const tx = await app.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { + const tx = await router.pauseStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager, }) @@ -753,22 +773,22 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) }) - it('deposit fails', async () => { + it('deposit fails on too large module id', async () => { await assert.revertsWithCustomError( - app.deposit(100, UINT24_MAX, '0x00', { value: 100, from: lido }), + router.deposit(100, UINT24_MAX, '0x00', { value: 100, from: lido }), 'StakingModuleIdTooLarge()' ) }) - it('deposit fails', async () => { + it('deposit fails when module is not active', async () => { await assert.revertsWithCustomError( - app.deposit(100, stakingModulesParams[0].expectedModuleId, '0x00', { value: ETH(32 * 100), from: lido }), + router.deposit(100, stakingModulesParams[0].expectedModuleId, '0x00', { value: ETH(32 * 100), from: lido }), 'StakingModuleNotActive()' ) }) it('getDepositsAllocation', async () => { - const keysAllocation = await app.getDepositsAllocation(1000) + const keysAllocation = await router.getDepositsAllocation(1000) assert.equals(keysAllocation.allocated, 0) assert.equals(keysAllocation.allocations, [0, 0]) @@ -776,7 +796,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('resume staking module does not allowed without role', async () => { await assert.reverts( - app.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { + router.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { from: stranger, }), `AccessControl: account ${stranger.toLowerCase()} is missing role ${STAKING_MODULE_RESUME_ROLE}` @@ -785,7 +805,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { it('resume staking module reverts when staking module id too large', async () => { await assert.revertsWithCustomError( - app.resumeStakingModule(UINT24_MAX, { + router.resumeStakingModule(UINT24_MAX, { from: appManager, }), `StakingModuleIdTooLarge()` @@ -793,20 +813,20 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('resume staking module does not allowed at not paused staking module', async () => { - await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { + await router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { from: appManager, }) await assert.revertsWithCustomError( - app.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { + router.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager, }), `StakingModuleNotPaused()` ) - await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { + await router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { from: appManager, }) await assert.revertsWithCustomError( - app.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { + router.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager, }), `StakingModuleNotPaused()` @@ -814,10 +834,14 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) it('resume staking module', async () => { - await app.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.DepositsPaused, { - from: appManager, - }) - const tx = await app.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { + await router.setStakingModuleStatus( + stakingModulesParams[0].expectedModuleId, + StakingModuleStatus.DepositsPaused, + { + from: appManager, + } + ) + const tx = await router.resumeStakingModule(stakingModulesParams[0].expectedModuleId, { from: appManager, }) @@ -828,4 +852,213 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) }) }) + + describe('report rewards minted', async () => { + before(snapshot) + after(revert) + + it('reverts if no REPORT_REWARDS_MINTED_ROLE role', async () => { + const stakingModuleIds = [1, 2] + const totalShares = [300, 400] + + await assert.revertsOZAccessControl( + router.reportRewardsMinted(stakingModuleIds, totalShares, { from: stranger }), + stranger, + 'REPORT_REWARDS_MINTED_ROLE' + ) + }) + + it('reverts if modules are not registered', async () => { + const stakingModuleIds = [1, 2] + const totalShares = [300, 400] + + await router.grantRole(await router.REPORT_REWARDS_MINTED_ROLE(), admin, { from: admin }) + await assert.reverts( + router.reportRewardsMinted(stakingModuleIds, totalShares, { from: admin }), + `StakingModuleUnregistered()` + ) + }) + + it('reverts if modules are not registered', async () => { + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await router.addStakingModule( + 'module 1', + module1.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: admin } + ) + await router.addStakingModule( + 'module 2', + module2.address, + 200, // 2 % _targetShare + 5_000, // 50 % _moduleFee + 0, // 0 % _treasuryFee + { from: admin } + ) + + const stakingModuleIds = [1, 2] + const totalShares = [300, 400] + + await router.grantRole(await router.REPORT_REWARDS_MINTED_ROLE(), admin, { from: admin }) + await router.reportRewardsMinted(stakingModuleIds, totalShares, { from: admin }) + + const module1lastcall = await module1.lastCall_onRewardsMinted() + assert.equal(+module1lastcall.callCount, 1) + assert.equal(+module1lastcall.totalShares, 300) + + const module2lastcall = await module2.lastCall_onRewardsMinted() + assert.equal(+module2lastcall.callCount, 1) + assert.equal(+module2lastcall.totalShares, 400) + }) + }) + + describe('updateRefundedValidatorsCount()', async () => { + before(snapshot) + after(revert) + + it('reverts if no stakingModuleId too large role', async () => { + const moduleId = new BN(2).pow(new BN(24)) + const nodeOperatorId = 1 + const refundedValidatorsCount = 3 + + await assert.reverts( + router.updateRefundedValidatorsCount(moduleId, nodeOperatorId, refundedValidatorsCount, { from: stranger }), + 'StakingModuleIdTooLarge()' + ) + }) + + it('reverts if no STAKING_MODULE_MANAGE_ROLE role', async () => { + const moduleId = 1 + const nodeOperatorId = 1 + const refundedValidatorsCount = 3 + + await assert.revertsOZAccessControl( + router.updateRefundedValidatorsCount(moduleId, nodeOperatorId, refundedValidatorsCount, { from: stranger }), + stranger, + 'STAKING_MODULE_MANAGE_ROLE' + ) + }) + + it('reverts if module not register', async () => { + const moduleId = 1 + const nodeOperatorId = 1 + const refundedValidatorsCount = 3 + + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await assert.reverts( + router.updateRefundedValidatorsCount(moduleId, nodeOperatorId, refundedValidatorsCount, { from: admin }), + 'StakingModuleUnregistered()' + ) + }) + + it('update refunded validators works', async () => { + const moduleId = 1 + const nodeOperatorId = 1 + const refundedValidatorsCount = 3 + + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await router.addStakingModule( + 'module 1', + module1.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: admin } + ) + + let lastCall = await module1.lastCall_updateRefundedValidatorsCount() + assert.equal(+lastCall.nodeOperatorId, 0) + assert.equal(+lastCall.refundedValidatorsCount, 0) + assert.equal(+lastCall.callCount, 0) + + await router.updateRefundedValidatorsCount(moduleId, nodeOperatorId, refundedValidatorsCount, { from: admin }) + + lastCall = await module1.lastCall_updateRefundedValidatorsCount() + assert.equal(+lastCall.nodeOperatorId, nodeOperatorId) + assert.equal(+lastCall.refundedValidatorsCount, refundedValidatorsCount) + assert.equal(+lastCall.callCount, 1) + }) + }) + + describe('getStakingModuleSummary()', async () => { + before(snapshot) + after(revert) + + let module1Id + + it('reverts if moduleId does not exists', async () => { + await assert.reverts(router.getStakingModuleSummary(0), 'StakingModuleUnregistered()') + }) + + it('module id summary works', async () => { + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await router.addStakingModule( + 'module 1', + module1.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: admin } + ) + module1Id = +(await router.getStakingModuleIds())[0] + + await module1.setTotalExitedValidatorsCount(11) + await module1.setActiveValidatorsCount(22) + await module1.setAvailableKeysCount(33) + + const summary = await router.getStakingModuleSummary(module1Id) + assert.equal(summary.totalExitedValidators, 11) + assert.equal(summary.totalDepositedValidators, 22) + assert.equal(summary.depositableValidatorsCount, 33) + }) + }) + + describe('getNodeOperatorSummary()', async () => { + before(snapshot) + after(revert) + + let module1Id + + it('reverts if moduleId does not exists', async () => { + await assert.reverts(router.getNodeOperatorSummary(0, 0), 'StakingModuleUnregistered()') + }) + + it('node operator summary by moduleId works', async () => { + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await router.addStakingModule( + 'module 1', + module1.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: admin } + ) + module1Id = +(await router.getStakingModuleIds())[0] + + const summary = { + isTargetLimitActive: true, + targetValidatorsCount: 1, + stuckValidatorsCount: 2, + refundedValidatorsCount: 3, + stuckPenaltyEndTimestamp: 4, + totalExitedValidators: 5, + totalDepositedValidators: 6, + depositableValidatorsCount: 7, + } + const nodeOperatorId = 0 + await module1.setNodeOperatorSummary(nodeOperatorId, summary) + + const moduleSummary = await router.getNodeOperatorSummary(module1Id, nodeOperatorId) + assert.equal(moduleSummary.isTargetLimitActive, true) + assert.equal(moduleSummary.targetValidatorsCount, 1) + assert.equal(moduleSummary.stuckValidatorsCount, 2) + assert.equal(moduleSummary.refundedValidatorsCount, 3) + assert.equal(moduleSummary.stuckPenaltyEndTimestamp, 4) + assert.equal(moduleSummary.totalExitedValidators, 5) + assert.equal(moduleSummary.totalDepositedValidators, 6) + assert.equal(moduleSummary.depositableValidatorsCount, 7) + }) + }) }) diff --git a/test/helpers/staking-modules.js b/test/helpers/staking-modules.js index bc946515d..ec9ee3905 100644 --- a/test/helpers/staking-modules.js +++ b/test/helpers/staking-modules.js @@ -80,6 +80,13 @@ async function setupNodeOperatorsRegistry({ dao, acl, lidoLocator, stakingRouter { from: appManager.address } ) + await acl.grantPermission( + stakingRouter.address, + nodeOperatorsRegistry.address, + NODE_OPERATOR_REGISTRY_MANAGE_NODE_OPERATOR_ROLE, + { from: appManager.address } + ) + return nodeOperatorsRegistry } From 2c8b858ba045756bf5cf03b1d45444d44013f75a Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Sun, 26 Feb 2023 23:33:11 +0200 Subject: [PATCH 036/236] feat: add basic sanity check --- contracts/0.8.9/WithdrawalQueueBase.sol | 96 ++++++++++++------- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- ...ithdrawal-queue-share-rate-changes.test.js | 2 + 5 files changed, 66 insertions(+), 38 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 3f449c753..c0fa03769 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -107,6 +107,7 @@ abstract contract WithdrawalQueueBase { error InvalidRequestId(uint256 _requestId); error InvalidRequestIdRange(uint256 startId, uint256 endId); error InvalidState(); + error InvalidBatches(); error EmptyBatches(); error RequestNotFoundOrNotFinalized(uint256 _requestId); error NotEnoughEther(); @@ -201,8 +202,8 @@ abstract contract WithdrawalQueueBase { _state.ethBudget -= etherRequested; if (length != 0 && ( - prevRequestShareRate < _maxShareRate && requestShareRate < _maxShareRate || - prevRequestShareRate >= _maxShareRate && requestShareRate >= _maxShareRate + prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || + prevRequestShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { _state.batches[length - 1] = requestId; } else { @@ -218,6 +219,7 @@ abstract contract WithdrawalQueueBase { _state.finished = requestId < postFinalId || requestId == lastRequestId + 1; if (_state.finished) { + assert(length <= MAX_NUMBER_OF_BATCHES); uint256[] memory batches = _state.batches; assembly { mstore(batches, length) @@ -230,50 +232,49 @@ abstract contract WithdrawalQueueBase { } function onPreRebase() external { - // Populate shareRate extrema array - // Invariants: - // • shareRate(extrema[0]) == shareRate(queue[1]) - // • shareRate(extrema[n]) != shareRate(extrema[n+1]) - // • extrema[last] is minimum => shareRate(lastRequestId) <= shareRate(lastRequestId) - // • extrema[last] is maximum => shareRate(lastRequestId) >= shareRate(lastRequestId) + // Populate shareRate extrema list uint256 lastRequestId = getLastRequestId(); uint256[] storage extrema = _getExtrema(); - // first request is an extremum + // first request is an extremum by default if (extrema.length == 0 && lastRequestId > 0) { extrema.push(lastRequestId); } uint256 lastExtremumId = extrema[extrema.length - 1]; + // no new requests => no new exrema + if (lastExtremumId == lastRequestId) return; - if (lastRequestId > lastExtremumId) { - uint256 lastRequestShareRate = _calcShareRate(lastRequestId); - uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId); + uint256 lastRequestShareRate = _calcShareRate(lastRequestId); + uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId); - if (lastRequestShareRate == lastExtremumShareRate) return; - // first met request in a sequence with equal shareRate is an extremum + if (lastRequestShareRate == lastExtremumShareRate) return; + // first met request in a sequence with equal shareRate is an extremum - if (extrema.length == 1) { - // first two different rates are always extrema + if (extrema.length == 1) { + // first two different rates are always extrema + extrema.push(lastRequestId); + } else { + uint256 prevExtremumShareRate = _calcShareRate(lastExtremumId - 1); + + bool wasGrowing = lastExtremumShareRate > prevExtremumShareRate; + // | • + // |• * + // +-------> + if (wasGrowing && lastRequestShareRate < lastExtremumShareRate) { extrema.push(lastRequestId); - } else { - uint256 prevExtremumShareRate = _calcShareRate(lastExtremumId - 1); - - bool wasGrowing = lastExtremumShareRate > prevExtremumShareRate; - // | • - // |• * - // +-------> - if (wasGrowing && lastRequestShareRate < lastExtremumShareRate) { - extrema.push(lastRequestId); - return; - } - // |• * - // | • - // +-------> - if (!wasGrowing && lastRequestShareRate > lastExtremumShareRate) { - extrema.push(lastRequestId); - return; - } + return; + } + // |• * + // | • + // +-------> + if (!wasGrowing && lastRequestShareRate > lastExtremumShareRate) { + extrema.push(lastRequestId); + return; } + // |• | * + // | * OR |• + // +----> +----> + extrema[extrema.length - 1] = lastRequestId; } } @@ -311,13 +312,36 @@ abstract contract WithdrawalQueueBase { function _checkFinalizationBatchesIntegrity(uint256[] memory _batches) internal view { if (_batches.length == 0) revert EmptyBatches(); + uint256 lastIdInBatch = _batches[_batches.length - 1]; if (lastIdInBatch > getLastRequestId()) revert InvalidRequestId(lastIdInBatch); + uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); uint256 firstIdInBatch = _batches[0]; if (firstIdInBatch <= lastFinalizedRequestId) revert InvalidRequestId(firstIdInBatch); - // TODO: check extrema and crossing points + // checking that between first and pre-last x-points we have odd number of extremums + uint256 index = _batches.length - 1; + uint256 currentExtrema = _getExtrema().length - 1; + + uint256 extremaCounter = 0; + + while (index > 0) { + uint256 extremumId = _getExtrema()[currentExtrema]; + + if (extremumId > _batches[index - 1]) { + --currentExtrema; + if (extremumId != _batches[index - 1] && extremumId < _batches[index]) { + // we are skipping extrema that are x-points in the same time + // and skipping extrema that are greater than the rightmost batchId + ++extremaCounter; + } + } else { + if (extremaCounter % 2 == 0) revert InvalidBatches(); + extremaCounter = 0; + --index; + } + } } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` @@ -334,6 +358,7 @@ abstract contract WithdrawalQueueBase { uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); + // TODO: Incorrect uint256 maxShareRate = SHARE_RATE_UNLIMITED; if (stETHToFinalize > _amountOfETH) { maxShareRate = _maxShareRate; @@ -520,6 +545,7 @@ abstract contract WithdrawalQueueBase { // 0-index is reserved as 'not_found' response in the interface everywhere _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint64(block.number), true); _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, 0); + _getExtrema().push(0); } function _sendValue(address _recipient, uint256 _amount) internal { diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index ff9012d5d..4ef2b629d 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index 71af00699..ea090f621 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":[],"name":"onPreRebase","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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":[],"name":"onPreRebase","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 807cc00f5..40dcc5a10 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index db9c29608..bc74c133f 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -60,6 +60,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives rewards, changing share rate to 2.0`, async () => { + await queue.onPreRebase() await setShareRate(2) }) @@ -70,6 +71,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives slashing, changing share rate to 1.0`, async () => { + await queue.onPreRebase() await setShareRate(1) }) From ccba587c91010ba0bc9c50cd3d896910f28fb740 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 27 Feb 2023 00:20:57 +0200 Subject: [PATCH 037/236] fix: checks, fixes and contract size optimizing --- contracts/0.8.9/WithdrawalQueue.sol | 32 +++++++------- contracts/0.8.9/WithdrawalQueueBase.sol | 55 +++++++++++++------------ contracts/0.8.9/utils/PausableUntil.sol | 16 +++++-- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 6 files changed, 62 insertions(+), 47 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index cf35d4548..236bc2fb3 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -98,13 +98,16 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } /// @notice Resume withdrawal requests placement and finalization - function resume() external whenPaused onlyRole(RESUME_ROLE) { + function resume() external { + _checkPaused(); + _checkRole(RESUME_ROLE, msg.sender); _resume(); } /// @notice Pause withdrawal requests placement and finalization. Claiming finalized requests will still be available /// @param _duration pause duration, seconds (use `PAUSE_INFINITELY` for unlimited) - function pause(uint256 _duration) external onlyRole(PAUSE_ROLE) { + function pause(uint256 _duration) external { + _checkRole(PAUSE_ROLE, msg.sender); _pause(_duration); } @@ -116,9 +119,9 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @return requestIds an array of the created withdrawal requests function requestWithdrawals(uint256[] calldata amounts, address _owner) public - whenResumed returns (uint256[] memory requestIds) { + _checkResumed(); if (_owner == address(0)) _owner = msg.sender; requestIds = new uint256[](amounts.length); for (uint256 i = 0; i < amounts.length; ++i) { @@ -135,9 +138,9 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @return requestIds an array of the created withdrawal requests function requestWithdrawalsWstETH(uint256[] calldata amounts, address _owner) public - whenResumed returns (uint256[] memory requestIds) { + _checkResumed(); if (_owner == address(0)) _owner = msg.sender; requestIds = new uint256[](amounts.length); for (uint256 i = 0; i < amounts.length; ++i) { @@ -163,7 +166,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @return requestIds an array of the created withdrawal requests function requestWithdrawalsWithPermit(uint256[] calldata _amounts, address _owner, PermitInput calldata _permit) external - whenResumed returns (uint256[] memory requestIds) { STETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s); @@ -182,7 +184,7 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit uint256[] calldata _amounts, address _owner, PermitInput calldata _permit - ) external whenResumed returns (uint256[] memory requestIds) { + ) external returns (uint256[] memory requestIds) { WSTETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s); return requestWithdrawalsWstETH(_amounts, _owner); } @@ -308,10 +310,14 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @notice Finalize requests from last finalized one up to `_lastRequestIdToFinalize` /// @dev ether to finalize all the requests should be calculated using `finalizationValue()` and sent along - /// - /// @param _nextFinalizedRequestId request index in the queue that will be last finalized request in a batch - function finalize(uint256 _nextFinalizedRequestId, uint256 _shareRate) external payable whenResumed onlyRole(FINALIZE_ROLE) { - _finalize(_nextFinalizedRequestId, msg.value, _shareRate); + function finalize(uint256[] calldata _batches, uint256 _maxShareRate) + external + payable + { + _checkResumed(); + _checkRole(FINALIZE_ROLE, msg.sender); + + _finalize(_batches, msg.value, _maxShareRate); } /// @notice Update bunker mode state @@ -319,10 +325,8 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// /// @param _isBunkerModeNow oracle report /// @param _sinceTimestamp timestamp of start of the bunker mode - function updateBunkerMode(bool _isBunkerModeNow, uint256 _sinceTimestamp) - external - onlyRole(BUNKER_MODE_REPORT_ROLE) - { + function updateBunkerMode(bool _isBunkerModeNow, uint256 _sinceTimestamp) external { + _checkRole(BUNKER_MODE_REPORT_ROLE, msg.sender); if (_sinceTimestamp >= block.timestamp) revert InvalidReportTimestamp(); bool isBunkerModeWasSetBefore = isBunkerModeActive(); diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index c0fa03769..f0e6c278f 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -20,10 +20,10 @@ abstract contract WithdrawalQueueBase { using UnstructuredRefStorage for bytes32; /// @notice precision base for share rate and discounting factor values in the contract - uint256 public constant E27_PRECISION_BASE = 1e27; + uint256 internal constant E27_PRECISION_BASE = 1e27; - uint256 public constant MAX_NUMBER_OF_BATCHES = 36; - uint256 public constant MAX_REQUESTS_PER_CALL = 1000; + uint256 internal constant MAX_REBASE_NUMBER = 36; + uint256 internal constant MAX_REQUESTS_PER_CALL = 1000; uint256 internal constant SHARE_RATE_UNLIMITED = type(uint256).max; @@ -175,19 +175,18 @@ abstract contract WithdrawalQueueBase { if (_state.batches.length == 0) { requestId = getLastFinalizedRequestId() + 1; - // we'll store batches as a array where [MAX_NUMBER_OF_BATCHES] element is the array's length - _state.batches = new uint256[](MAX_NUMBER_OF_BATCHES + 1); + // we'll store batches as a array where [MAX_REBASE_NUMBER] element is the array's length + _state.batches = new uint256[](MAX_REBASE_NUMBER + 1); } else { - uint256 prevIterationEndId = _state.batches[_state.batches[0]]; - requestId = prevIterationEndId + 1; - prevRequestShareRate = _calcShareRate(prevIterationEndId, _maxShareRate); + requestId = _state.batches[_state.batches[0]] + 1; + prevRequestShareRate = _calcShareRate(_state.batches[_state.batches[0]], _maxShareRate); } - uint256 length = _state.batches[MAX_NUMBER_OF_BATCHES]; - uint256 lastRequestId = getLastRequestId(); uint256 postFinalId = Math.min(requestId + MAX_REQUESTS_PER_CALL, lastRequestId + 1); + uint256 rebaseCounter; + while (requestId < postFinalId) { WithdrawalRequest memory request = _getQueue()[requestId]; @@ -201,15 +200,20 @@ abstract contract WithdrawalQueueBase { _state.ethBudget -= etherRequested; - if (length != 0 && ( + if (prevRequestShareRate != requestShareRate) { + ++rebaseCounter; + // finalization batch is 36 days max + if (rebaseCounter > MAX_REBASE_NUMBER) break; + } + + if (_state.batches[MAX_REBASE_NUMBER] != 0 && ( prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || prevRequestShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { - _state.batches[length - 1] = requestId; + _state.batches[_state.batches[MAX_REBASE_NUMBER] - 1] = requestId; } else { - if (length == MAX_NUMBER_OF_BATCHES) break; - _state.batches[length] = requestId; - ++length; + _state.batches[_state.batches[MAX_REBASE_NUMBER]] = requestId; + ++_state.batches[MAX_REBASE_NUMBER]; } prevRequestShareRate = requestShareRate; @@ -219,13 +223,12 @@ abstract contract WithdrawalQueueBase { _state.finished = requestId < postFinalId || requestId == lastRequestId + 1; if (_state.finished) { - assert(length <= MAX_NUMBER_OF_BATCHES); + assert(_state.batches[MAX_REBASE_NUMBER] <= MAX_REBASE_NUMBER); uint256[] memory batches = _state.batches; + uint256 length = _state.batches[MAX_REBASE_NUMBER]; assembly { mstore(batches, length) } - } else { - _state.batches[MAX_NUMBER_OF_BATCHES] = length; } return _state; @@ -346,21 +349,21 @@ abstract contract WithdrawalQueueBase { /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` /// Emits WithdrawalBatchFinalized event. - function _finalize(uint256 _nextFinalizedRequestId, uint256 _amountOfETH, uint256 _maxShareRate) internal { - if (_nextFinalizedRequestId > getLastRequestId()) revert InvalidRequestId(_nextFinalizedRequestId); + function _finalize(uint256[] memory _batches, uint256 _amountOfETH, uint256 _maxShareRate) internal { + uint256 nextFinalizedRequestId = _batches[_batches.length - 1]; + if (nextFinalizedRequestId > getLastRequestId()) revert InvalidRequestId(nextFinalizedRequestId); uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); uint256 firstUnfinalizedRequestId = lastFinalizedRequestId + 1; - if (_nextFinalizedRequestId <= lastFinalizedRequestId) revert InvalidRequestId(_nextFinalizedRequestId); + if (nextFinalizedRequestId <= lastFinalizedRequestId) revert InvalidRequestId(nextFinalizedRequestId); WithdrawalRequest memory lastFinalizedRequest = _getQueue()[lastFinalizedRequestId]; - WithdrawalRequest memory requestToFinalize = _getQueue()[_nextFinalizedRequestId]; + WithdrawalRequest memory requestToFinalize = _getQueue()[nextFinalizedRequestId]; uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); - // TODO: Incorrect uint256 maxShareRate = SHARE_RATE_UNLIMITED; - if (stETHToFinalize > _amountOfETH) { + if (_batches.length > 1) { maxShareRate = _maxShareRate; } @@ -374,11 +377,11 @@ abstract contract WithdrawalQueueBase { } _setLockedEtherAmount(getLockedEtherAmount() + _amountOfETH); - _setLastFinalizedRequestId(_nextFinalizedRequestId); + _setLastFinalizedRequestId(nextFinalizedRequestId); emit WithdrawalBatchFinalized( firstUnfinalizedRequestId, - _nextFinalizedRequestId, + nextFinalizedRequestId, _amountOfETH, requestToFinalize.cumulativeShares - lastFinalizedRequest.cumulativeShares, block.timestamp diff --git a/contracts/0.8.9/utils/PausableUntil.sol b/contracts/0.8.9/utils/PausableUntil.sol index 0fe8a8356..6560f5d12 100644 --- a/contracts/0.8.9/utils/PausableUntil.sol +++ b/contracts/0.8.9/utils/PausableUntil.sol @@ -24,18 +24,26 @@ contract PausableUntil { /// @notice Reverts when resumed modifier whenPaused() { - if (!isPaused()) { - revert PausedExpected(); - } + _checkPaused(); _; } /// @notice Reverts when paused modifier whenResumed() { + _checkResumed(); + _; + } + + function _checkPaused() internal view { + if (!isPaused()) { + revert PausedExpected(); + } + } + + function _checkResumed() internal view { if (isPaused()) { revert ResumedExpected(); } - _; } /// @notice Returns whether the contract is paused diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 4ef2b629d..d4500f14b 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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":"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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index ea090f621..742119b7e 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"E27_PRECISION_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":[],"name":"onPreRebase","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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":[],"name":"onPreRebase","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 40dcc5a10..8a9fd7ba9 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NUMBER_OF_BATCHES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REQUESTS_PER_CALL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nextFinalizedRequestId","type":"uint256"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 9f9fbae5db6525dd31752f4f2347e0bfba8e649a Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Mon, 27 Feb 2023 06:16:38 +0700 Subject: [PATCH 038/236] remove unused test --- .../staking-router-keys-reporting.test.js | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/test/0.8.9/staking-router/staking-router-keys-reporting.test.js b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js index 437b76fa0..aa71cb03e 100644 --- a/test/0.8.9/staking-router/staking-router-keys-reporting.test.js +++ b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js @@ -940,27 +940,5 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { await router.unsafeSetExitedValidatorsCount(module1Id, 0, true, ValidatorsCountsCorrection, { from: admin }) assert.equal(+(await module1.callCount_onExitedAndStuckValidatorsCountsUpdated()), 1) }) - - // it('reverts UnexpectedCurrentValidatorsCount()', async () => { - // let currentModuleExitedValidatorsCount=0 - // let currentNodeOperatorExitedValidatorsCount=0 - // let currentNodeOperatorStuckValidatorsCount=0 - // let newModuleExitedValidatorsCount=0 - // let newNodeOperatorExitedValidatorsCount=0 - // let newNodeOperatorStuckValidatorsCount=0 - - // let ValidatorsCountsCorrection = [ - // currentModuleExitedValidatorsCount, - // currentNodeOperatorExitedValidatorsCount, - // currentNodeOperatorStuckValidatorsCount, - // newModuleExitedValidatorsCount, - // newNodeOperatorExitedValidatorsCount, - // newNodeOperatorStuckValidatorsCount, - // ] - - // await router.grantRole(await router.UNSAFE_SET_EXITED_VALIDATORS_ROLE(), admin, { from: admin }) - - // await router.unsafeSetExitedValidatorsCount(module1Id,0,false,ValidatorsCountsCorrection, {from: admin}) - // }) }) }) From 79b3711548e52bb592a035a1f4e6cce0dcaa501a Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 01:50:56 +0300 Subject: [PATCH 039/236] fix: inject latest interface to Lido --- contracts/0.4.24/Lido.sol | 110 +++++++++--------- lib/abi/Lido.json | 2 +- test/0.4.24/lido-handle-oracle-report.test.js | 80 ++++++------- test/0.4.24/lido.test.js | 8 +- 4 files changed, 100 insertions(+), 100 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 59aef31fa..840db82c9 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -59,7 +59,7 @@ interface IOracleReportSanityChecker { ); function checkWithdrawalQueueOracleReport( - uint256 _lastFinalizableRequestId, + uint256[] _withdrawalFinalizationBatches, uint256 _reportTimestamp ) external view; @@ -113,18 +113,20 @@ interface IStakingRouter { } interface IWithdrawalQueue { - function finalizationBatch(uint256 _newLastFinalizedRequestId, uint256 _shareRate) + function finalizationValue(uint256[] _batches, uint256 _maxShareRate) external view returns (uint128 eth, uint128 shares); - function finalize(uint256 _lastIdToFinalize) external payable; + function finalize(uint256 _nextFinalizedRequestId, uint256 _maxShareRate) external payable; function isPaused() external view returns (bool); function unfinalizedStETH() external view returns (uint256); function isBunkerModeActive() external view returns (bool); + + function onPreRebase() external; } /** @@ -168,10 +170,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { 0xe6dc5d79630c61871e99d341ad72c5a052bed2fc8c79e5a4480a7cd31117576c; // keccak256("UNSAFE_CHANGE_DEPOSITED_VALIDATORS_ROLE") uint256 private constant DEPOSIT_SIZE = 32 ether; - uint256 public constant TOTAL_BASIS_POINTS = 10000; - /// @dev special value to not finalize withdrawal requests - /// see the `_lastFinalizableRequestId` arg for `handleOracleReport()` - uint256 private constant DONT_FINALIZE_WITHDRAWALS = 0; /// @dev storage slot position for the Lido protocol contracts locator bytes32 internal constant LIDO_LOCATOR_POSITION = @@ -269,7 +267,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { onlyInit { uint256 amount = _bootstrapInitialHolder(); - BUFFERED_ETHER_POSITION.setStorageUint256(amount); + _setBufferedEther(amount); emit Submitted(INITIAL_TOKEN_HOLDER, amount, 0); @@ -475,7 +473,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * are treated as a user deposit */ function receiveELRewards() external payable { - require(msg.sender == getLidoLocator().elRewardsVault(), "EXECUTION_LAYER_REWARDS_VAULT_ONLY"); + require(msg.sender == getLidoLocator().elRewardsVault()); TOTAL_EL_REWARDS_COLLECTED_POSITION.setStorageUint256(getTotalELRewardsCollected().add(msg.value)); @@ -530,7 +528,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 elRewardsVaultBalance; uint256 sharesRequestedToBurn; // Decision about withdrawals processing - uint256 lastFinalizableRequestId; + uint256[] withdrawalFinalizationBatches; uint256 simulatedShareRate; } @@ -559,17 +557,18 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer at `_reportTimestamp` * @param _elRewardsVaultBalance elRewards vault balance on Execution Layer at `_reportTimestamp` * @param _sharesRequestedToBurn shares requested to burn through Burner at `_reportTimestamp` - * @param _lastFinalizableRequestId right boundary of requestId range if equals 0, no requests should be finalized + * @param _withdrawalFinalizationBatches the ascendingly-sorted array of withdrawal request IDs obtained by calling + * WithdrawalQueue.calculateFinalizationBatches. Empty array means that no withdrawal requests should be finalized * @param _simulatedShareRate share rate that was simulated by oracle when the report data created (1e27 precision) * * NB: `_simulatedShareRate` should be calculated off-chain by calling the method with `eth_call` JSON-RPC API - * while passing `_lastFinalizableRequestId` == `_simulatedShareRate` == 0, and plugging the returned values + * while passing empty `_withdrawalFinalizationBatches` and `_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 + * @return postRebaseAmounts[0]: `postTotalPooledEther` amount of ether in the protocol after report + * @return postRebaseAmounts[1]: `postTotalShares` amount of shares in the protocol after report + * @return postRebaseAmounts[2]: `withdrawals` withdrawn from the withdrawals vault + * @return postRebaseAmounts[3]: `elRewards` withdrawn from the execution layer rewards vault */ function handleOracleReport( // Oracle timings @@ -583,14 +582,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 _elRewardsVaultBalance, uint256 _sharesRequestedToBurn, // Decision about withdrawals processing - uint256 _lastFinalizableRequestId, + uint256[] _withdrawalFinalizationBatches, uint256 _simulatedShareRate - ) external returns ( - uint256 postTotalPooledEther, - uint256 postTotalShares, - uint256 withdrawals, - uint256 elRewards - ) { + ) external returns (uint256[4] postRebaseAmounts) { _whenNotStopped(); return _handleOracleReport( @@ -602,7 +596,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { _withdrawalVaultBalance, _elRewardsVaultBalance, _sharesRequestedToBurn, - _lastFinalizableRequestId, + _withdrawalFinalizationBatches, _simulatedShareRate ) ); @@ -714,7 +708,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 depositsValue = depositsCount.mul(DEPOSIT_SIZE); /// @dev firstly update the local state of the contract to prevent a reentrancy attack, /// even if the StakingRouter is a trusted contract. - BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().sub(depositsValue)); + _setBufferedEther(_getBufferedEther().sub(depositsValue)); emit Unbuffered(depositsValue); uint256 newDepositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(depositsCount); @@ -832,7 +826,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { OracleReportContracts memory _contracts, uint256 _withdrawalsToWithdraw, uint256 _elRewardsToWithdraw, - uint256 _lastFinalizableRequestId, + uint256[] _withdrawalFinalizationBatches, + uint256 _simulatedShareRate, uint256 _etherToLockOnWithdrawalQueue ) internal { // withdraw execution layer rewards and put them to the buffer @@ -848,19 +843,18 @@ contract Lido is Versioned, StETHPermit, AragonApp { // finalize withdrawals (send ether, assign shares for burning) if (_etherToLockOnWithdrawalQueue > 0) { IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(_contracts.withdrawalQueue); - withdrawalQueue.finalize.value(_etherToLockOnWithdrawalQueue)(_lastFinalizableRequestId); + withdrawalQueue.finalize.value(_etherToLockOnWithdrawalQueue)( + _withdrawalFinalizationBatches[_withdrawalFinalizationBatches.length - 1], + _simulatedShareRate + ); } - uint256 preBufferedEther = _getBufferedEther(); - uint256 postBufferedEther = preBufferedEther + uint256 postBufferedEther = _getBufferedEther() .add(_elRewardsToWithdraw) // Collected from ELVault .add(_withdrawalsToWithdraw) // Collected from WithdrawalVault .sub(_etherToLockOnWithdrawalQueue); // Sent to WithdrawalQueue - // Storing even the same value costs gas, so just avoid it - if (preBufferedEther != postBufferedEther) { - BUFFERED_ETHER_POSITION.setStorageUint256(postBufferedEther); - } + _setBufferedEther(postBufferedEther); } /** @@ -877,12 +871,12 @@ contract Lido is Versioned, StETHPermit, AragonApp { if (!withdrawalQueue.isPaused()) { IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkWithdrawalQueueOracleReport( - _reportedData.lastFinalizableRequestId, + _reportedData.withdrawalFinalizationBatches, _reportedData.reportTimestamp ); - (etherToLock, sharesToBurn) = withdrawalQueue.finalizationBatch( - _reportedData.lastFinalizableRequestId, + (etherToLock, sharesToBurn) = withdrawalQueue.finalizationValue( + _reportedData.withdrawalFinalizationBatches, _reportedData.simulatedShareRate ); } @@ -903,13 +897,12 @@ contract Lido is Versioned, StETHPermit, AragonApp { // See LIP-12 for details: // https://research.lido.fi/t/lip-12-on-chain-part-of-the-rewards-distribution-after-the-merge/1625 if (postCLTotalBalance > _reportContext.preCLBalance) { - uint256 consensusLayerRewards = postCLTotalBalance.sub(_reportContext.preCLBalance); - uint256 totalRewards = consensusLayerRewards.add(_withdrawnElRewards); + uint256 consensusLayerRewards = postCLTotalBalance - _reportContext.preCLBalance; sharesMintedAsFees = _distributeFee( _reportContext.preTotalPooledEther, _reportContext.preTotalShares, - totalRewards + consensusLayerRewards.add(_withdrawnElRewards) ); } } @@ -939,7 +932,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { _mintShares(msg.sender, sharesAmount); - BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().add(msg.value)); + _setBufferedEther(_getBufferedEther().add(msg.value)); emit Submitted(msg.sender, msg.value, _referral); _emitTransferAfterMintingShares(msg.sender, sharesAmount); @@ -1066,10 +1059,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 totalFee, uint256 totalRewards ) internal returns (uint256[] memory moduleRewards, uint256 totalModuleRewards) { - totalModuleRewards = 0; moduleRewards = new uint256[](recipients.length); - for (uint256 i = 0; i < recipients.length; i++) { + for (uint256 i; i < recipients.length; ++i) { if (modulesFees[i] > 0) { uint256 iModuleRewards = totalRewards.mul(modulesFees[i]).div(totalFee); moduleRewards[i] = iModuleRewards; @@ -1093,6 +1085,10 @@ contract Lido is Versioned, StETHPermit, AragonApp { return BUFFERED_ETHER_POSITION.getStorageUint256(); } + function _setBufferedEther(uint256 _newBufferedEther) internal { + BUFFERED_ETHER_POSITION.setStorageUint256(_newBufferedEther); + } + /// @dev Calculates and returns the total base balance (multiple of 32) of validators in transient state, /// i.e. submitted to the official Deposit contract but not yet visible in the CL state. /// @return transient balance in wei (1e-18 Ether) @@ -1145,8 +1141,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @dev Size-efficient analog of the `auth(_role)` modifier * @param _role Permission name */ - function _auth(bytes32 _role) internal view auth(_role) { - // no-op + function _auth(bytes32 _role) internal view { + require(canPerform(msg.sender, _role, new uint256[](0)), "APP_AUTH_FAILED"); } /** @@ -1182,14 +1178,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * 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 - ) internal returns ( - uint256 postTotalPooledEther, - uint256 postTotalShares, - uint256 withdrawals, - uint256 elRewards - ) { + function _handleOracleReport(OracleReportedData memory _reportedData) internal returns (uint256[4]) { OracleReportContracts memory contracts = _loadOracleReportContracts(); require(msg.sender == contracts.accountingOracle, "APP_AUTH_FAILED"); @@ -1216,7 +1205,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 3. // Pre-calculate the ether to lock for withdrawal queue and shares to be burnt // due to withdrawal requests to finalize - if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { + if (_reportedData.withdrawalFinalizationBatches.length != 0) { + IWithdrawalQueue(contracts.withdrawalQueue).onPreRebase(); + ( reportContext.etherToLockOnWithdrawalQueue, reportContext.sharesToBurnFromWithdrawalQueue @@ -1230,6 +1221,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { } } + uint256 withdrawals; + uint256 elRewards; + // Step 4. // Pass the accounting values to sanity checker to smoothen positive token rebase ( @@ -1252,7 +1246,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { contracts, withdrawals, elRewards, - _reportedData.lastFinalizableRequestId, + _reportedData.withdrawalFinalizationBatches, + _reportedData.simulatedShareRate, reportContext.etherToLockOnWithdrawalQueue ); @@ -1281,6 +1276,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { _burnShares(contracts.burner, reportContext.sharesToBurn); } + uint256 postTotalShares; + uint256 postTotalPooledEther; + // Step 8. // Complete token rebase by informing observers (emit an event and call the external receivers if any) ( @@ -1293,7 +1291,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { ); // Step 9. Sanity check for the provided simulated share rate - if (_reportedData.lastFinalizableRequestId != DONT_FINALIZE_WITHDRAWALS) { + if (_reportedData.withdrawalFinalizationBatches.length != 0) { IOracleReportSanityChecker(contracts.oracleReportSanityChecker).checkSimulatedShareRate( postTotalPooledEther, postTotalShares, @@ -1302,6 +1300,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { _reportedData.simulatedShareRate ); } + + return [postTotalPooledEther, postTotalShares, withdrawals, elRewards]; } /** diff --git a/lib/abi/Lido.json b/lib/abi/Lido.json index 6585318ab..c28e25b8b 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":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":true,"stateMutability":"payable","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":"eip712Domain","outputs":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","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":true,"inputs":[],"name":"getEIP712StETH","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","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":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":"_sharesRequestedToBurn","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":true,"inputs":[],"name":"getDepositableEther","outputs":[{"name":"","type":"uint256"}],"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":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":"_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":true,"stateMutability":"payable","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":"eip712Domain","outputs":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","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":true,"inputs":[],"name":"getEIP712StETH","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_sharesRequestedToBurn","type":"uint256"},{"name":"_withdrawalFinalizationBatches","type":"uint256[]"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"postRebaseAmounts","type":"uint256[4]"}],"payable":false,"stateMutability":"nonpayable","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":"getDepositableEther","outputs":[{"name":"","type":"uint256"}],"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":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/test/0.4.24/lido-handle-oracle-report.test.js b/test/0.4.24/lido-handle-oracle-report.test.js index e6c70cce5..e10672daa 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -212,16 +212,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another } it('handleOracleReport access control', async () => { - await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'APP_AUTH_FAILED') + 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, 0, { from: stranger }), 'CONTRACT_IS_STOPPED') + 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 () => { - const tx = await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, [], 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -265,7 +265,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit without rewards', async () => { - const tx = await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, [], 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -295,7 +295,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit with rewards', async () => { - const tx = await lido.handleOracleReport(0, ONE_YEAR, 1, ETH(33), 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, ONE_YEAR, 1, ETH(33), 0, 0, 0, [], 0, { from: oracle }) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) await checkEvents({ tx, @@ -334,36 +334,36 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another it('reverts on reported more than deposited', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 4, 0, 0, 0, 0, 0, 0, { from: oracle }), + 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.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + 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.handleOracleReport(0, 0, 2, 0, 0, 0, 0, 0, 0, { from: oracle }), + 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.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, [], 0, { from: oracle }), 'IncorrectWithdrawalsVaultBalance(0)' ) }) it('withdrawal vault balance check 2', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, 0, { from: oracle }), + 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 () => { - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -389,7 +389,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 3, @@ -421,7 +421,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -447,7 +447,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, 0, 0, { from: oracle }) + tx = await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, [], 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 3, @@ -480,7 +480,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + 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, @@ -491,7 +491,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, [], 0, { from: oracle }), 'IncorrectCLBalanceDecrease(101)' ) }) @@ -506,7 +506,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + 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, @@ -516,7 +516,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - const tx = await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, [], 0, { from: oracle }) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.96), 10, 100, ETH(100), ETH(100.96)) await checkEvents({ tx, @@ -556,7 +556,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + 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, @@ -567,7 +567,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, [], 0, { from: oracle }), 'IncorrectCLBalanceIncrease(101)' ) }) @@ -584,7 +584,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 100, ETH(3200), 0, 0, 0, 0, 0, { from: oracle, 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) }) }) @@ -600,7 +600,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) await assert.reverts( - lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }), + lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }), 'IncorrectAppearedValidators(101)' ) }) @@ -628,7 +628,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, 0, 0, { from: oracle, 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) }) }) @@ -640,7 +640,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(100), 0, 0, 0, 0, 0, { from: oracle, 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) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(4), @@ -663,7 +663,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, 0, 0, { from: oracle, 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), @@ -687,7 +687,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1.1), 0, 0, 0, 0, { from: oracle, 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), @@ -712,7 +712,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1), 0, 0, 0, { from: oracle, 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({ @@ -738,7 +738,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(95.5), 0, ETH(1.5), 0, 0, 0, { from: oracle, 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), @@ -763,7 +763,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1.1), 0, 0, 0, { from: oracle, 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), @@ -787,7 +787,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(0.9), 0, 0, 0, { from: oracle, 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({ @@ -813,7 +813,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(1.1), 0, 0, 0, { from: oracle, 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), @@ -851,7 +851,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -872,7 +872,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.0027), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.0027), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.0027) }) }) @@ -885,7 +885,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96 + 0.0028), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96 + 0.0028), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96 + clIncrease) }) assert( 0.00014 + 0.0028 * 0.9 * 0.3 + 0.0028 * 0.9 * 0.69 + 0.0028 * 0.01 * 0.9 + 0.00014 === clIncrease, @@ -912,7 +912,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -936,7 +936,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1.1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -961,7 +961,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1), 0, [], 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -987,7 +987,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(95.5), 0, ETH(1.5), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -1012,7 +1012,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -1036,7 +1036,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(0.9), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport(0, ONE_DAY, 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({ diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index c1814c1bf..830ea7859 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -381,14 +381,14 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await app.setELRewardsWithdrawalLimit(initialValue, { from: voting }) // unable to receive execution layer rewards from arbitrary account - await assert.reverts(app.receiveELRewards({ from: user1, value: ETH(1) }), 'EXECUTION_LAYER_REWARDS_VAULT_ONLY') + await assert.reverts(app.receiveELRewards({ from: user1, value: ETH(1) })) }) }) }) describe('receiveELRewards()', async () => { it('unable to receive eth from arbitrary account', async () => { - await assert.reverts(app.receiveELRewards({ from: nobody, value: ETH(1) }), 'EXECUTION_LAYER_REWARDS_VAULT_ONLY') + await assert.reverts(app.receiveELRewards({ from: nobody, value: ETH(1) })) }) it('event work', async () => { @@ -984,7 +984,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await checkStat({ depositedValidators: 1, beaconValidators: 0, beaconBalance: ETH(0) }) await assert.reverts( - app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(30), 0, 0, 0, 0, 0, 0, { from: appManager }), + app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(30), 0, 0, 0, 0, [], 0, { from: appManager }), 'APP_AUTH_FAILED' ) @@ -992,7 +992,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await checkStat({ depositedValidators: 1, beaconValidators: 1, beaconBalance: ETH(30) }) await assert.reverts( - app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(29), 0, 0, 0, 0, 0, 0, { from: nobody }), + app.handleOracleReport(await getCurrentBlockTimestamp(), 1, ETH(29), 0, 0, 0, 0, [], 0, { from: nobody }), 'APP_AUTH_FAILED' ) From 25b0bebbe4c680e928e38455edadf882fea2cb0b Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 02:16:07 +0300 Subject: [PATCH 040/236] fix: update sanity checker --- .../sanity_checks/OracleReportSanityChecker.sol | 15 ++++++++------- .../OracleReportSanityCheckerMocks.sol | 3 +-- lib/abi/OracleReportSanityChecker.json | 2 +- test/0.8.9/oracle-report-sanity-checker.test.js | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index acf729969..06624ce85 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -470,11 +470,11 @@ contract OracleReportSanityChecker is AccessControlEnumerable { } /// @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 _withdrawalFinalizationBatches the ascendingly-sorted array of withdrawal request IDs obtained by calling + /// WithdrawalQueue.calculateFinalizationBatches. Empty array means that no withdrawal requests should be finalized /// @param _reportTimestamp timestamp when the originated oracle report was submitted function checkWithdrawalQueueOracleReport( - uint256 _lastFinalizableRequestId, + uint256[] calldata _withdrawalFinalizationBatches, uint256 _reportTimestamp ) external @@ -483,7 +483,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { LimitsList memory limitsList = _limits.unpack(); address withdrawalQueue = LIDO_LOCATOR.withdrawalQueue(); - _checkRequestIdToFinalizeUpTo(limitsList, withdrawalQueue, _lastFinalizableRequestId, _reportTimestamp); + _checkFinalizationBatches(limitsList, withdrawalQueue, _withdrawalFinalizationBatches, _reportTimestamp); } /// @notice Applies sanity checks to the simulated share rate for withdrawal requests finalization @@ -593,14 +593,15 @@ contract OracleReportSanityChecker is AccessControlEnumerable { if (_appearedValidators > churnLimit) revert IncorrectAppearedValidators(_appearedValidators); } - function _checkRequestIdToFinalizeUpTo( + function _checkFinalizationBatches( LimitsList memory _limitsList, address _withdrawalQueue, - uint256 _requestIdToFinalizeUpTo, + uint256[] calldata _withdrawalFinalizationBatches, uint256 _reportTimestamp ) internal view { + //TODO: update sanity check (, , , uint256 requestTimestampToFinalizeUpTo, , ) = IWithdrawalQueue(_withdrawalQueue) - .getWithdrawalRequestStatus(_requestIdToFinalizeUpTo); + .getWithdrawalRequestStatus(_withdrawalFinalizationBatches[_withdrawalFinalizationBatches.length - 1]); if (_reportTimestamp < requestTimestampToFinalizeUpTo + _limitsList.requestTimestampMargin) revert IncorrectRequestFinalization(requestTimestampToFinalizeUpTo); } diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index 23d597ba2..bf1def18d 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -115,8 +115,7 @@ contract OracleReportSanityCheckerStub { ) external view {} function checkWithdrawalQueueOracleReport( - uint256 _lastFinalizableRequestId, - uint256 _simulatedShareRate, + uint256[] calldata _withdrawalFinalizationBatches, uint256 _reportTimestamp ) external view {} diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index a824c32f6..c4f35b259 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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"actualBurnerRequests","type":"uint256"}],"name":"IncorrectBurnerRequests","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"actualBurnerRequests","type":"uint256"}],"name":"IncorrectBurnerRequests","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"checkSimulatedShareRate","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_withdrawalFinalizationBatches","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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 e78914ec8..f9b747ac6 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -243,7 +243,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa const newRequestId = 2 let oldRequestCreationTimestamp, newRequestCreationTimestamp const correctWithdrawalQueueOracleReport = { - requestIdToFinalizeUpTo: oldRequestId, + withdrawalFinalizationBatches: [oldRequestId], refReportTimestamp: -1, } @@ -251,7 +251,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa const currentBlockTimestamp = await getCurrentBlockTimestamp() correctWithdrawalQueueOracleReport.refReportTimestamp = currentBlockTimestamp oldRequestCreationTimestamp = currentBlockTimestamp - defaultLimitsList.requestTimestampMargin - correctWithdrawalQueueOracleReport.requestIdToFinalizeUpTo = oldRequestCreationTimestamp + correctWithdrawalQueueOracleReport.withdrawalFinalizationBatches[0] = oldRequestCreationTimestamp await withdrawalQueueMock.setRequestBlockNumber(oldRequestId, oldRequestCreationTimestamp) newRequestCreationTimestamp = currentBlockTimestamp - Math.floor(defaultLimitsList.requestTimestampMargin / 2) await withdrawalQueueMock.setRequestBlockNumber(newRequestId, newRequestCreationTimestamp) @@ -262,7 +262,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa oracleReportSanityChecker.checkWithdrawalQueueOracleReport( ...Object.values({ ...correctWithdrawalQueueOracleReport, - requestIdToFinalizeUpTo: newRequestId, + withdrawalFinalizationBatches: [newRequestId], }) ), `IncorrectRequestFinalization(${newRequestCreationTimestamp})` From b3a59ecb9040787e9bf3969bc4eda4b365d1fb39 Mon Sep 17 00:00:00 2001 From: Andrei Date: Mon, 27 Feb 2023 12:17:59 +0700 Subject: [PATCH 041/236] test: withdrawalQueue: nft: mint, burn, token address --- .../0.8.9/test_helpers/NFTDescriptorMock.sol | 50 +++ test/0.8.9/withdrawal-queue-deploy.test.js | 14 +- test/0.8.9/withdrawal-queue-nft.test.js | 391 ++++++++++++++++++ 3 files changed, 453 insertions(+), 2 deletions(-) create mode 100644 contracts/0.8.9/test_helpers/NFTDescriptorMock.sol create mode 100644 test/0.8.9/withdrawal-queue-nft.test.js diff --git a/contracts/0.8.9/test_helpers/NFTDescriptorMock.sol b/contracts/0.8.9/test_helpers/NFTDescriptorMock.sol new file mode 100644 index 000000000..eca029393 --- /dev/null +++ b/contracts/0.8.9/test_helpers/NFTDescriptorMock.sol @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +/* See contracts/COMPILERS.md */ +pragma solidity 0.8.9; + +import { Strings } from "@openzeppelin/contracts-v4.4/utils/Strings.sol"; +import { INFTDescriptor } from "../WithdrawalQueueERC721.sol"; + +contract NFTDescriptorMock is INFTDescriptor { + using Strings for uint256; + + bytes32 private BASE_TOKEN_URI; + + constructor(string memory _baseURI) INFTDescriptor() { + BASE_TOKEN_URI = _toBytes32(_baseURI); + } + + function constructTokenURI( + uint256 _requestId + ) external view returns (string memory) { + string memory baseURI = _toString(BASE_TOKEN_URI); + return string(abi.encodePacked(baseURI, _requestId.toString())); + } + + function baseTokenURI() external view returns (string memory) { + return _toString(BASE_TOKEN_URI); + } + + function setBaseTokenURI(string memory _baseURI) external { + BASE_TOKEN_URI = _toBytes32(_baseURI); + } + + function _toBytes32(string memory _str) internal pure returns (bytes32) { + bytes memory bstr = bytes(_str); + require(bstr.length <= 32, "NFTDescriptor: string too long"); + return bytes32(uint256(bytes32(bstr)) | bstr.length); + } + + function _toString(bytes32 _sstr) internal pure returns (string memory) { + uint256 len = uint256(_sstr) & 0xFF; + string memory str = new string(32); + /// @solidity memory-safe-assembly + assembly { + mstore(str, len) + mstore(add(str, 0x20), _sstr) + } + return str; + } +} diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 84b884e45..e9ab7a2f4 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -8,6 +8,11 @@ const { assert } = require('../helpers/assert') const StETHMock = artifacts.require('StETHPermitMock.sol') const WstETH = artifacts.require('WstETHMock.sol') const EIP712StETH = artifacts.require('EIP712StETH') +const NFTDescriptorMock = artifacts.require('NFTDescriptorMock.sol') + +const QUEUE_NAME = 'Unsteth nft' +const QUEUE_SYMBOL = 'UNSTETH' +const NFT_DESCRIPTOR_BASE_URI = 'https://exampleDescriptor.com/' async function deployWithdrawalQueue({ stethOwner, @@ -16,10 +21,11 @@ async function deployWithdrawalQueue({ queueResumer, queueFinalizer, queueBunkerReporter, - queueName = 'Unsteth nft', - symbol = 'UNSTETH', + queueName = QUEUE_NAME, + symbol = QUEUE_SYMBOL, doResume = true, }) { + const nftDescriptor = await NFTDescriptorMock.new(NFT_DESCRIPTOR_BASE_URI) const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) const wsteth = await WstETH.new(steth.address, { from: stethOwner }) const eip712StETH = await EIP712StETH.new(steth.address, { from: stethOwner }) @@ -44,11 +50,15 @@ async function deployWithdrawalQueue({ steth, wsteth, withdrawalQueue, + nftDescriptor, } } module.exports = { deployWithdrawalQueue, + QUEUE_NAME, + QUEUE_SYMBOL, + NFT_DESCRIPTOR_BASE_URI, } contract( diff --git a/test/0.8.9/withdrawal-queue-nft.test.js b/test/0.8.9/withdrawal-queue-nft.test.js new file mode 100644 index 000000000..985b1373f --- /dev/null +++ b/test/0.8.9/withdrawal-queue-nft.test.js @@ -0,0 +1,391 @@ +const { contract, ethers, web3 } = require('hardhat') +const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') + +const { ETH, StETH, shareRate, shares } = require('../helpers/utils') +const { assert } = require('../helpers/assert') +const { impersonate, EvmSnapshot, setBalance } = require('../helpers/blockchain') + +const { + deployWithdrawalQueue, + QUEUE_NAME, + QUEUE_SYMBOL, + NFT_DESCRIPTOR_BASE_URI, +} = require('./withdrawal-queue-deploy.test') + +contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) => { + let withdrawalQueue, steth, nftDescriptor + + const manageTokenUriRoleKeccak156 = web3.utils.keccak256('MANAGE_TOKEN_URI_ROLE') + const snapshot = new EvmSnapshot(ethers.provider) + + before('Deploy', async () => { + const deployed = await deployWithdrawalQueue({ + stethOwner: owner, + queueAdmin: daoAgent, + queuePauser: daoAgent, + queueResumer: daoAgent, + queueFinalizer: daoAgent, + }) + + steth = deployed.steth + withdrawalQueue = deployed.withdrawalQueue + nftDescriptor = deployed.nftDescriptor + + await steth.setTotalPooledEther(ETH(600)) + // we need 1 ETH additionally to pay gas on finalization because coverage ingnores gasPrice=0 + await setBalance(steth.address, ETH(600 + 1)) + await steth.mintShares(user, shares(1)) + await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) + await withdrawalQueue.grantRole(manageTokenUriRoleKeccak156, tokenUriManager, { from: daoAgent }) + + await impersonate(ethers.provider, steth.address) + await snapshot.make() + }) + + afterEach(async () => { + await snapshot.rollback() + }) + + it('Initial properties', async () => { + assert.equals(await withdrawalQueue.isPaused(), false) + assert.equals(await withdrawalQueue.getLastRequestId(), 0) + assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 0) + assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 0) + assert.equals(await withdrawalQueue.unfinalizedStETH(), StETH(0)) + assert.equals(await withdrawalQueue.unfinalizedRequestNumber(), 0) + assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(0)) + }) + + context('constructor', function () { + it('should set name and symbol', async function () { + assert.equals(await withdrawalQueue.name(), QUEUE_NAME) + assert.equals(await withdrawalQueue.symbol(), QUEUE_SYMBOL) + }) + }) + + context('supportsInterface', async () => { + it('supports ERC165', async () => { + assert.isTrue(await withdrawalQueue.supportsInterface('0x01ffc9a7')) + }) + + it('supports ERC721', async () => { + assert.isTrue(await withdrawalQueue.supportsInterface('0x80ac58cd')) + }) + + it('supports ERC721Metadata', async () => { + assert.isTrue(await withdrawalQueue.supportsInterface('0x5b5e139f')) + }) + + it('not supports interface not supported', async () => { + assert.isFalse(await withdrawalQueue.supportsInterface('0x12345678')) + }) + }) + + context('name', async () => { + it('returns name', async () => { + assert.equals(await withdrawalQueue.name(), QUEUE_NAME) + }) + }) + + context('symbol', async () => { + it('returns symbol', async () => { + assert.equals(await withdrawalQueue.symbol(), QUEUE_SYMBOL) + }) + }) + + context('tokenURI', async () => { + const requestId = 1 + const baseTokenUri = 'https://example.com/' + + beforeEach(async function () { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + }) + + it('returns tokenURI without nftDescriptor', async () => { + await withdrawalQueue.setBaseURI(baseTokenUri, { from: tokenUriManager }) + assert.equals(await withdrawalQueue.tokenURI(1), `${baseTokenUri}${requestId}`) + }) + + it('returns tokenURI without nftDescriptor and baseUri', async () => { + assert.equals(await withdrawalQueue.tokenURI(1), '') + }) + + it('returns tokenURI with nftDescriptor', async () => { + await withdrawalQueue.setNFTDescriptorAddress(nftDescriptor.address, { from: tokenUriManager }) + + assert.equals(await withdrawalQueue.tokenURI(1), `${NFT_DESCRIPTOR_BASE_URI}${requestId}`) + }) + + it('revert on invalid token id', async () => { + await assert.reverts(withdrawalQueue.tokenURI(0), 'InvalidRequestId(0)') + }) + + it('should set baseURI and return', async () => { + await withdrawalQueue.setBaseURI(baseTokenUri, { from: tokenUriManager }) + assert.equals(await withdrawalQueue.getBaseURI(), baseTokenUri) + }) + + it('should set nftDescriptorAddress and return', async () => { + await withdrawalQueue.setNFTDescriptorAddress(nftDescriptor.address, { from: tokenUriManager }) + assert.equals(await withdrawalQueue.getNFTDescriptorAddress(), nftDescriptor.address) + }) + }) + + context('balanceOf', () => { + it('should return 0 for not existing', async () => { + assert.equals(await withdrawalQueue.balanceOf(stranger), 0) + }) + + it('should return 1 after request', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + }) + + it('should return 2 after request', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 2) + }) + + it('should return 0 after claim', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + + const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) + await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 0) + }) + + it('should revert with ZeroAddress', async () => { + await assert.reverts(withdrawalQueue.balanceOf(ZERO_ADDRESS), `InvalidOwnerAddress("${ZERO_ADDRESS}")`) + }) + }) + + context('ownerOf', () => { + it('should revert with not existing', async () => { + await assert.reverts(withdrawalQueue.ownerOf(1), 'InvalidRequestId(1)') + }) + it('should return owner after request', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.ownerOf(1), user) + }) + + it('should revert after claim', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.ownerOf(1), user) + + const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) + await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + + await assert.reverts(withdrawalQueue.ownerOf(1), 'RequestAlreadyClaimed(1)') + }) + }) + + context('getApproved', () => { + it('should revert with invalid request id', async () => { + await assert.reverts(withdrawalQueue.getApproved(1), 'InvalidRequestId(1)') + }) + + it('should return zero address for not approved', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.getApproved(1), ZERO_ADDRESS) + }) + + it('should return approved address', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) + await withdrawalQueue.approve(stranger, 1, { from: user }) + assert.equals(await withdrawalQueue.getApproved(1), stranger) + }) + }) + + context('isApprovedForAll', () => { + it('should return false for not approved', async () => { + assert.isFalse(await withdrawalQueue.isApprovedForAll(user, stranger)) + }) + + it('should return true for approved', async () => { + await withdrawalQueue.setApprovalForAll(stranger, true, { from: user }) + assert.isTrue(await withdrawalQueue.isApprovedForAll(user, stranger)) + }) + }) + + context('mint', async () => { + it('should mint', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.tokenURI(1), '') + }) + + it('should mint with tokenURI', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + await withdrawalQueue.setBaseURI('https://example.com/', { from: tokenUriManager }) + + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.tokenURI(1), 'https://example.com/1') + }) + + it('should mint with nftDescriptor', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + await withdrawalQueue.setNFTDescriptorAddress(nftDescriptor.address, { from: tokenUriManager }) + nftDescriptor.setBaseTokenURI('https://nftDescriptor.com/') + + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.tokenURI(1), 'https://nftDescriptor.com/1') + }) + + it('should mint more after request', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 4) + assert.equals(await withdrawalQueue.ownerOf(3), user) + assert.equals(await withdrawalQueue.ownerOf(4), user) + }) + }) + + context('burn', async () => { + it('should burn', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + + const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) + await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.ownerOf(2), user) + await assert.reverts(withdrawalQueue.ownerOf(1), 'RequestAlreadyClaimed(1)') + }) + + it('revert on claim not owner', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + + const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) + await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + + await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: stranger }), `NotOwner("${stranger}", "${user}")`) + + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + }) + + it('revert on claim not existing', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + + await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: user }), 'RequestNotFoundOrNotFinalized(1)') + }) + + it('should burn more after request', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + + const batch = await withdrawalQueue.finalizationBatch(2, shareRate(1)) + await withdrawalQueue.finalize(2, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.ownerOf(2), user) + await assert.reverts(withdrawalQueue.ownerOf(1), 'RequestAlreadyClaimed(1)') + + await withdrawalQueue.claimWithdrawal(2, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 0) + }) + + it('should burn after transfer', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + + await withdrawalQueue.transferFrom(user, stranger, 1, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.ownerOf(2), user) + assert.equals(await withdrawalQueue.ownerOf(1), stranger) + + const batch = await withdrawalQueue.finalizationBatch(2, shareRate(1)) + await withdrawalQueue.finalize(2, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.claimWithdrawal(2, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 0) + }) + + it('should revert on transfer himself', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + + await assert.reverts(withdrawalQueue.transferFrom(user, user, 1, { from: user }), 'TransferToThemselves()') + }) + + it('should revert on transfer not owner', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + + await assert.reverts( + withdrawalQueue.transferFrom(user, stranger, 1, { from: stranger }), + `NotOwnerOrApproved("${stranger}")` + ) + }) + + it('should burn after approve and transfer ', async () => { + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25), ETH(25)], user, { from: user }) + assert.equals(await withdrawalQueue.balanceOf(user), 3) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + assert.equals(await withdrawalQueue.ownerOf(3), user) + + await withdrawalQueue.approve(stranger, 2, { from: user }) + await withdrawalQueue.approve(stranger, 3, { from: user }) + + assert.equals(await withdrawalQueue.balanceOf(user), 3) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + assert.equals(await withdrawalQueue.ownerOf(3), user) + + await withdrawalQueue.transferFrom(user, stranger, 3, { from: stranger }) + + assert.equals(await withdrawalQueue.balanceOf(user), 2) + assert.equals(await withdrawalQueue.balanceOf(stranger), 1) + assert.equals(await withdrawalQueue.ownerOf(1), user) + assert.equals(await withdrawalQueue.ownerOf(2), user) + assert.equals(await withdrawalQueue.ownerOf(3), stranger) + + const batch = await withdrawalQueue.finalizationBatch(3, shareRate(1)) + await withdrawalQueue.finalize(3, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + await withdrawalQueue.claimWithdrawal(3, { from: stranger }) + + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.balanceOf(stranger), 0) + + await assert.reverts(withdrawalQueue.claimWithdrawal(2, { from: stranger }), `NotOwner("${stranger}", "${user}")`) + + assert.equals(await withdrawalQueue.balanceOf(user), 1) + }) + }) +}) From 659b648bd7564a18246ba742d9434ddd0259106d Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 27 Feb 2023 10:29:20 +0200 Subject: [PATCH 042/236] fix: proper Checkpoint optimization --- contracts/0.8.9/WithdrawalQueueBase.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index f0e6c278f..ba4c37ce8 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -338,10 +338,12 @@ abstract contract WithdrawalQueueBase { // we are skipping extrema that are x-points in the same time // and skipping extrema that are greater than the rightmost batchId ++extremaCounter; + // TODO: check that extremum is above or below the line } } else { if (extremaCounter % 2 == 0) revert InvalidBatches(); extremaCounter = 0; + // TODO: check that batch[index] is really crossing point --index; } } @@ -363,7 +365,8 @@ abstract contract WithdrawalQueueBase { if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); uint256 maxShareRate = SHARE_RATE_UNLIMITED; - if (_batches.length > 1) { + // if we have a crossing point or avg batch share rate is more than `_maxShareRate` + if (_batches.length > 1 || stETHToFinalize > _amountOfETH) { maxShareRate = _maxShareRate; } From f93b9f5db32b3a2d9b5e9b61f9c1484d9d0854eb Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 11:35:51 +0300 Subject: [PATCH 043/236] chore: restrict visibility as compiler warns --- contracts/0.8.9/StakingRouter.sol | 2 +- contracts/0.8.9/oracle/AccountingOracle.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 1ec148083..551d9f1e3 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -1026,7 +1026,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version function _checkValidatorsByNodeOperatorReportData( bytes calldata _nodeOperatorIds, bytes calldata _validatorsCounts - ) internal { + ) internal pure { if (_nodeOperatorIds.length % 8 != 0 || _validatorsCounts.length % 16 != 0) { revert InvalidReportData(3); } diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index f1d8478dd..fdb2bc0c3 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -692,7 +692,7 @@ contract AccountingOracle is BaseOracle { } function _checkCanSubmitExtraData(ExtraDataProcessingState memory procState, uint256 format) - internal + internal view { _checkMsgSenderIsAllowedToSubmitData(); _checkProcessingDeadline(); From 51e60711bc360c99f8b68bec2ce50eeebe693e16 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 11:36:25 +0300 Subject: [PATCH 044/236] chore: visible broken ABI err for pre-commit hook --- .husky/pre-commit | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index c79d6bcc2..b63c34415 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,7 +1,10 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" +RED_COLOR='\033[0;31m' +NO_COLOR='\033[0m' + yarn compile -git diff --quiet lib/abi +git diff --quiet lib/abi || (echo -e "${RED_COLOR}Unstaged ABIs detected${NO_COLOR}"; exit 1) yarn lint From a8e9e7347f1ecce581564eed191b90048f42005a Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 11:37:28 +0300 Subject: [PATCH 045/236] fix: review fixes --- contracts/0.4.24/Lido.sol | 12 ++++-------- contracts/0.8.9/oracle/AccountingOracle.sol | 3 +++ .../sanity_checks/OracleReportSanityChecker.sol | 14 ++++++-------- .../MockWithdrawalQueueForAccoutingOracle.sol | 8 ++++++++ lib/abi/OracleReportSanityChecker.json | 2 +- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 840db82c9..fe34812b2 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -59,7 +59,7 @@ interface IOracleReportSanityChecker { ); function checkWithdrawalQueueOracleReport( - uint256[] _withdrawalFinalizationBatches, + uint256 _lastFinalizableRequestId, uint256 _reportTimestamp ) external view; @@ -118,15 +118,13 @@ interface IWithdrawalQueue { view returns (uint128 eth, uint128 shares); - function finalize(uint256 _nextFinalizedRequestId, uint256 _maxShareRate) external payable; + function finalize(uint256[] _batches, uint256 _maxShareRate) external payable; function isPaused() external view returns (bool); function unfinalizedStETH() external view returns (uint256); function isBunkerModeActive() external view returns (bool); - - function onPreRebase() external; } /** @@ -844,7 +842,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { if (_etherToLockOnWithdrawalQueue > 0) { IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(_contracts.withdrawalQueue); withdrawalQueue.finalize.value(_etherToLockOnWithdrawalQueue)( - _withdrawalFinalizationBatches[_withdrawalFinalizationBatches.length - 1], + _withdrawalFinalizationBatches, _simulatedShareRate ); } @@ -871,7 +869,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { if (!withdrawalQueue.isPaused()) { IOracleReportSanityChecker(_contracts.oracleReportSanityChecker).checkWithdrawalQueueOracleReport( - _reportedData.withdrawalFinalizationBatches, + _reportedData.withdrawalFinalizationBatches[_reportedData.withdrawalFinalizationBatches.length - 1], _reportedData.reportTimestamp ); @@ -1206,8 +1204,6 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Pre-calculate the ether to lock for withdrawal queue and shares to be burnt // due to withdrawal requests to finalize if (_reportedData.withdrawalFinalizationBatches.length != 0) { - IWithdrawalQueue(contracts.withdrawalQueue).onPreRebase(); - ( reportContext.etherToLockOnWithdrawalQueue, reportContext.sharesToBurnFromWithdrawalQueue diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index fdb2bc0c3..bc790d87c 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -82,6 +82,7 @@ interface IStakingRouter { interface IWithdrawalQueue { function updateBunkerMode(bool isBunkerMode, uint256 prevReportTimestamp) external; + function onPreRebase() external; } @@ -610,6 +611,8 @@ contract AccountingOracle is BaseOracle { GENESIS_TIME + prevRefSlot * SECONDS_PER_SLOT ); + withdrawalQueue.onPreRebase(); + ILido(LIDO).handleOracleReport( GENESIS_TIME + data.refSlot * SECONDS_PER_SLOT, slotsElapsed * SECONDS_PER_SLOT, diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 06624ce85..e402b19ba 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -470,11 +470,10 @@ contract OracleReportSanityChecker is AccessControlEnumerable { } /// @notice Applies sanity checks to the withdrawal requests finalization - /// @param _withdrawalFinalizationBatches the ascendingly-sorted array of withdrawal request IDs obtained by calling - /// WithdrawalQueue.calculateFinalizationBatches. Empty array means that no withdrawal requests should be finalized + /// @param _lastFinalizableRequestId last finalizable withdrawal request id /// @param _reportTimestamp timestamp when the originated oracle report was submitted function checkWithdrawalQueueOracleReport( - uint256[] calldata _withdrawalFinalizationBatches, + uint256 _lastFinalizableRequestId, uint256 _reportTimestamp ) external @@ -483,7 +482,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { LimitsList memory limitsList = _limits.unpack(); address withdrawalQueue = LIDO_LOCATOR.withdrawalQueue(); - _checkFinalizationBatches(limitsList, withdrawalQueue, _withdrawalFinalizationBatches, _reportTimestamp); + _checkLastFinalizableId(limitsList, withdrawalQueue, _lastFinalizableRequestId, _reportTimestamp); } /// @notice Applies sanity checks to the simulated share rate for withdrawal requests finalization @@ -593,15 +592,14 @@ contract OracleReportSanityChecker is AccessControlEnumerable { if (_appearedValidators > churnLimit) revert IncorrectAppearedValidators(_appearedValidators); } - function _checkFinalizationBatches( + function _checkLastFinalizableId( LimitsList memory _limitsList, address _withdrawalQueue, - uint256[] calldata _withdrawalFinalizationBatches, + uint256 _lastFinalizableId, uint256 _reportTimestamp ) internal view { - //TODO: update sanity check (, , , uint256 requestTimestampToFinalizeUpTo, , ) = IWithdrawalQueue(_withdrawalQueue) - .getWithdrawalRequestStatus(_withdrawalFinalizationBatches[_withdrawalFinalizationBatches.length - 1]); + .getWithdrawalRequestStatus(_lastFinalizableId); if (_reportTimestamp < requestTimestampToFinalizeUpTo + _limitsList.requestTimestampMargin) revert IncorrectRequestFinalization(requestTimestampToFinalizeUpTo); } diff --git a/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol b/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol index 6526b42db..e305c6a50 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol @@ -5,6 +5,9 @@ pragma solidity 0.8.9; import { IWithdrawalQueue } from "../../oracle/AccountingOracle.sol"; contract MockWithdrawalQueueForAccountingOracle is IWithdrawalQueue { + struct OnPreRebaseCallData { + uint256 callCount; + } struct UpdateBunkerModeCallData { bool isBunkerMode; @@ -13,10 +16,15 @@ contract MockWithdrawalQueueForAccountingOracle is IWithdrawalQueue { } UpdateBunkerModeCallData public lastCall__updateBunkerMode; + OnPreRebaseCallData public lastCall__onPreRebase; function updateBunkerMode(bool isBunkerMode, uint256 prevReportTimestamp) external { lastCall__updateBunkerMode.isBunkerMode = isBunkerMode; lastCall__updateBunkerMode.prevReportTimestamp = prevReportTimestamp; ++lastCall__updateBunkerMode.callCount; } + + function onPreRebase() external { + ++lastCall__onPreRebase.callCount; + } } diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index c4f35b259..a824c32f6 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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"actualBurnerRequests","type":"uint256"}],"name":"IncorrectBurnerRequests","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_simulatedShareRate","type":"uint256"}],"name":"checkSimulatedShareRate","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_withdrawalFinalizationBatches","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"actualBurnerRequests","type":"uint256"}],"name":"IncorrectBurnerRequests","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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 7209ff13f995bfb35057f80045254235797e1ddd Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 11:47:03 +0300 Subject: [PATCH 046/236] test: fix oracle-report-sanity-checker --- test/0.8.9/oracle-report-sanity-checker.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 f9b747ac6..78436fa45 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -243,7 +243,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa const newRequestId = 2 let oldRequestCreationTimestamp, newRequestCreationTimestamp const correctWithdrawalQueueOracleReport = { - withdrawalFinalizationBatches: [oldRequestId], + lastFinalizableRequestId: oldRequestId, refReportTimestamp: -1, } @@ -251,7 +251,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa const currentBlockTimestamp = await getCurrentBlockTimestamp() correctWithdrawalQueueOracleReport.refReportTimestamp = currentBlockTimestamp oldRequestCreationTimestamp = currentBlockTimestamp - defaultLimitsList.requestTimestampMargin - correctWithdrawalQueueOracleReport.withdrawalFinalizationBatches[0] = oldRequestCreationTimestamp + correctWithdrawalQueueOracleReport.lastFinalizableRequestId = oldRequestCreationTimestamp await withdrawalQueueMock.setRequestBlockNumber(oldRequestId, oldRequestCreationTimestamp) newRequestCreationTimestamp = currentBlockTimestamp - Math.floor(defaultLimitsList.requestTimestampMargin / 2) await withdrawalQueueMock.setRequestBlockNumber(newRequestId, newRequestCreationTimestamp) @@ -262,7 +262,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa oracleReportSanityChecker.checkWithdrawalQueueOracleReport( ...Object.values({ ...correctWithdrawalQueueOracleReport, - withdrawalFinalizationBatches: [newRequestId], + lastFinalizableRequestId: newRequestId, }) ), `IncorrectRequestFinalization(${newRequestCreationTimestamp})` From afc4bfd563a71b1c5054cb8aec4b20ce5a16ad70 Mon Sep 17 00:00:00 2001 From: Artyom Veremeenko Date: Mon, 27 Feb 2023 16:02:26 +0400 Subject: [PATCH 047/236] refactor: remove needless grantRole calls in exit bus initialize() --- .../0.8.9/oracle/ValidatorsExitBusOracle.sol | 4 ---- lib/abi/ValidatorsExitBusOracle.json | 2 +- ...ors-exit-bus-oracle-access-control.test.js | 4 +--- .../validators-exit-bus-oracle-deploy.test.js | 20 ++++--------------- 4 files changed, 6 insertions(+), 24 deletions(-) diff --git a/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol b/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol index dd5abea1a..585e1323d 100644 --- a/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol +++ b/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol @@ -98,16 +98,12 @@ contract ValidatorsExitBusOracle is BaseOracle, PausableUntil { function initialize( address admin, - address pauser, - address resumer, address consensusContract, uint256 consensusVersion, uint256 lastProcessingRefSlot ) external { if (admin == address(0)) revert AdminCannotBeZero(); _setupRole(DEFAULT_ADMIN_ROLE, admin); - if (pauser != address(0)) _grantRole(PAUSE_ROLE, pauser); - if (resumer != address(0)) _grantRole(RESUME_ROLE, resumer); _pause(PAUSE_INFINITELY); _initialize(consensusContract, consensusVersion, lastProcessingRefSlot); diff --git a/lib/abi/ValidatorsExitBusOracle.json b/lib/abi/ValidatorsExitBusOracle.json index d8dfe9d41..2b226780f 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":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":[],"name":"getResumeSinceTimestamp","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":"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":"pauser","type":"address"},{"internalType":"address","name":"resumer","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":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":[],"name":"getResumeSinceTimestamp","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":"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-access-control.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js index dca98c7f8..cc0acfe26 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js @@ -92,10 +92,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, account1 }) it('should revert without admin address', async () => { - const pauser = ZERO_ADDRESS - const resumer = ZERO_ADDRESS await assert.reverts( - oracle.initialize(ZERO_ADDRESS, pauser, resumer, consensus.address, CONSENSUS_VERSION, 0, { + oracle.initialize(ZERO_ADDRESS, consensus.address, CONSENSUS_VERSION, 0, { from: admin, }), 'AdminCannotBeZero()' 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 69066b197..3cab5a7a7 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 @@ -100,13 +100,7 @@ async function deployOracleReportSanityCheckerForExitBus(lidoLocator, admin) { async function deployExitBusOracle( admin, - { - dataSubmitter = null, - lastProcessingRefSlot = 0, - resumeAfterDeploy = false, - pauser = ZERO_ADDRESS, - resumer = ZERO_ADDRESS, - } = {} + { dataSubmitter = null, lastProcessingRefSlot = 0, resumeAfterDeploy = false } = {} ) { const locator = (await deployLocatorWithDummyAddressesImplementation(admin)).address @@ -123,15 +117,9 @@ async function deployExitBusOracle( oracleReportSanityChecker: oracleReportSanityChecker.address, }) - const initTx = await oracle.initialize( - admin, - pauser, - resumer, - consensus.address, - CONSENSUS_VERSION, - lastProcessingRefSlot, - { from: admin } - ) + const initTx = await oracle.initialize(admin, consensus.address, CONSENSUS_VERSION, lastProcessingRefSlot, { + from: admin, + }) assert.emits(initTx, 'ContractVersionSet', { version: 1 }) From cf7205962bbd17b46604b8e7499dd5dd02f2a30b Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Mon, 27 Feb 2023 19:23:43 +0700 Subject: [PATCH 048/236] feat: add mintSteth to mock --- contracts/0.4.24/test_helpers/StETHMock.sol | 6 +++ test/0.8.9/withdrawal-queue.test.js | 45 ++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/contracts/0.4.24/test_helpers/StETHMock.sol b/contracts/0.4.24/test_helpers/StETHMock.sol index 612166c60..de24a2676 100644 --- a/contracts/0.4.24/test_helpers/StETHMock.sol +++ b/contracts/0.4.24/test_helpers/StETHMock.sol @@ -38,6 +38,12 @@ contract StETHMock is StETH { _emitTransferAfterMintingShares(_to, _sharesAmount); } + function mintSteth(address _to) public payable { + uint256 sharesAmount = getSharesByPooledEth(msg.value); + mintShares(_to, sharesAmount); + setTotalPooledEther(_getTotalPooledEther().add(msg.value)); + } + function burnShares(address _account, uint256 _sharesAmount) public returns (uint256 newTotalShares) { return _burnShares(_account, _sharesAmount); } diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index f8b3c12f8..2cd29dcf8 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -27,7 +27,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, withdrawalQueue = deployed.withdrawalQueue await steth.setTotalPooledEther(ETH(600)) - // we need 1 ETH additionally to pay gas on finalization because coverage ingnores gasPrice=0 + // we need 1 ETH additionally to pay gas on finalization because coverage ignores gasPrice=0 await setBalance(steth.address, ETH(600 + 1)) await steth.mintShares(user, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) @@ -681,6 +681,49 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) + context('claim fuzzing', () => { + const fuzzClaim = async (perRequestWEI, requestCount, finalizedWEI) => { + await withdrawalQueue.requestWithdrawals(Array(requestCount).fill(perRequestWEI), user, { from: user }) + const requestIds = await withdrawalQueue.getWithdrawalRequests(user, { from: user }) + + const id = await withdrawalQueue.getLastRequestId() + await withdrawalQueue.finalize(id, { from: steth.address, value: finalizedWEI }) + + const hints = await withdrawalQueue.findCheckpointHintsUnbounded(requestIds) + const claimableEth = await withdrawalQueue.getClaimableEther(requestIds, hints) + const totalClaimable = claimableEth.reduce((s, i) => s.iadd(i) && s, bn(0)) + assert.equals(totalClaimable, finalizedWEI, `Total Claimable doesn't add up to finalized amount`) + + const balanceBefore = bn(await ethers.provider.getBalance(user)) + await withdrawalQueue.claimWithdrawals(requestIds, hints, { from: user }) + const balanceAfter = bn(await ethers.provider.getBalance(user)) + assert.equals(balanceBefore.addn(finalizedWEI), balanceAfter, `Total Claimed doesn't add up to finalized amount`) + } + + it('distribute&claim 10wei per 100*100WEI requests ', async () => { + await fuzzClaim(100, 100, 1000) + }) + + it('distribute&claim 1wei per 100*100WEI requests', async () => { + await fuzzClaim(100, 100, 100) + }) + + it('distribute&claim 1 wei per 10*MAX_STETH_WITHDRAWAL_AMOUNT requests', async () => { + const MAX_STETH_WITHDRAWAL_AMOUNT = await withdrawalQueue.MAX_STETH_WITHDRAWAL_AMOUNT() + // account for stEth~ { + await fuzzClaim(100, 100, 10) + }) + }) + context('findLastFinalizableRequestIdByTimestamp()', async () => { const numOfRequests = 10 From b9f75911cb2e9fb79c551f0911df75ae70c28de5 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 27 Feb 2023 14:27:04 +0200 Subject: [PATCH 049/236] feat: check batch extrema and boundaries --- contracts/0.8.9/WithdrawalQueueBase.sol | 37 ++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index ba4c37ce8..2a8ba7543 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -287,7 +287,7 @@ abstract contract WithdrawalQueueBase { returns (uint256 ethToLock, uint256 sharesToBurn) { if (_maxShareRate == 0) revert ZeroShareRate(); - _checkFinalizationBatchesIntegrity(_batches); + _checkFinalizationBatchesIntegrity(_batches, _maxShareRate); uint256 preBatchStartId = getLastFinalizedRequestId(); uint256 batchIndex; @@ -313,7 +313,7 @@ abstract contract WithdrawalQueueBase { } while (batchIndex < _batches.length); } - function _checkFinalizationBatchesIntegrity(uint256[] memory _batches) internal view { + function _checkFinalizationBatchesIntegrity(uint256[] memory _batches, uint256 _maxShareRate) internal view { if (_batches.length == 0) revert EmptyBatches(); uint256 lastIdInBatch = _batches[_batches.length - 1]; @@ -327,6 +327,15 @@ abstract contract WithdrawalQueueBase { uint256 index = _batches.length - 1; uint256 currentExtrema = _getExtrema().length - 1; + uint256 batchShareRate; + if (index > 0) { + (batchShareRate,) = _calcShareRateAndEth( + _getQueue()[_batches[index - 1]], + _getQueue()[_batches[index]], + SHARE_RATE_UNLIMITED + ); + } + uint256 extremaCounter = 0; while (index > 0) { @@ -338,13 +347,33 @@ abstract contract WithdrawalQueueBase { // we are skipping extrema that are x-points in the same time // and skipping extrema that are greater than the rightmost batchId ++extremaCounter; - // TODO: check that extremum is above or below the line + + uint256 extremumShareRate = _calcShareRate(extremumId); + if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); + if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); } } else { if (extremaCounter % 2 == 0) revert InvalidBatches(); extremaCounter = 0; - // TODO: check that batch[index] is really crossing point --index; + if (index > 0) { + (uint256 nextBatchShareRate,) = _calcShareRateAndEth( + _getQueue()[_batches[index - 1]], + _getQueue()[_batches[index]], + SHARE_RATE_UNLIMITED + ); + if (batchShareRate <= _maxShareRate && nextBatchShareRate <= _maxShareRate) revert InvalidBatches(); + + // touching from above is valid, though. + // | • • + // |---*---- maxShareRate + // +--------> + if (_calcShareRate(_batches[index]) != _maxShareRate) { + if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) revert InvalidBatches(); + } + + batchShareRate = nextBatchShareRate; + } } } } From d7eccd5dd07362d08d9d196a7017883f7c0c8478 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 27 Feb 2023 14:40:22 +0200 Subject: [PATCH 050/236] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F:=20optimize=20WQ?= =?UTF-8?q?=20contract=20size=20-=20remove=20roles=20from=20initializer=20?= =?UTF-8?q?-=20remove=20wsteth=20related=20methods=20-=20remove=20findChec?= =?UTF-8?q?kpointHintsUnbounded?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueue.sol | 98 +++------------------- contracts/0.8.9/WithdrawalQueueERC721.sol | 6 +- lib/abi/IWstETH.json | 1 - lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- test/0.8.9/withdrawal-queue-deploy.test.js | 5 +- test/0.8.9/withdrawal-request-nft.test.js | 4 +- test/helpers/factories.js | 4 +- test/helpers/withdrawals.js | 4 +- test/scenario/helpers/deploy.js | 4 +- 10 files changed, 22 insertions(+), 108 deletions(-) delete mode 100644 lib/abi/IWstETH.json diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 236bc2fb3..0a23f8386 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -21,14 +21,6 @@ interface IStETH is IERC20, IERC20Permit { function getSharesByPooledEth(uint256 _pooledEthAmount) external view returns (uint256); } -/// @notice Interface defining a Lido liquid staking pool wrapper -/// @dev see WstETH.sol for full docs -interface IWstETH is IERC20, IERC20Permit { - function unwrap(uint256 _wstETHAmount) external returns (uint256); - function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); - function stETH() external view returns (IStETH); -} - /// @title A contract for handling stETH withdrawal request queue within the Lido protocol /// @author folkyatina abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, WithdrawalQueueBase, Versioned { @@ -57,12 +49,10 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit uint256 public constant MAX_STETH_WITHDRAWAL_AMOUNT = 1000 * 1e18; /// @notice Lido stETH token address to be set upon construction - IStETH public immutable STETH; - /// @notice Lido wstETH token address to be set upon construction - IWstETH public immutable WSTETH; + IStETH internal immutable STETH; /// @notice Emitted when the contract initialized - event InitializedV1(address _admin, address _pauser, address _resumer, address _finalizer, address _bunkerReporter); + event InitializedV1(address _admin); event BunkerModeEnabled(uint256 _sinceTimestamp); event BunkerModeDisabled(); @@ -73,28 +63,23 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit error RequestIdsNotSorted(); error ZeroRecipient(); - /// @param _wstETH address of WstETH contract - constructor(IWstETH _wstETH) { + /// @param _stETH address of stETH contract + constructor(address _stETH) { // init immutables - WSTETH = _wstETH; - STETH = WSTETH.stETH(); + STETH = IStETH(_stETH); } /// @notice Initialize the contract storage explicitly. /// @param _admin admin address that can change every role. - /// @param _pauser address that will be able to pause the withdrawals - /// @param _resumer address that will be able to resume the withdrawals after pause - /// @param _finalizer address that can finalize requests in the queue - /// @param _bunkerReporter address that can report a bunker mode /// @dev Reverts if `_admin` equals to `address(0)` /// @dev NB! It's initialized in paused state by default and should be resumed explicitly to start /// @dev NB! Bunker mode is disabled by default - function initialize(address _admin, address _pauser, address _resumer, address _finalizer, address _bunkerReporter) + function initialize(address _admin) external { if (_admin == address(0)) revert AdminZeroAddress(); - _initialize(_admin, _pauser, _resumer, _finalizer, _bunkerReporter); + _initialize(_admin); } /// @notice Resume withdrawal requests placement and finalization @@ -130,24 +115,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } } - /// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data - /// @param amounts an array of stETH amount values. The standalone withdrawal request will - /// be created for each item in the passed list. - /// @param _owner address that will be able to transfer or claim the request. - /// If `owner` is set to `address(0)`, `msg.sender` will be used as owner. - /// @return requestIds an array of the created withdrawal requests - function requestWithdrawalsWstETH(uint256[] calldata amounts, address _owner) - public - returns (uint256[] memory requestIds) - { - _checkResumed(); - if (_owner == address(0)) _owner = msg.sender; - requestIds = new uint256[](amounts.length); - for (uint256 i = 0; i < amounts.length; ++i) { - requestIds[i] = _requestWithdrawalWstETH(amounts[i], _owner); - } - } - struct PermitInput { uint256 value; uint256 deadline; @@ -172,23 +139,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit return requestWithdrawals(_amounts, _owner); } - /// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data - /// using EIP-2612 Permit - /// @param _amounts an array of stETH amount values. The standalone withdrawal request will - /// be created for each item in the passed list. - /// @param _owner address that will be able to transfer or claim the request. - /// If `owner` is set to `address(0)`, `msg.sender` will be used as owner. - /// @param _permit data required for the wstETH.permit() method to set the allowance - /// @return requestIds an array of the created withdrawal requests - function requestWithdrawalsWstETHWithPermit( - uint256[] calldata _amounts, - address _owner, - PermitInput calldata _permit - ) external returns (uint256[] memory requestIds) { - WSTETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s); - return requestWithdrawalsWstETH(_amounts, _owner); - } - /// @notice Returns all withdrawal requests that belongs to the `_owner` address /// /// WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed @@ -282,7 +232,7 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @param _lastIndex right boundary of the search range /// @return hintIds the hints for `claimWithdrawal` to find the checkpoint for the passed request ids function findCheckpointHints(uint256[] calldata _requestIds, uint256 _firstIndex, uint256 _lastIndex) - public + external view returns (uint256[] memory hintIds) { @@ -296,18 +246,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } } - /// @notice Finds the list of hints for the given `_requestIds` searching among the checkpoints with indices - /// in the range `[1, lastCheckpointIndex]`. NB! Array of request ids should be sorted - /// @dev WARNING! OOG is possible if used onchain. - /// @param _requestIds ids of the requests sorted in the ascending order to get hints for - function findCheckpointHintsUnbounded(uint256[] calldata _requestIds) - public - view - returns (uint256[] memory hintIds) - { - return findCheckpointHints(_requestIds, 1, getLastCheckpointIndex()); - } - /// @notice Finalize requests from last finalized one up to `_lastRequestIdToFinalize` /// @dev ether to finalize all the requests should be calculated using `finalizationValue()` and sent along function finalize(uint256[] calldata _batches, uint256 _maxShareRate) @@ -361,7 +299,7 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit function _emitTransfer(address from, address to, uint256 _requestId) internal virtual; /// @dev internal initialization helper. Doesn't check provided addresses intentionally - function _initialize(address _admin, address _pauser, address _resumer, address _finalizer, address _bunkerReporter) + function _initialize(address _admin) internal { _initializeQueue(); @@ -370,14 +308,10 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit _initializeContractVersionTo(1); _grantRole(DEFAULT_ADMIN_ROLE, _admin); - if (_pauser != address(0)) _grantRole(PAUSE_ROLE, _pauser); - if (_resumer != address(0)) _grantRole(RESUME_ROLE, _resumer); - if (_finalizer != address(0)) _grantRole(FINALIZE_ROLE, _finalizer); - if (_bunkerReporter != address(0)) _grantRole(BUNKER_MODE_REPORT_ROLE, _bunkerReporter); BUNKER_MODE_SINCE_TIMESTAMP_POSITION.setStorageUint256(BUNKER_MODE_DISABLED_TIMESTAMP); - emit InitializedV1(_admin, _pauser, _resumer, _finalizer, _bunkerReporter); + emit InitializedV1(_admin); } function _requestWithdrawal(uint256 _amountOfStETH, address _owner) internal returns (uint256 requestId) { @@ -390,18 +324,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit _emitTransfer(address(0), _owner, requestId); } - function _requestWithdrawalWstETH(uint256 _amountOfWstETH, address _owner) internal returns (uint256 requestId) { - WSTETH.transferFrom(msg.sender, address(this), _amountOfWstETH); - uint256 amountOfStETH = WSTETH.unwrap(_amountOfWstETH); - _checkWithdrawalRequestAmount(amountOfStETH); - - uint256 amountOfShares = STETH.getSharesByPooledEth(amountOfStETH); - - requestId = _enqueue(uint128(amountOfStETH), uint128(amountOfShares), _owner); - - _emitTransfer(address(0), _owner, requestId); - } - function _checkWithdrawalRequestAmount(uint256 _amountOfStETH) internal pure { if (_amountOfStETH < MIN_STETH_WITHDRAWAL_AMOUNT) { revert RequestAmountTooSmall(_amountOfStETH); diff --git a/contracts/0.8.9/WithdrawalQueueERC721.sol b/contracts/0.8.9/WithdrawalQueueERC721.sol index e22d8201f..d15150c39 100644 --- a/contracts/0.8.9/WithdrawalQueueERC721.sol +++ b/contracts/0.8.9/WithdrawalQueueERC721.sol @@ -13,7 +13,7 @@ import {EnumerableSet} from "@openzeppelin/contracts-v4.4/utils/structs/Enumerab import {Address} from "@openzeppelin/contracts-v4.4/utils/Address.sol"; import {Strings} from "@openzeppelin/contracts-v4.4/utils/Strings.sol"; -import {IWstETH, WithdrawalQueue} from "./WithdrawalQueue.sol"; +import {WithdrawalQueue} from "./WithdrawalQueue.sol"; import {AccessControlEnumerable} from "./utils/access/AccessControlEnumerable.sol"; import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; @@ -73,10 +73,10 @@ contract WithdrawalQueueERC721 is IERC721Metadata, WithdrawalQueue { bytes32 private immutable NAME; bytes32 private immutable SYMBOL; - /// @param _wstETH address of WstETH contract + /// @param _stETH address of WstETH contract /// @param _name IERC721Metadata name string. Should be shorter than 32 bytes /// @param _symbol IERC721Metadata symbol string. Should be shorter than 32 bytes - constructor(address _wstETH, string memory _name, string memory _symbol) WithdrawalQueue(IWstETH(_wstETH)) { + constructor(address _stETH, string memory _name, string memory _symbol) WithdrawalQueue(_stETH) { if (bytes(_name).length == 0 || bytes(_symbol).length == 0) revert ZeroMetadata(); NAME = _toBytes32(_name); SYMBOL = _toBytes32(_symbol); diff --git a/lib/abi/IWstETH.json b/lib/abi/IWstETH.json deleted file mode 100644 index b034090cf..000000000 --- a/lib/abi/IWstETH.json +++ /dev/null @@ -1 +0,0 @@ -[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"getStETHByWstETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"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"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"unwrap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index d4500f14b..ef751ccb8 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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":"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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 8a9fd7ba9..73c01e4a1 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 9bebf602f..194aa7349 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -6,7 +6,6 @@ const withdrawals = require('../helpers/withdrawals') const { assert } = require('../helpers/assert') const StETHMock = artifacts.require('StETHPermitMock.sol') -const WstETH = artifacts.require('WstETHMock.sol') const EIP712StETH = artifacts.require('EIP712StETH') async function deployWithdrawalQueue({ @@ -21,11 +20,10 @@ async function deployWithdrawalQueue({ doResume = true, }) { const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) - const wsteth = await WstETH.new(steth.address, { from: stethOwner }) const eip712StETH = await EIP712StETH.new(steth.address, { from: stethOwner }) await steth.initializeEIP712StETH(eip712StETH.address) - const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, wsteth.address, queueName, symbol) + const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, steth.address, queueName, symbol) const initTx = await withdrawalQueue.initialize( queueAdmin, @@ -42,7 +40,6 @@ async function deployWithdrawalQueue({ return { initTx, steth, - wsteth, withdrawalQueue, } } diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index c452071cb..e84a2ad8e 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -7,7 +7,6 @@ const { shares, ETH, shareRate } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') const StETH = artifacts.require('StETHMock') -const WstETH = artifacts.require('WstETHMock') const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock') contract('WithdrawalNFT', (addresses) => { @@ -20,9 +19,8 @@ contract('WithdrawalNFT', (addresses) => { stETH = await StETH.new({ value: ETH(1), from: deployer }) await setBalance(stETH.address, ETH(100)) - wstETH = await WstETH.new(stETH.address, { from: deployer }) erc721ReceiverMock = await ERC721ReceiverMock.new({ from: deployer }) - withdrawalQueueERC721 = (await withdrawals.deploy(deployer, wstETH.address, 'Lido TEST Request', 'unstEsT')).queue + withdrawalQueueERC721 = (await withdrawals.deploy(deployer, stETH.address, 'Lido TEST Request', 'unstEsT')).queue await withdrawalQueueERC721.initialize( deployer, // owner deployer, // pauser diff --git a/test/helpers/factories.js b/test/helpers/factories.js index c93c7d2ca..e9ce4e2ca 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -257,8 +257,8 @@ async function elRewardsVaultFactory({ pool, treasury }) { return await LidoExecutionLayerRewardsVault.new(pool.address, treasury.address) } -async function withdrawalQueueFactory({ appManager, oracle, wsteth }) { - const withdrawalQueue = (await withdrawals.deploy(appManager.address, wsteth.address)).queue +async function withdrawalQueueFactory({ appManager, oracle, pool }) { + const withdrawalQueue = (await withdrawals.deploy(appManager.address, pool.address)).queue await withdrawalQueue.initialize( appManager.address, diff --git a/test/helpers/withdrawals.js b/test/helpers/withdrawals.js index 0413bd2f5..1c4bc53bf 100644 --- a/test/helpers/withdrawals.js +++ b/test/helpers/withdrawals.js @@ -3,8 +3,8 @@ const { artifacts } = require('hardhat') const OssifiableProxy = artifacts.require('OssifiableProxy.sol') const WithdrawalQueueERC721 = artifacts.require('WithdrawalQueueERC721Mock.sol') -async function deploy(ownerAddress, wstethAddress, name = 'Lido: Withdrawal Request NFT', symbol = 'unstETH') { - const impl = await WithdrawalQueueERC721.new(wstethAddress, name, symbol) +async function deploy(ownerAddress, stethAddress, name = 'Lido: Withdrawal Request NFT', symbol = 'unstETH') { + const impl = await WithdrawalQueueERC721.new(stethAddress, name, symbol) const proxy = await OssifiableProxy.new(impl.address, ownerAddress, '0x') const queue = await WithdrawalQueueERC721.at(proxy.address) diff --git a/test/scenario/helpers/deploy.js b/test/scenario/helpers/deploy.js index 633bd0c27..52a9bb416 100644 --- a/test/scenario/helpers/deploy.js +++ b/test/scenario/helpers/deploy.js @@ -4,7 +4,6 @@ const withdrawals = require('../../helpers/withdrawals') const { newDao, newApp } = require('../../0.4.24/helpers/dao') const Lido = artifacts.require('LidoMock.sol') -const WstETH = artifacts.require('WstETH.sol') const LidoELRewardsVault = artifacts.require('LidoExecutionLayerRewardsVault.sol') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') const OracleMock = artifacts.require('AccountingOracleMock.sol') @@ -132,8 +131,7 @@ async function deployDaoAndPool(appManager, voting) { const eip712StETH = await EIP712StETH.new({ from: appManager }) - const wsteth = await WstETH.new(pool.address) - const withdrawalQueue = (await withdrawals.deploy(appManager, wsteth.address)).queue + const withdrawalQueue = (await withdrawals.deploy(appManager, pool.address)).queue await pool.initialize( oracleMock.address, From 8b1aaf207eba21189b2761db53f089b065f8f0b6 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Mon, 27 Feb 2023 22:54:46 +0700 Subject: [PATCH 051/236] fix: assert for AC revert --- test/0.8.9/withdrawal-queue.test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 2cd29dcf8..82bda3c98 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -314,10 +314,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('Finalizer can finalize a request', async () => { - await assert.reverts( - withdrawalQueue.finalize(1, { from: stranger }), - `AccessControl: account ${stranger.toLowerCase()} is missing role ${await withdrawalQueue.FINALIZE_ROLE()}` - ) + await assert.revertsOZAccessControl(withdrawalQueue.finalize(1, { from: stranger }), stranger, 'FINALIZE_ROLE') await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), amount) From bfe3a48580057c1302cecf0b7b19db9ac2ec0c0d Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Mon, 27 Feb 2023 17:56:24 +0200 Subject: [PATCH 052/236] tests: fix WQ scenario test setup broken by the latest changes --- test/helpers/factories.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index e9ce4e2ca..8e10f9e3c 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -260,17 +260,18 @@ async function elRewardsVaultFactory({ pool, treasury }) { async function withdrawalQueueFactory({ appManager, oracle, pool }) { const withdrawalQueue = (await withdrawals.deploy(appManager.address, pool.address)).queue - await withdrawalQueue.initialize( - appManager.address, - appManager.address, - appManager.address, - appManager.address, - appManager.address - ) + await withdrawalQueue.initialize(appManager.address) const BUNKER_MODE_REPORT_ROLE = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() await withdrawalQueue.grantRole(BUNKER_MODE_REPORT_ROLE, oracle.address, { from: appManager.address }) + await grantRoles({ + by: appManager.address, + on: withdrawalQueue, + to: appManager.address, + roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'BUNKER_MODE_REPORT_ROLE'] + }) + return withdrawalQueue } @@ -360,6 +361,12 @@ async function postSetup({ await pool.resumeProtocolAndStaking({ from: voting.address }) } +async function grantRoles({by, on, to, roles}) { + await Promise.all(roles.map(async (role) => { + await on.grantRole(await on[role](), to, { from: by }) + })) +} + module.exports = { appManagerFactory, treasuryFactory, @@ -389,4 +396,5 @@ module.exports = { oracleReportSanityCheckerFactory, validatorExitBusFactory, oracleReportSanityCheckerStubFactory, + grantRoles, } From 08aa338bbae566bb68bd017fe24f46d0730a8d8b Mon Sep 17 00:00:00 2001 From: KRogLA Date: Tue, 28 Feb 2023 10:24:37 +0100 Subject: [PATCH 053/236] fix: set target limit role --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index b1c8b4eaf..0a7b9d08c 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -592,7 +592,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @param _isTargetLimitActive active flag function updateTargetValidatorsLimits(uint256 _nodeOperatorId, bool _isTargetLimitActive, uint64 _targetLimit) external { _onlyExistedNodeOperator(_nodeOperatorId); - _auth(STAKING_ROUTER_ROLE); + _auth(MANAGE_NODE_OPERATOR_ROLE); Packed64x4.Packed memory operatorTargetStats = _loadOperatorTargetValidatorsStats(_nodeOperatorId); operatorTargetStats.set(IS_TARGET_LIMIT_ACTIVE_OFFSET, _isTargetLimitActive ? 1 : 0); From 8bfb8edcd43f959610a6060a94f0a53a0460073a Mon Sep 17 00:00:00 2001 From: KRogLA Date: Tue, 28 Feb 2023 10:47:48 +0100 Subject: [PATCH 054/236] fix: allow zero deposits --- contracts/0.4.24/Lido.sol | 22 ++++++++------- contracts/0.8.9/StakingRouter.sol | 47 ++++++++++++++++--------------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 47061b896..8dd93abd4 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -705,17 +705,19 @@ contract Lido is Versioned, StETHPermit, AragonApp { _maxDepositsCount, stakingRouter.getStakingModuleMaxDepositsCount(_stakingModuleId, getDepositableEther()) ); - if (depositsCount == 0) return; - uint256 depositsValue = depositsCount.mul(DEPOSIT_SIZE); - /// @dev firstly update the local state of the contract to prevent a reentrancy attack, - /// even if the StakingRouter is a trusted contract. - BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().sub(depositsValue)); - emit Unbuffered(depositsValue); - - uint256 newDepositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(depositsCount); - DEPOSITED_VALIDATORS_POSITION.setStorageUint256(newDepositedValidators); - emit DepositedValidatorsChanged(newDepositedValidators); + uint256 depositsValue; + if (depositsCount > 0) { + depositsValue = depositsCount.mul(DEPOSIT_SIZE); + /// @dev firstly update the local state of the contract to prevent a reentrancy attack, + /// even if the StakingRouter is a trusted contract. + BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().sub(depositsValue)); + emit Unbuffered(depositsValue); + + uint256 newDepositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(depositsCount); + DEPOSITED_VALIDATORS_POSITION.setStorageUint256(newDepositedValidators); + emit DepositedValidatorsChanged(newDepositedValidators); + } /// @dev transfer ether to StakingRouter and make a deposit at the same time. All the ether /// sent to StakingRouter is counted as deposited. If StakingRouter can't deposit all diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index e35d8c831..ef3a3bcb1 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -964,34 +964,37 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version ) external payable validStakingModuleId(_stakingModuleId) { if (msg.sender != LIDO_POSITION.getStorageAddress()) revert AppAuthLidoFailed(); + StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); uint256 depositsValue = msg.value; - if (depositsValue == 0 || depositsValue != _depositsCount * DEPOSIT_SIZE) { - revert InvalidDepositsValue(depositsValue); - } - bytes32 withdrawalCredentials = getWithdrawalCredentials(); - if (withdrawalCredentials == 0) revert EmptyWithdrawalsCredentials(); + if (depositsValue > 0) { + if (depositsValue != _depositsCount * DEPOSIT_SIZE) { + revert InvalidDepositsValue(depositsValue); + } - StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); - if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) { - revert StakingModuleNotActive(); - } + bytes32 withdrawalCredentials = getWithdrawalCredentials(); + if (withdrawalCredentials == 0) revert EmptyWithdrawalsCredentials(); - (bytes memory publicKeysBatch, bytes memory signaturesBatch) = - IStakingModule(stakingModule.stakingModuleAddress) - .obtainDepositData(_depositsCount, _depositCalldata); + if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) { + revert StakingModuleNotActive(); + } - uint256 etherBalanceBeforeDeposits = address(this).balance; - _makeBeaconChainDeposits32ETH( - _depositsCount, - abi.encodePacked(withdrawalCredentials), - publicKeysBatch, - signaturesBatch - ); - uint256 etherBalanceAfterDeposits = address(this).balance; + (bytes memory publicKeysBatch, bytes memory signaturesBatch) = + IStakingModule(stakingModule.stakingModuleAddress) + .obtainDepositData(_depositsCount, _depositCalldata); - /// @dev all sent ETH must be deposited and self balance stay the same - assert(etherBalanceBeforeDeposits - etherBalanceAfterDeposits == depositsValue); + uint256 etherBalanceBeforeDeposits = address(this).balance; + _makeBeaconChainDeposits32ETH( + _depositsCount, + abi.encodePacked(withdrawalCredentials), + publicKeysBatch, + signaturesBatch + ); + uint256 etherBalanceAfterDeposits = address(this).balance; + + /// @dev all sent ETH must be deposited and self balance stay the same + assert(etherBalanceBeforeDeposits - etherBalanceAfterDeposits == depositsValue); + } stakingModule.lastDepositAt = uint64(block.timestamp); stakingModule.lastDepositBlock = block.number; From 6b4dde20b07d9f56bfee003f36d6bd45000a760c Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 13:21:17 +0200 Subject: [PATCH 055/236] feat: limit extrema loop with cached prev checked index --- contracts/0.8.9/WithdrawalQueueBase.sol | 194 +++++++++++++----------- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 4 files changed, 110 insertions(+), 90 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 2a8ba7543..3a2410383 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -22,7 +22,7 @@ abstract contract WithdrawalQueueBase { /// @notice precision base for share rate and discounting factor values in the contract uint256 internal constant E27_PRECISION_BASE = 1e27; - uint256 internal constant MAX_REBASE_NUMBER = 36; + uint256 internal constant MAX_EXTREMA_PER_CALL = 36; uint256 internal constant MAX_REQUESTS_PER_CALL = 1000; uint256 internal constant SHARE_RATE_UNLIMITED = type(uint256).max; @@ -46,7 +46,9 @@ abstract contract WithdrawalQueueBase { /// withdrawal requests mapped to the owners bytes32 internal constant REQUEST_BY_OWNER_POSITION = keccak256("lido.WithdrawalQueue.requestsByOwner"); /// list of extremum requests for shareRate(request_id) function - bytes32 internal constant EXTREMA_POSITION = keccak256("lido.WithdrawalQueue.extremumRequestId"); + bytes32 internal constant EXTREMA_POSITION = keccak256("lido.WithdrawalQueue.extrema"); + /// last extreum index that was already checked for finalization + bytes32 internal constant LAST_CHECKED_EXTREMUM_POSITION = keccak256("lido.WithdrawalQueue.lastCheckedExtremum"); /// @notice structure representing a request for withdrawal. struct WithdrawalRequest { @@ -60,6 +62,8 @@ abstract contract WithdrawalQueueBase { uint64 timestamp; /// @notice flag if the request was claimed bool claimed; + + //reportTimestamp; } /// @notice structure to store discounts for requests that are affected by negative rebase @@ -163,6 +167,8 @@ abstract contract WithdrawalQueueBase { uint256[] batches; } + // TODO: 1-2 wei corner case use rebaseTimestamp + // TODO: [10, 10] batches (when last id is also a crossing point) function calculateFinalizationBatches(uint256 _maxShareRate, uint256 _maxTimestamp, CalcState memory _state) external view @@ -176,56 +182,60 @@ abstract contract WithdrawalQueueBase { if (_state.batches.length == 0) { requestId = getLastFinalizedRequestId() + 1; // we'll store batches as a array where [MAX_REBASE_NUMBER] element is the array's length - _state.batches = new uint256[](MAX_REBASE_NUMBER + 1); + _state.batches = new uint256[](MAX_EXTREMA_PER_CALL + 1); } else { requestId = _state.batches[_state.batches[0]] + 1; prevRequestShareRate = _calcShareRate(_state.batches[_state.batches[0]], _maxShareRate); } - uint256 lastRequestId = getLastRequestId(); - uint256 postFinalId = Math.min(requestId + MAX_REQUESTS_PER_CALL, lastRequestId + 1); + uint256 maxPossibleRequstId = requestId + MAX_REQUESTS_PER_CALL; - uint256 rebaseCounter; + uint256 extremaCounter; - while (requestId < postFinalId) { + while (requestId < maxPossibleRequstId) { + if (requestId > lastRequestId) break; // if end of the queue WithdrawalRequest memory request = _getQueue()[requestId]; if (request.timestamp > _maxTimestamp) break; WithdrawalRequest memory prevRequest = _getQueue()[requestId - 1]; - (uint256 requestShareRate, uint256 etherRequested) = - _calcShareRateAndEth(prevRequest, request, _maxShareRate); + uint256 requestShareRate = _calcShareRate(prevRequest, request, _maxShareRate); + uint256 etherRequested = request.cumulativeStETH - prevRequest.cumulativeStETH; + if (etherRequested > _state.ethBudget) break; _state.ethBudget -= etherRequested; if (prevRequestShareRate != requestShareRate) { - ++rebaseCounter; + ++extremaCounter; // finalization batch is 36 days max - if (rebaseCounter > MAX_REBASE_NUMBER) break; + // todo: extrema counts + if (extremaCounter > MAX_EXTREMA_PER_CALL) break; } - if (_state.batches[MAX_REBASE_NUMBER] != 0 && ( + if (_state.batches[MAX_EXTREMA_PER_CALL] != 0 && ( + // todo: check if we can omit `touching from above` case prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || prevRequestShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { - _state.batches[_state.batches[MAX_REBASE_NUMBER] - 1] = requestId; + _state.batches[_state.batches[MAX_EXTREMA_PER_CALL] - 1] = requestId; } else { - _state.batches[_state.batches[MAX_REBASE_NUMBER]] = requestId; - ++_state.batches[MAX_REBASE_NUMBER]; + _state.batches[_state.batches[MAX_EXTREMA_PER_CALL]] = requestId; + ++_state.batches[MAX_EXTREMA_PER_CALL]; } prevRequestShareRate = requestShareRate; unchecked{ ++requestId; } } - _state.finished = requestId < postFinalId || requestId == lastRequestId + 1; + _state.finished = requestId < maxPossibleRequstId || requestId == lastRequestId + 1; if (_state.finished) { - assert(_state.batches[MAX_REBASE_NUMBER] <= MAX_REBASE_NUMBER); + assert(_state.batches[MAX_EXTREMA_PER_CALL] <= MAX_EXTREMA_PER_CALL); uint256[] memory batches = _state.batches; - uint256 length = _state.batches[MAX_REBASE_NUMBER]; + uint256 length = _state.batches[MAX_EXTREMA_PER_CALL]; + // todo: use MemUtils assembly { mstore(batches, length) } @@ -234,6 +244,8 @@ abstract contract WithdrawalQueueBase { return _state; } + // todo: move to finalizationValue or to requestWithdrawal + // read both request at once function onPreRebase() external { // Populate shareRate extrema list uint256 lastRequestId = getLastRequestId(); @@ -250,7 +262,7 @@ abstract contract WithdrawalQueueBase { uint256 lastRequestShareRate = _calcShareRate(lastRequestId); uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId); - if (lastRequestShareRate == lastExtremumShareRate) return; + if (lastRequestShareRate == lastExtremumShareRate) return; // todo: 1-2 wei corner case // first met request in a sequence with equal shareRate is an extremum if (extrema.length == 1) { @@ -281,13 +293,20 @@ abstract contract WithdrawalQueueBase { } } - function finalizationValue(uint256[] calldata _batches, uint256 _maxShareRate) + function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate) public - view returns (uint256 ethToLock, uint256 sharesToBurn) { if (_maxShareRate == 0) revert ZeroShareRate(); - _checkFinalizationBatchesIntegrity(_batches, _maxShareRate); + if (_batches.length == 0) revert EmptyBatches(); + + uint256 lastIdInBatch = _batches[_batches.length - 1]; + if (lastIdInBatch > getLastRequestId()) revert InvalidRequestId(lastIdInBatch); + + uint256 firstIdInBatch = _batches[0]; + if (firstIdInBatch <= getLastFinalizedRequestId()) revert InvalidRequestId(firstIdInBatch); + + _setLastCheckedExtremum(_checkFinalizationBatchesIntegrity(_batches, _maxShareRate)); uint256 preBatchStartId = getLastFinalizedRequestId(); uint256 batchIndex; @@ -300,6 +319,7 @@ abstract contract WithdrawalQueueBase { uint256 eth = batchEnd.cumulativeStETH - batchStart.cumulativeStETH; uint256 batchShareRate = (eth * E27_PRECISION_BASE) / shares; + // todo: check equality if (batchShareRate > _maxShareRate) { ethToLock += shares * _maxShareRate / E27_PRECISION_BASE; } else { @@ -313,69 +333,67 @@ abstract contract WithdrawalQueueBase { } while (batchIndex < _batches.length); } - function _checkFinalizationBatchesIntegrity(uint256[] memory _batches, uint256 _maxShareRate) internal view { - if (_batches.length == 0) revert EmptyBatches(); - - uint256 lastIdInBatch = _batches[_batches.length - 1]; - if (lastIdInBatch > getLastRequestId()) revert InvalidRequestId(lastIdInBatch); - - uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); - uint256 firstIdInBatch = _batches[0]; - if (firstIdInBatch <= lastFinalizedRequestId) revert InvalidRequestId(firstIdInBatch); + function _checkFinalizationBatchesIntegrity(uint256[] memory _batches, uint256 _maxShareRate) + internal + view + returns (uint256 lastCheckedExtremum) + { + uint256 index = 0; + uint256 batchPreStartId = getLastFinalizedRequestId(); + uint256 batchEndId = _batches[index]; - // checking that between first and pre-last x-points we have odd number of extremums - uint256 index = _batches.length - 1; - uint256 currentExtrema = _getExtrema().length - 1; + uint256 extremumIndex = _getLastCheckedExtremum(); + uint256 extremumId; uint256 batchShareRate; - if (index > 0) { - (batchShareRate,) = _calcShareRateAndEth( - _getQueue()[_batches[index - 1]], + if (index < _batches.length - 1) { + batchShareRate = _calcShareRate( _getQueue()[_batches[index]], + _getQueue()[_batches[index + 1]], SHARE_RATE_UNLIMITED ); } - uint256 extremaCounter = 0; - - while (index > 0) { - uint256 extremumId = _getExtrema()[currentExtrema]; - - if (extremumId > _batches[index - 1]) { - --currentExtrema; - if (extremumId != _batches[index - 1] && extremumId < _batches[index]) { - // we are skipping extrema that are x-points in the same time - // and skipping extrema that are greater than the rightmost batchId - ++extremaCounter; + while (index < _batches.length - 1) { + if (extremumId < _batches[batchEndId]) { + unchecked { ++extremumIndex; } + extremumId = _getExtrema()[extremumIndex]; + // check extremum + uint256 extremumShareRate = _calcShareRate(extremumId); + if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); + if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); - uint256 extremumShareRate = _calcShareRate(extremumId); - if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); - if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); - } } else { - if (extremaCounter % 2 == 0) revert InvalidBatches(); - extremaCounter = 0; - --index; - if (index > 0) { - (uint256 nextBatchShareRate,) = _calcShareRateAndEth( - _getQueue()[_batches[index - 1]], - _getQueue()[_batches[index]], - SHARE_RATE_UNLIMITED - ); - if (batchShareRate <= _maxShareRate && nextBatchShareRate <= _maxShareRate) revert InvalidBatches(); - - // touching from above is valid, though. - // | • • - // |---*---- maxShareRate - // +--------> - if (_calcShareRate(_batches[index]) != _maxShareRate) { - if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) revert InvalidBatches(); + // check crossing point + uint256 nextBatchShareRate = _calcShareRate( + _getQueue()[batchEndId], + _getQueue()[_batches[index + 1]], + SHARE_RATE_UNLIMITED + ); + // avg batch rate before crossing point and after crossing point + // can't be both below `_maxShareRate` + if (batchShareRate <= _maxShareRate && nextBatchShareRate <= _maxShareRate) revert InvalidBatches(); + + // avg batch rate before crossing point and after crossing point + // can't be both above `_maxShareRate` + // except the case when crossing point is extremum and touching `_maxShareRate` from above + // | • • + // |---*---- maxShareRate + // +--------> + if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) { + // TODO: get rid of this corner case + if (!(extremumId == batchEndId && _calcShareRate(_batches[index]) != _maxShareRate)) { + revert InvalidBatches(); } - - batchShareRate = nextBatchShareRate; } + + batchShareRate = nextBatchShareRate; + batchPreStartId = batchEndId; + unchecked { ++index; } } } + + return extremumIndex; } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` @@ -591,29 +609,23 @@ abstract contract WithdrawalQueueBase { if (!success) revert CantSendValueRecipientMayHaveReverted(); } - function _calcShareRateAndEth( - WithdrawalRequest memory _prevRequest, - WithdrawalRequest memory _lastRequest, - uint256 maxShareRate - ) internal pure returns (uint256 eth, uint256 shares) { - uint256 ethRequested = _lastRequest.cumulativeStETH - _prevRequest.cumulativeStETH; - uint256 shareRequested = _lastRequest.cumulativeShares - _prevRequest.cumulativeShares; + /// calculate avg share rate for the batch of (_preStartRequest, _endRequest] + function _calcShareRate( + WithdrawalRequest memory _preStartRequest, + WithdrawalRequest memory _endRequest, + uint256 _maxShareRate + ) internal pure returns (uint256 shareRate) { + uint256 ethRequested = _endRequest.cumulativeStETH - _preStartRequest.cumulativeStETH; + uint256 shareRequested = _endRequest.cumulativeShares - _preStartRequest.cumulativeShares; - if (ethRequested * E27_PRECISION_BASE / shareRequested <= maxShareRate) { - return (ethRequested, shareRequested); - } - - return (shareRequested * maxShareRate / E27_PRECISION_BASE, shareRequested); + return Math.min(ethRequested * E27_PRECISION_BASE / shareRequested, _maxShareRate); } function _calcShareRate(uint256 _requestId, uint256 _maxShareRate) internal view returns (uint256) { WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; WithdrawalRequest memory lastRequest = _getQueue()[_requestId]; - uint256 ethRequested = lastRequest.cumulativeStETH - prevRequest.cumulativeStETH; - uint256 shareRequested = lastRequest.cumulativeShares - prevRequest.cumulativeShares; - - return Math.min(ethRequested * E27_PRECISION_BASE / shareRequested, _maxShareRate); + return _calcShareRate(prevRequest, lastRequest, _maxShareRate); } function _calcShareRate(uint256 _requestId) internal view returns (uint256) { @@ -652,6 +664,10 @@ abstract contract WithdrawalQueueBase { return EXTREMA_POSITION.storageUint256Array(); } + function _getLastCheckedExtremum() internal view returns (uint256) { + return LAST_CHECKED_EXTREMUM_POSITION.getStorageUint256(); + } + function _setLastRequestId(uint256 _lastRequestId) internal { LAST_REQUEST_ID_POSITION.setStorageUint256(_lastRequestId); } @@ -667,4 +683,8 @@ abstract contract WithdrawalQueueBase { function _setLockedEtherAmount(uint256 _lockedEtherAmount) internal { LOCKED_ETHER_AMOUNT_POSITION.setStorageUint256(_lockedEtherAmount); } + + function _setLastCheckedExtremum(uint256 _lastCheckedExtremum) internal { + LAST_CHECKED_EXTREMUM_POSITION.setStorageUint256(_lastCheckedExtremum); + } } diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index ef751ccb8..37127a7e0 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index 742119b7e..1779db035 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":[],"name":"onPreRebase","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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 73c01e4a1..11e022394 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalizationValue","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 c2891433571a0c2c46d9dd37afb59e4b51bf5e57 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 13:21:48 +0200 Subject: [PATCH 056/236] =?UTF-8?q?=F0=9F=92=85:=20fix=20prettier=20lint?= =?UTF-8?q?=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/helpers/factories.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 8e10f9e3c..bedf0d187 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -269,7 +269,7 @@ async function withdrawalQueueFactory({ appManager, oracle, pool }) { by: appManager.address, on: withdrawalQueue, to: appManager.address, - roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'BUNKER_MODE_REPORT_ROLE'] + roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'BUNKER_MODE_REPORT_ROLE'], }) return withdrawalQueue @@ -361,10 +361,12 @@ async function postSetup({ await pool.resumeProtocolAndStaking({ from: voting.address }) } -async function grantRoles({by, on, to, roles}) { - await Promise.all(roles.map(async (role) => { - await on.grantRole(await on[role](), to, { from: by }) - })) +async function grantRoles({ by, on, to, roles }) { + await Promise.all( + roles.map(async (role) => { + await on.grantRole(await on[role](), to, { from: by }) + }) + ) } module.exports = { From 04cb1df4e771e42e309371823d9fea8a7d16d964 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 13:30:09 +0200 Subject: [PATCH 057/236] test: fix initialization tests --- test/0.8.9/withdrawal-queue-deploy.test.js | 74 ++++------------------ 1 file changed, 11 insertions(+), 63 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 194aa7349..85d4edc5f 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -25,12 +25,17 @@ async function deployWithdrawalQueue({ const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, steth.address, queueName, symbol) - const initTx = await withdrawalQueue.initialize( - queueAdmin, - queuePauser || queueAdmin, - queueResumer || queueAdmin, - queueFinalizer || steth.address, - queueBunkerReporter || steth.address + const initTx = await withdrawalQueue.initialize(queueAdmin) + + await withdrawalQueue.grantRole(await withdrawalQueue.FINALIZE_ROLE(), queueFinalizer || steth.address, { + from: queueAdmin, + }) + await withdrawalQueue.grantRole(await withdrawalQueue.PAUSE_ROLE(), queuePauser || queueAdmin, { from: queueAdmin }) + await withdrawalQueue.grantRole(await withdrawalQueue.RESUME_ROLE(), queueResumer || queueAdmin, { from: queueAdmin }) + await withdrawalQueue.grantRole( + await withdrawalQueue.BUNKER_MODE_REPORT_ROLE(), + queueBunkerReporter || steth.address, + { from: queueAdmin } ) if (doResume) { @@ -89,10 +94,6 @@ contract( }) assert.emits(initTx, 'InitializedV1', { _admin: queueAdmin, - _pauser: queuePauser, - _resumer: queueResumer, - _finalizer: queueFinalizer, - _bunkerReporter: queueBunkerReporter, }) }) @@ -137,59 +138,6 @@ contract( 'ZeroMetadata()' ) }) - - context('no roles for zero addresses', () => { - it('check if pauser is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser: ZERO_ADDRESS, - queueResumer, - }) - const role = await withdrawalQueue.PAUSE_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - - it('check if pauser is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser, - queueResumer: ZERO_ADDRESS, - doResume: false, - }) - const role = await withdrawalQueue.RESUME_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - - it('check if finalizer is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser, - queueResumer, - queueFinalizer: ZERO_ADDRESS, - }) - const role = await withdrawalQueue.FINALIZE_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - - it('check if bunker reporter is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser, - queueResumer, - queueBunkerReporter: ZERO_ADDRESS, - }) - const role = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - }) }) } ) From 8cb1d92db3b192a8d37f0b56595a8bc78ef1d532 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Tue, 28 Feb 2023 11:14:42 +0100 Subject: [PATCH 058/236] test: zero deposit works --- .../staking-router-deposits.test.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/0.8.9/staking-router/staking-router-deposits.test.js b/test/0.8.9/staking-router/staking-router-deposits.test.js index 9739aa446..c4668398b 100644 --- a/test/0.8.9/staking-router/staking-router-deposits.test.js +++ b/test/0.8.9/staking-router/staking-router-deposits.test.js @@ -226,17 +226,18 @@ contract('StakingRouter', ([depositor, stranger]) => { await operators.setNodeOperatorStakingLimit(1, 100000, { from: voting }) }) - it('deposits not work if depositValue == 0', async () => { - const depositsCount = 100 - + it('zero deposits just updates module lastDepositBlock', async () => { + const depositsCount = 1 // allow tx `StakingRouter.deposit()` from the Lido contract addr await ethers.provider.send('hardhat_impersonateAccount', [lido.address]) - const value = ETH(0) - await assert.reverts( - router.deposit(depositsCount, curatedModuleId, '0x', { from: lido.address, value }), - `InvalidDepositsValue(${value}, ${depositsCount})` - ) + const receipt = await router.deposit(depositsCount, curatedModuleId, '0x', { from: lido.address, value }) + + assert.emits(receipt, 'StakingRouterETHDeposited', { stakingModuleId: curatedModuleId, amount: value }) + + const lastModuleBlock = await router.getStakingModuleLastDepositBlock(curatedModuleId) + const currentBlockNumber = await web3.eth.getBlockNumber() + assert.equal(currentBlockNumber, +lastModuleBlock) }) it('deposits not work if depositValue != depositsCount * 32 ', async () => { From 380ce4abfde92b1c104bc7514f8043219c93b18d Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 15:16:31 +0200 Subject: [PATCH 059/236] fix: fix underflow in calculateFinalizationBatches --- contracts/0.8.9/WithdrawalQueueBase.sol | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 3a2410383..851cd4b7b 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -200,8 +200,14 @@ abstract contract WithdrawalQueueBase { WithdrawalRequest memory prevRequest = _getQueue()[requestId - 1]; - uint256 requestShareRate = _calcShareRate(prevRequest, request, _maxShareRate); uint256 etherRequested = request.cumulativeStETH - prevRequest.cumulativeStETH; + uint256 shareRequested = request.cumulativeShares - prevRequest.cumulativeShares; + uint256 requestShareRate = etherRequested * E27_PRECISION_BASE / shareRequested; + + if (requestShareRate > _maxShareRate) { + etherRequested = shareRequested * _maxShareRate / E27_PRECISION_BASE; + requestShareRate = _maxShareRate; + } if (etherRequested > _state.ethBudget) break; @@ -251,8 +257,9 @@ abstract contract WithdrawalQueueBase { uint256 lastRequestId = getLastRequestId(); uint256[] storage extrema = _getExtrema(); // first request is an extremum by default - if (extrema.length == 0 && lastRequestId > 0) { + if (extrema.length == 1 && lastRequestId > 0) { extrema.push(lastRequestId); + return; } uint256 lastExtremumId = extrema[extrema.length - 1]; @@ -265,7 +272,7 @@ abstract contract WithdrawalQueueBase { if (lastRequestShareRate == lastExtremumShareRate) return; // todo: 1-2 wei corner case // first met request in a sequence with equal shareRate is an extremum - if (extrema.length == 1) { + if (extrema.length == 2) { // first two different rates are always extrema extrema.push(lastRequestId); } else { From d3022c75ef2849fe84b7db564fef4578ca9b668c Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 15:33:10 +0200 Subject: [PATCH 060/236] test: fix share rate test --- test/0.8.9/withdrawal-queue-share-rate-changes.test.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index bc74c133f..5f9eb2794 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -75,22 +75,26 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { await setShareRate(1) }) + let batches + it(`both requests can be finalized with 2 ETH`, async () => { const result = await queue.calculateFinalizationBatches(e27(1), MAX_UINT256, [e18(2), false, []]) assert.isTrue(result.finished) - const batch = await queue.finalizationValue(result.batches, e27(1)) + const batch = await queue.prefinalize.call(result.batches, e27(1)) assert.equals(batch.ethToLock, e18(2)) assert.equals(batch.sharesToBurn, e18(2)) + + batches = result.batches }) let claimableEther it(`requests get finalized`, async () => { - await queue.finalize(requestIds[1], e27(1), { from: finalizer, value: e18(2) }) + await queue.finalize(batches, e27(1), { from: finalizer, value: e18(2) }) assert.equals(await queue.getLastFinalizedRequestId(), requestIds[1]) - const hints = await queue.findCheckpointHintsUnbounded(requestIds) + const hints = await queue.findCheckpointHints(requestIds, 1, await queue.getLastCheckpointIndex()) claimableEther = await queue.getClaimableEther(requestIds, hints) }) From 1d856f573fe1e8076e5ebbbdd1c44dbd94369471 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 15:55:43 +0200 Subject: [PATCH 061/236] test: add test 2 requests 2 batches --- ...ithdrawal-queue-share-rate-changes.test.js | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index 5f9eb2794..e48e8dc9a 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -41,7 +41,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { await snapshot() }) - context(`multiple requests with diff entry share rate`, async () => { + context(`2 requests with diff share rate, maxShareRate == shareRate(1)`, async () => { /// /// invariant 1: all requests in the same batch should be finalized using the same share rate /// @@ -106,4 +106,73 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { assert.isClose(claimableEther[1], e18(1), 10) }) }) + + context(`2 requests 2 batches, shareRate(2) > maxShareRate > shareRate(1)`, async () => { + /// + /// invariant 1: all requests in the same batch should be finalized using the same share rate + /// + /// invariant 2: a withdrawal request cannot be finalized using a lower share rate than the + /// minimum share rate that was reported by the oracle since the last oracle report before + /// the request was added to the queue + /// + after(rollback) + + const requestIds = [0, 0] + + it(`share rate 1.0: a user requests a withdrawal of 1 stETH (10**18 shares)`, async () => { + const tx = await queue.requestWithdrawals([e18(1)], user, { from: user }) + requestIds[0] = +getFirstEventArgs(tx, 'WithdrawalRequested').requestId + assert.equals(await queue.unfinalizedStETH(), e18(1)) + }) + + it(`protocol receives rewards, changing share rate to 2.0`, async () => { + await queue.onPreRebase() + await setShareRate(2) + }) + + it(`share rate 2.0: a user requests a withdrawal of 2 stETH (10**18 shares)`, async () => { + const tx = await queue.requestWithdrawals([e18(2)], user, { from: user }) + requestIds[1] = +getFirstEventArgs(tx, 'WithdrawalRequested').requestId + assert.equals(await queue.unfinalizedStETH(), e18(3)) + }) + + it(`protocol receives slashing, changing share rate to 1.0`, async () => { + await queue.onPreRebase() + await setShareRate(1) + }) + + let batches + const maxShareRate = e27(1.5) + + it(`both requests can be finalized with 2 ETH`, async () => { + const result = await queue.calculateFinalizationBatches(maxShareRate, MAX_UINT256, [e18(2.5), false, []]) + assert.isTrue(result.finished) + + console.log(result) + + const batch = await queue.prefinalize.call(result.batches, maxShareRate) + assert.equals(batch.ethToLock, e18(2.5)) + assert.equals(batch.sharesToBurn, e18(2)) + + batches = result.batches + }) + + let claimableEther + + it(`requests get finalized`, async () => { + await queue.finalize(batches, maxShareRate, { from: finalizer, value: e18(2.5) }) + assert.equals(await queue.getLastFinalizedRequestId(), requestIds[1]) + + const hints = await queue.findCheckpointHints(requestIds, 1, await queue.getLastCheckpointIndex()) + claimableEther = await queue.getClaimableEther(requestIds, hints) + }) + + it(`first request is fullfilled with 1 ETH`, async () => { + assert.isClose(claimableEther[0], e18(1), 10) + }) + + it(`second request is fullfilled with 1 ETH`, async () => { + assert.isClose(claimableEther[1], e18(1.5), 10) + }) + }) }) From 00c4da5a1b03035a01e4cab62a11a06925efd086 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 16:12:46 +0200 Subject: [PATCH 062/236] fix: fix for calculateFinalizationBatches --- contracts/0.8.9/WithdrawalQueueBase.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 851cd4b7b..9afe413a7 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -206,7 +206,6 @@ abstract contract WithdrawalQueueBase { if (requestShareRate > _maxShareRate) { etherRequested = shareRequested * _maxShareRate / E27_PRECISION_BASE; - requestShareRate = _maxShareRate; } if (etherRequested > _state.ethBudget) break; From 5a9df5ff8f746e4a450bc9d956f8ca8b06ca27c6 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 16:28:13 +0200 Subject: [PATCH 063/236] fix: fix test with two batches --- contracts/0.8.9/WithdrawalQueueBase.sol | 29 +++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 9afe413a7..4bc2e2a77 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -344,36 +344,33 @@ abstract contract WithdrawalQueueBase { view returns (uint256 lastCheckedExtremum) { - uint256 index = 0; + uint256 batchIndex = 0; uint256 batchPreStartId = getLastFinalizedRequestId(); - uint256 batchEndId = _batches[index]; + uint256 batchEndId = _batches[batchIndex]; - uint256 extremumIndex = _getLastCheckedExtremum(); + uint256 extremumIndex = _getLastCheckedExtremum() + 1; uint256 extremumId; - uint256 batchShareRate; - if (index < _batches.length - 1) { - batchShareRate = _calcShareRate( - _getQueue()[_batches[index]], - _getQueue()[_batches[index + 1]], + uint256 batchShareRate= _calcShareRate( + _getQueue()[batchPreStartId], + _getQueue()[batchEndId], SHARE_RATE_UNLIMITED ); - } - while (index < _batches.length - 1) { - if (extremumId < _batches[batchEndId]) { - unchecked { ++extremumIndex; } + while (batchIndex < _batches.length - 1) { + if (extremumId < batchEndId) { extremumId = _getExtrema()[extremumIndex]; // check extremum uint256 extremumShareRate = _calcShareRate(extremumId); + if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); - + unchecked { ++extremumIndex; } } else { // check crossing point uint256 nextBatchShareRate = _calcShareRate( _getQueue()[batchEndId], - _getQueue()[_batches[index + 1]], + _getQueue()[_batches[batchIndex + 1]], SHARE_RATE_UNLIMITED ); // avg batch rate before crossing point and after crossing point @@ -388,14 +385,14 @@ abstract contract WithdrawalQueueBase { // +--------> if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) { // TODO: get rid of this corner case - if (!(extremumId == batchEndId && _calcShareRate(_batches[index]) != _maxShareRate)) { + if (!(extremumId == batchEndId && _calcShareRate(_batches[batchIndex]) != _maxShareRate)) { revert InvalidBatches(); } } batchShareRate = nextBatchShareRate; batchPreStartId = batchEndId; - unchecked { ++index; } + unchecked { ++batchIndex; } } } From 96d356a68f6f0c05053ca2fc533aff1855193fd3 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 16:37:15 +0200 Subject: [PATCH 064/236] test: remove withdrawal tests for wsteth --- test/0.8.9/withdrawal-queue.test.js | 135 +--------------------------- 1 file changed, 3 insertions(+), 132 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index a2316d44d..83416c9de 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -3,14 +3,14 @@ const { bn, getEventArgument, ZERO_ADDRESS, ZERO_BYTES32 } = require('@aragon/co const { ETH, StETH, shareRate, shares } = require('../helpers/utils') const { assert } = require('../helpers/assert') -const { signPermit, makeDomainSeparator } = require('../0.6.12/helpers/permit_helpers') +const { signPermit } = require('../0.6.12/helpers/permit_helpers') const { MAX_UINT256, ACCOUNTS_AND_KEYS } = require('../0.6.12/helpers/constants') const { impersonate, EvmSnapshot, getCurrentBlockTimestamp, setBalance } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, bunkerReporter]) => { - let withdrawalQueue, steth, wsteth + let withdrawalQueue, steth const snapshot = new EvmSnapshot(ethers.provider) @@ -28,7 +28,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) steth = deployed.steth - wsteth = deployed.wsteth withdrawalQueue = deployed.withdrawalQueue await steth.setTotalPooledEther(ETH(600)) @@ -75,19 +74,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.pause(100000000, { from: daoAgent }) assert(await withdrawalQueue.isPaused()) await assert.reverts(withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }), 'ResumedExpected()') - await assert.reverts( - withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], owner, { from: user }), - 'ResumedExpected()' - ) const stubPermit = [0, 0, ZERO_BYTES32, ZERO_BYTES32, ZERO_BYTES32] await assert.reverts( withdrawalQueue.requestWithdrawalsWithPermit([ETH(1)], owner, stubPermit, { from: user }), 'ResumedExpected()' ) - await assert.reverts( - withdrawalQueue.requestWithdrawalsWstETHWithPermit([ETH(1)], owner, stubPermit, { from: user }), - 'ResumedExpected()' - ) await assert.reverts(withdrawalQueue.finalize(1, 0, { from: owner }), 'ResumedExpected()') }) @@ -267,10 +258,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const PAUSE_INFINITELY = await withdrawalQueue.PAUSE_INFINITELY() await withdrawalQueue.pause(PAUSE_INFINITELY, { from: daoAgent }) await assert.reverts(withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), 'ResumedExpected()') - await assert.reverts( - withdrawalQueue.requestWithdrawalsWstETH([ETH(300)], owner, { from: user }), - 'ResumedExpected()' - ) }) it('data is being accumulated properly', async () => { @@ -879,39 +866,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) - context('findCheckpointHintsUnbounded()', () => { - let requestId - const amount = ETH(20) - - beforeEach('Enqueue a request', async () => { - await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - requestId = await withdrawalQueue.getLastRequestId() - }) - - it('returns correct hints array for given request ids', async () => { - await withdrawalQueue.finalize(requestId, shareRate(20), { from: steth.address, value: ETH(20) }) - - await steth.mintShares(owner, shares(1)) - await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) - - const secondRequestAmount = ETH(10) - await withdrawalQueue.requestWithdrawals([secondRequestAmount], owner, { from: owner }) - const secondRequestId = await withdrawalQueue.getLastRequestId() - - const thirdRequestAmount = ETH(30) - await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) - const thirdRequestId = await withdrawalQueue.getLastRequestId() - - await withdrawalQueue.finalize(thirdRequestId, shareRate(20), { from: steth.address, value: ETH(40) }) - - const hints = await withdrawalQueue.findCheckpointHintsUnbounded([requestId, secondRequestId, thirdRequestId]) - assert.equal(hints.length, 3) - assert.equals(hints[0], 1) - assert.equals(hints[1], 1) - assert.equals(hints[2], 1) - }) - }) - context('claimWithdrawals()', () => { const amount = ETH(20) @@ -951,89 +905,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) - context('requestWithdrawalsWstETH()', () => { - it('works correctly with non empty payload and different tokens', async () => { - await wsteth.mint(user, ETH(100)) - await steth.mintShares(wsteth.address, shares(100)) - await steth.mintShares(user, shares(100)) - await wsteth.approve(withdrawalQueue.address, ETH(300), { from: user }) - const requests = [ETH(10), ETH(20)] - const wstETHBalanceBefore = await wsteth.balanceOf(user) - const lastRequestIdBefore = await withdrawalQueue.getLastRequestId() - - await withdrawalQueue.requestWithdrawalsWstETH(requests, stranger, { from: user }) - - assert.equals(await withdrawalQueue.getLastRequestId(), lastRequestIdBefore.add(bn(requests.length))) - const wstETHBalanceAfter = await wsteth.balanceOf(user) - assert.equals(wstETHBalanceAfter, wstETHBalanceBefore.sub(bn(requests[0])).sub(bn(requests[1]))) - }) - - it('uses sender address as owner if zero passed', async () => { - await wsteth.mint(user, ETH(1)) - await steth.mintShares(wsteth.address, shares(1)) - await steth.mintShares(user, shares(1)) - await wsteth.approve(withdrawalQueue.address, ETH(1), { from: user }) - - const tx = await withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], ZERO_ADDRESS, { from: user }) - - assert.emits(tx, 'WithdrawalRequested', { - requestId: 1, - requestor: user.toLowerCase(), - owner: user.toLowerCase(), - amountOfStETH: await steth.getPooledEthByShares(ETH(1)), - amountOfShares: shares(1), - }) - }) - }) - - context('requestWithdrawalsWstETHWithPermit()', () => { - const [alice] = ACCOUNTS_AND_KEYS - it('works correctly with non empty payload', async () => { - await wsteth.mint(user, ETH(100)) - await steth.mintShares(wsteth.address, shares(100)) - await steth.mintShares(user, shares(100)) - await wsteth.approve(withdrawalQueue.address, ETH(300), { from: user }) - await impersonate(ethers.provider, alice.address) - await web3.eth.sendTransaction({ to: alice.address, from: user, value: ETH(1) }) - await wsteth.transfer(alice.address, ETH(100), { from: user }) - - const requests = [] - - const withdrawalRequestsCount = 5 - for (let i = 0; i < withdrawalRequestsCount; ++i) { - requests.push(ETH(10)) - } - - const amount = bn(ETH(10)).mul(bn(withdrawalRequestsCount)) - const chainId = await wsteth.getChainId() - const deadline = MAX_UINT256 - const domainSeparator = makeDomainSeparator('Wrapped liquid staked Ether 2.0', '1', chainId, wsteth.address) - const { v, r, s } = signPermit( - alice.address, - withdrawalQueue.address, - amount, // amount - 0, // nonce - deadline, - domainSeparator, - alice.key - ) - const permission = [ - amount, - deadline, // deadline - v, - r, - s, - ] - - const aliceBalancesBefore = await wsteth.balanceOf(alice.address) - const lastRequestIdBefore = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.requestWithdrawalsWstETHWithPermit(requests, owner, permission, { from: alice.address }) - assert.equals(await withdrawalQueue.getLastRequestId(), lastRequestIdBefore.add(bn(requests.length))) - const aliceBalancesAfter = await wsteth.balanceOf(alice.address) - assert.equals(aliceBalancesAfter, aliceBalancesBefore.sub(bn(ETH(10)).mul(bn(withdrawalRequestsCount)))) - }) - }) - context('requestWithdrawalsWithPermit()', () => { const [alice] = ACCOUNTS_AND_KEYS it('works correctly with non empty payload', async () => { @@ -1116,7 +987,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it("One can't change claimed request", async () => { - await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([requestId], shareRate(300), { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(requestId, { from: user }) await assert.reverts( From 8b19ea12ff2d1363e1e4bfa46d65fad19713a5b6 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 28 Feb 2023 22:07:39 +0700 Subject: [PATCH 065/236] test: scenario: el rewards: un skip and fix/upgrage --- contracts/0.8.9/oracle/AccountingOracle.sol | 4 +- ...tion_layer_rewards_after_the_merge.test.js | 491 ++++++++++++------ 2 files changed, 338 insertions(+), 157 deletions(-) diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index f6ef31d40..30a49e40e 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -243,8 +243,8 @@ contract AccountingOracle is BaseOracle { /// @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. + /// up to (and including) the one passed in the lastFinalizableWithdrawalRequestId field. + /// Must be set to zero if lastFinalizableWithdrawalRequestId is zero. uint256 simulatedShareRate; /// @dev Whether, based on the state observed at the reference slot, the protocol should diff --git a/test/scenario/execution_layer_rewards_after_the_merge.test.js b/test/scenario/execution_layer_rewards_after_the_merge.test.js index 951372ef2..cf62877ff 100644 --- a/test/scenario/execution_layer_rewards_after_the_merge.test.js +++ b/test/scenario/execution_layer_rewards_after_the_merge.test.js @@ -1,4 +1,4 @@ -const { contract, artifacts, web3 } = require('hardhat') +const { contract, artifacts, web3, ethers } = require('hardhat') const { assert } = require('../helpers/assert') const { BN } = require('bn.js') @@ -15,6 +15,7 @@ const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') const TOTAL_BASIS_POINTS = 10 ** 4 const MAX_POSITIVE_REBASE_PRECISION_POINTS = 10 ** 9 const CURATED_MODULE_ID = 1 +const LIDO_INIT_BALANCE_ETH = 1 const makeAccountingReport = ({ refSlot, numValidators, clBalanceGwei, elRewardsVaultBalance }) => ({ refSlot, @@ -32,8 +33,35 @@ const makeAccountingReport = ({ refSlot, numValidators, clBalanceGwei, elRewards extraDataHash: ZERO_HASH, extraDataItemsCount: 0, }) - -contract.skip('Lido: merge acceptance', (addresses) => { +function calcReportDataHash(reportItems) { + const data = web3.eth.abi.encodeParameters( + [ + '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)', + ], + [reportItems] + ) + return web3.utils.keccak256(data) +} +function getReportDataItems(r) { + return [ + r.consensusVersion, + +r.refSlot, + r.numValidators, + r.clBalanceGwei, + r.stakingModuleIdsWithNewlyExitedValidators, + r.numExitedValidatorsByStakingModule, + r.withdrawalVaultBalance, + r.elRewardsVaultBalance, + r.lastWithdrawalRequestIdToFinalize, + r.finalizationShareRate, + r.isBunkerMode, + r.extraDataFormat, + r.extraDataHash, + r.extraDataItemsCount, + ] +} + +contract('Lido: merge acceptance', (addresses) => { const [ // node operators operator_1, @@ -50,7 +78,8 @@ contract.skip('Lido: merge acceptance', (addresses) => { let oracleMock, depositContractMock let treasuryAddr, guardians, stakingRouter let depositSecurityModule, depositRoot - let elRewardsVault, voting + let elRewardsVault, voting, signers + let consensus // Total fee is 1% const totalFeePoints = 0.01 * TOTAL_BASIS_POINTS @@ -115,12 +144,16 @@ contract.skip('Lido: merge acceptance', (addresses) => { oracleMock = deployed.oracle depositContractMock = deployed.depositContract + // consensus members + signers = deployed.signers + // addresses treasuryAddr = deployed.treasury.address depositSecurityModule = deployed.depositSecurityModule guardians = deployed.guardians elRewardsVault = deployed.elRewardsVault voting = deployed.voting.address + consensus = deployed.consensusContract depositRoot = await depositContractMock.get_deposit_root() @@ -161,12 +194,10 @@ contract.skip('Lido: merge acceptance', (addresses) => { await nodeOperatorsRegistry.setNodeOperatorStakingLimit(0, validatorsLimit, { from: voting }) // The key was added - let totalKeys = await nodeOperatorsRegistry.getTotalSigningKeyCount(nodeOperator1.id, { from: nobody }) assert.equals(totalKeys, 1, 'total signing keys') // The key was not used yet - let unusedKeys = await nodeOperatorsRegistry.getUnusedSigningKeyCount(nodeOperator1.id, { from: nobody }) assert.equals(unusedKeys, 1, 'unused signing keys') @@ -193,7 +224,6 @@ contract.skip('Lido: merge acceptance', (addresses) => { await nodeOperatorsRegistry.setNodeOperatorStakingLimit(1, validatorsLimit, { from: voting }) // The key was added - totalKeys = await nodeOperatorsRegistry.getTotalSigningKeyCount(nodeOperator2.id, { from: nobody }) assert.equals(totalKeys, 1, 'total signing keys') @@ -232,7 +262,6 @@ contract.skip('Lido: merge acceptance', (addresses) => { ) // No Ether was deposited yet to the validator contract - assert.equals(await depositContractMock.totalCalls(), 0) const ether2Stat = await pool.getBeaconStat() @@ -241,14 +270,16 @@ contract.skip('Lido: merge acceptance', (addresses) => { // All Ether was buffered within the pool contract atm - assert.equals(await pool.getBufferedEther(), ETH(3), 'buffered ether') - assert.equals(await pool.getTotalPooledEther(), ETH(3), 'total pooled ether') + // The contract's balance must be non-zero. When the contract is deployed, + // it receives LIDO_INIT_BALANCE_ETH ETH in deployProtocol() function. - // The amount of tokens corresponding to the deposited ETH value was minted to the user + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 3), 'buffered ether') + assert.equals(await pool.getTotalPooledEther(), ETH(LIDO_INIT_BALANCE_ETH + 3), 'total pooled ether') + // The amount of tokens corresponding to the deposited ETH value was minted to the user assert.equals(await token.balanceOf(user1), tokens(3), 'user1 tokens') - assert.equals(await token.totalSupply(), tokens(3), 'token total supply') + assert.equals(await token.totalSupply(), tokens(LIDO_INIT_BALANCE_ETH + 3), 'token total supply') }) it('the second user deposits 30 ETH to the pool', async () => { @@ -297,15 +328,18 @@ contract.skip('Lido: merge acceptance', (addresses) => { // Some Ether remained buffered within the pool contract - assert.equals(await pool.getBufferedEther(), ETH(1), 'buffered ether') - assert.equals(await pool.getTotalPooledEther(), ETH(1 + 32), 'total pooled ether') + // The contract's balance must be non-zero. When the contract is deployed, + // it receives LIDO_INIT_BALANCE_ETH ETH in deployProtocol() function. + + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 1), 'buffered ether') + assert.equals(await pool.getTotalPooledEther(), ETH(LIDO_INIT_BALANCE_ETH + 1 + 32), 'total pooled ether') // The amount of tokens corresponding to the deposited ETH value was minted to the users assert.equals(await token.balanceOf(user1), tokens(3), 'user1 tokens') assert.equals(await token.balanceOf(user2), tokens(30), 'user2 tokens') - assert.equals(await token.totalSupply(), tokens(3 + 30), 'token total supply') + assert.equals(await token.totalSupply(), tokens(LIDO_INIT_BALANCE_ETH + 3 + 30), 'token total supply') }) it('the third user deposits 64 ETH to the pool', async () => { @@ -358,8 +392,11 @@ contract.skip('Lido: merge acceptance', (addresses) => { // The pool ran out of validator keys, so the remaining 32 ETH were added to the // pool buffer - assert.equals(await pool.getBufferedEther(), ETH(1 + 32), 'buffered ether') - assert.equals(await pool.getTotalPooledEther(), ETH(33 + 64), 'total pooled ether') + // The contract's balance must be non-zero. When the contract is deployed, + // it receives LIDO_INIT_BALANCE_ETH ETH in deployProtocol() function. + + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 1 + 32), 'buffered ether') + assert.equals(await pool.getTotalPooledEther(), ETH(LIDO_INIT_BALANCE_ETH + 3 + 30 + 64), 'total pooled ether') // The amount of tokens corresponding to the deposited ETH value was minted to the users @@ -367,7 +404,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { assert.equals(await token.balanceOf(user2), tokens(30), 'user2 tokens') assert.equals(await token.balanceOf(user3), tokens(64), 'user3 tokens') - assert.equals(await token.totalSupply(), tokens(3 + 30 + 64), 'token total supply') + assert.equals(await token.totalSupply(), tokens(LIDO_INIT_BALANCE_ETH + 3 + 30 + 64), 'token total supply') }) it('collect 9 ETH execution layer rewards to the vault', async () => { @@ -375,30 +412,34 @@ contract.skip('Lido: merge acceptance', (addresses) => { assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(9), 'Execution layer rewards vault balance') }) - it('the oracle reports balance increase on Ethereum2 side (+32 ETH) and claims collected execution layer rewards (+9 ETH)', async () => { - const frame = 1 - + it('the oracle reports balance increase on Ethereum2 side (+0.35 ETH) and claims collected execution layer rewards (+9 ETH)', async () => { // Total shares are equal to deposited eth before ratio change and fee mint const oldTotalShares = await token.getTotalShares() - assert.equals(oldTotalShares, ETH(97), 'total shares') + assert.equals(oldTotalShares, ETH(LIDO_INIT_BALANCE_ETH + 97), 'total shares') // Old total pooled Ether const oldTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(oldTotalPooledEther, ETH(33 + 64), 'total pooled ether') + assert.equals(oldTotalPooledEther, ETH(LIDO_INIT_BALANCE_ETH + 3 + 30 + 64), 'total pooled ether') + + // Reporting balance increase (64 => 64.35) - // Reporting 1.5-fold balance increase (64 => 96) + const { refSlot } = await consensus.getCurrentFrame() - await oracleMock.submitReportData( + const reportItems = getReportDataItems( makeAccountingReport({ - refSlot: frame * SLOTS_PER_FRAME - 1, + refSlot: +refSlot, numValidators: 2, - clBalanceGwei: gwei(96), + clBalanceGwei: gwei(64.35), elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), - }), - 1 + }) ) + const reportHash = calcReportDataHash(reportItems) + + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) + await oracleMock.submitReportData(reportItems, 1, { from: signers[4].address }) // Execution layer rewards just claimed assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(0), 'Execution layer rewards vault balance') @@ -407,51 +448,61 @@ contract.skip('Lido: merge acceptance', (addresses) => { // shares ~= oldTotalShares + reward * oldTotalShares / (newTotalPooledEther - reward) // // totalFee = 1000 (10%) - // reward = 41000000000000000000 - // oldTotalShares = 97000000000000000000 - // newTotalPooledEther = 138000000000000000000 - // shares2mint = int(41000000000000000000 * 1000 * 97000000000000000000 / (138000000000000000000 * 10000 - 1000 * 41000000000000000000 )) - // shares2mint ~= 2970126960418222592 + // reward = 9350000000000000000 + // oldTotalShares = 98000000000000000000 + // newTotalPooledEther = 107350000000000000000 + // shares2mint = int(9350000000000000000 * 1000 * 98000000000000000000 / (107350000000000000000 * 10000 - 1000 * 9350000000000000000 )) + // shares2mint ~= 861062820091152800 const newTotalShares = await token.getTotalShares() - assert.equals(newTotalShares, new BN('99970126960418222554'), 'total shares') + assert.equals(newTotalShares, new BN('98861062820091152563'), 'total shares') const elRewards = 9 // Total pooled Ether increased - const newTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(newTotalPooledEther, ETH(33 + 96 + elRewards), 'total pooled ether') + assert.equals(newTotalPooledEther, ETH(LIDO_INIT_BALANCE_ETH + 3 + 30 + 64.35 + elRewards), 'total pooled ether') // Ether2 stat reported by the pool changed correspondingly const ether2Stat = await pool.getBeaconStat() assert.equals(ether2Stat.depositedValidators, 2, 'deposited ether2') - assert.equals(ether2Stat.beaconBalance, ETH(96), 'remote ether2') + assert.equals(ether2Stat.beaconBalance, ETH(64.35), 'remote ether2') // Buffered Ether amount changed on execution layer rewards - assert.equals(await pool.getBufferedEther(), ETH(33 + elRewards), 'buffered ether') + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 33 + elRewards), 'buffered ether') // New tokens was minted to distribute fee - assert.equals(await token.totalSupply(), tokens(129 + elRewards), 'token total supply') + assert.equals(await token.totalSupply(), tokens(98.35 + elRewards), 'token total supply') - const reward = toBN(ETH(96 - 64 + elRewards)) + const reward = toBN(ETH(64.35 - 64 + elRewards)) const mintedAmount = new BN(totalFeePoints).mul(reward).divn(TOTAL_BASIS_POINTS) + // rewards = 9350000000000000000 + // user1 shares = 3 + // user2 shares = 30 + // user3 shares = 64 + + // user1 balance = ETH(3) + 9350000000000000000 * 0.9 * 3/98 = ~3257602040816326530 + // user2 balance = ETH(30) + 9350000000000000000 * 0.9 * 30/98 = ~32576020408163265306 + // user3 balance = ETH(64) + 9350000000000000000 * 0.9 * 64/98 = ~69495510204081632653 + // Token user balances increased - assert.equals(await token.balanceOf(user1), new BN('4141237113402061855'), 'user1 tokens') - assert.equals(await token.balanceOf(user2), new BN('41412371134020618556'), 'user2 tokens') - assert.equals(await token.balanceOf(user3), new BN('88346391752577319587'), 'user3 tokens') + assert.equals(await token.balanceOf(user1), new BN('3257602040816326530'), 'user1 tokens') + assert.equals(await token.balanceOf(user2), new BN('32576020408163265306'), 'user2 tokens') + assert.equals(await token.balanceOf(user3), new BN('69495510204081632653'), '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 - assert.equals(await token.balanceOf(treasuryAddr), new BN('2049999999999999999'), 'treasury tokens') + + // treasuryFeePoints = 500, insuranceFeePoints = 0 + assert.equals(await token.balanceOf(treasuryAddr), new BN('467500000000000000'), 'treasury tokens') // Module fee, rewards distribution between modules should be make by module - assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('2049999999999999999'), 'module1 tokens') + assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('467499999999999999'), 'module1 tokens') // Real minted amount should be a bit less than calculated caused by round errors on mint and transfer operations assert( @@ -464,46 +515,50 @@ 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 setBalance(elRewardsVault.address, ETH(2)) - assert.equals( - await web3.eth.getBalance(elRewardsVault.address), - ETH(2) + balanceBefore, - 'Execution layer rewards vault balance' - ) + const balanceBefore = +(await web3.eth.getBalance(elRewardsVault.address)) + await setBalance(elRewardsVault.address, ETH(7)) - await setBalance(elRewardsVault.address, ETH(5)) assert.equals( await web3.eth.getBalance(elRewardsVault.address), - ETH(7) + balanceBefore, + +ETH(7) + balanceBefore, 'Execution layer rewards vault balance' ) }) it('the oracle reports same balance on Ethereum2 side (+0 ETH) and claims collected execution layer rewards (+7 ETH)', async () => { - const frame = 2 - // Total shares are equal to deposited eth before ratio change and fee mint const oldTotalShares = await token.getTotalShares() - assert.equals(oldTotalShares, new BN('99970126960418222554'), 'total shares') + assert.equals(oldTotalShares, new BN('98861062820091152563'), 'total shares') // Old total pooled Ether const oldTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(oldTotalPooledEther, ETH(138), 'total pooled ether') + assert.equals(oldTotalPooledEther, ETH(107.35), 'total pooled ether') - // Reporting the same balance as it was before (96ETH => 96ETH) - await oracleMock.submitReportData( + // Reporting the same balance as it was before (64.35ETH => 64.35ETH) + + const oneDay = 1 * 24 * 60 * 60 + await ethers.provider.send('evm_increaseTime', [oneDay]) + + await consensus.setQuorum(2) + const { refSlot } = await consensus.getCurrentFrame() + + const reportItems = getReportDataItems( makeAccountingReport({ - refSlot: frame * SLOTS_PER_FRAME - 1, + refSlot: +refSlot, numValidators: 2, - clBalanceGwei: gwei(96), + clBalanceGwei: gwei(64.35), elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), - }), - 1 + }) ) + const reportHash = calcReportDataHash(reportItems) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) + + await oracleMock.submitReportData(reportItems, 1, { from: signers[4].address }) // Execution layer rewards just claimed + assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(0), 'Execution layer rewards vault balance') // Total shares preserved because fee shares NOT minted @@ -515,28 +570,49 @@ contract.skip('Lido: merge acceptance', (addresses) => { // Total pooled Ether increased const newTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(newTotalPooledEther, ETH(138 + 7), 'total pooled ether') + assert.equals(newTotalPooledEther, ETH(107.35 + 7), 'total pooled ether') // Ether2 stat reported by the pool changed correspondingly const ether2Stat = await pool.getBeaconStat() assert.equals(ether2Stat.depositedValidators, 2, 'deposited ether2') - assert.equals(ether2Stat.beaconBalance, ETH(96), 'remote ether2') + assert.equals(ether2Stat.beaconBalance, ETH(64.35), 'remote ether2') // Buffered Ether amount changed on execution layer rewards - assert.equals(await pool.getBufferedEther(), ETH(42 + 7), 'buffered ether') + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 42 + 7), 'buffered ether') - assert.equals(await token.totalSupply(), tokens(145), 'token total supply') + assert.equals(await token.totalSupply(), tokens(114.35), 'token total supply') // All of the balances should be increased with proportion of newTotalPooledEther/oldTotalPooledEther (which is >1) // cause shares per user and overall shares number are preserved - assert.equals(await token.balanceOf(user1), new BN('4351299865531151949'), 'user1 tokens') - assert.equals(await token.balanceOf(user2), new BN('43512998655311519498'), 'user2 tokens') - assert.equals(await token.balanceOf(user3), new BN('92827730464664574929'), 'user3 tokens') + // oldTotalPooledEther = 107.35 + // newTotalPooledEther = 107.35 + 7 = 114.35 + // newTotalPooledEther/oldTotalPooledEther = 1.065207266 + // sharePrice = 1156673787819739000 - assert.equals(await token.balanceOf(treasuryAddr), new BN('2153985507246376811'), 'treasury tokens') - assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('2153985507246376811'), 'module1 tokens') + // user1 balance = 3257602040816326530 * 1.065207266 = ~3470021363459216942 + // user1 balance = sharePrice * shares = 1156673787819739000 * 3 = ~3470021363459216942 + + // user2 balance = 32576020408163265306 * 1.065207266 = ~34700213634592169424 + // user2 balance = sharePrice * shares = 1156673787819739000 * 30 = ~34700213634592169424 + + // user3 balance = 69495510204081632653 * 1.065207266 = ~74027122420463294773 + // user3 balance = sharePrice * shares = 1156673787819739000 * 64 = ~74027122420463294773 + + assert.equals(await token.balanceOf(user1), new BN('3470021363459216942'), 'user1 tokens') + assert.equals(await token.balanceOf(user2), new BN('34700213634592169424'), 'user2 tokens') + assert.equals(await token.balanceOf(user3), new BN('74027122420463294773'), 'user3 tokens') + + // treasuryTokenBalance = (oldTreasuryShares + mintedRewardShares * treasuryFeePoints / 10000) * sharePrice + + // oldTreasuryShares = 430531410045576260 + // mintedRewardShares = 0 + // sharePrice = 1156673787819739000 + // treasuryFeePoints = 500 + // treasuryTokenBalance = (43.0531410045576260 + (0 * 500) / 10000) * 1156673787819739000 = ~497984396832789939 + assert.equals(await token.balanceOf(treasuryAddr), new BN('497984396832789939'), 'treasury tokens') + assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('497984396832789938'), 'module1 tokens') // operators do not claim rewards from module assert.equals(await token.balanceOf(nodeOperator1.address), 0, 'operator_1 tokens') @@ -549,27 +625,36 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('the oracle reports loss on Ethereum2 side (-2 ETH) and claims collected execution layer rewards (+5 ETH)', async () => { - const frame = 3 - // Total shares are equal to deposited eth before ratio change and fee mint const oldTotalShares = await token.getTotalShares() - assert.equals(oldTotalShares, new BN('99970126960418222554'), 'total shares') + assert.equals(oldTotalShares, new BN('98861062820091152563'), 'total shares') // Old total pooled Ether const oldTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(oldTotalPooledEther, ETH(145), 'total pooled ether') + assert.equals(oldTotalPooledEther, ETH(114.35), 'total pooled ether') + + // Reporting balance decrease (64.35ETH => 62.35ETH) + + const oneDay = 1 * 24 * 60 * 60 + await ethers.provider.send('evm_increaseTime', [oneDay]) + + await consensus.setQuorum(2) + const { refSlot } = await consensus.getCurrentFrame() - // Reporting balance decrease (96ETH => 94ETH) - await oracleMock.submitReportData( + const reportItems = getReportDataItems( makeAccountingReport({ - refSlot: frame * SLOTS_PER_FRAME - 1, + refSlot: +refSlot, numValidators: 2, - clBalanceGwei: gwei(94), + clBalanceGwei: gwei(62.35), elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), - }), - 1 + }) ) + const reportHash = calcReportDataHash(reportItems) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) + + await oracleMock.submitReportData(reportItems, 1, { from: signers[4].address }) // Execution layer rewards just claimed assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(0), 'Execution layer rewards vault balance') @@ -581,27 +666,49 @@ contract.skip('Lido: merge acceptance', (addresses) => { // Total pooled Ether increased by 5ETH - 2ETH const newTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(newTotalPooledEther, ETH(145 + 3), 'total pooled ether') + assert.equals(newTotalPooledEther, ETH(114.35 + 3), 'total pooled ether') // Ether2 stat reported by the pool changed correspondingly const ether2Stat = await pool.getBeaconStat() assert.equals(ether2Stat.depositedValidators, 2, 'deposited ether2') - assert.equals(ether2Stat.beaconBalance, ETH(94), 'remote ether2') + assert.equals(ether2Stat.beaconBalance, ETH(62.35), 'remote ether2') // Buffered Ether amount changed on execution layer rewards - assert.equals(await pool.getBufferedEther(), ETH(49 + 5), 'buffered ether') + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 49 + 5), 'buffered ether') - assert.equals(await token.totalSupply(), tokens(145 + 3), 'token total supply') + assert.equals(await token.totalSupply(), tokens(114.35 + 3), 'token total supply') // All of the balances should be increased with proportion of newTotalPooledEther/oldTotalPooledEther (which is >1) // cause shares per user and overall shares number are preserved - assert.equals(await token.balanceOf(user1), new BN('4441326759300761990'), 'user1 tokens') - assert.equals(await token.balanceOf(user2), new BN('44413267593007619901'), 'user2 tokens') - assert.equals(await token.balanceOf(user3), new BN('94748304198416255789'), 'user3 tokens') + // oldTotalPooledEther = 114.35 + // newTotalPooledEther = 114.35 + 3 = 117.35 + // newTotalPooledEther/oldTotalPooledEther = 1,0262352427 + // sharePrice = 1187019405340151800 + + // user1 balance = 3470021363459216942 * 1,0262352427 = ~3561058216020455690 + // user1 balance = sharePrice * shares = 1187019405340151800 * 3 = ~3561058216020455690 + + // user2 balance = 34700213634592169424 * 1,0262352427 = ~35610582160204556904 + // user2 balance = sharePrice * shares = 1187019405340151800 * 30 = ~35610582160204556904 + + // user3 balance = 74027122420463294773 * 1,0262352427 = ~75969241941769721395 + // user3 balance = sharePrice * shares = 1187019405340151800 * 64 = ~75969241941769721395 + + assert.equals(await token.balanceOf(user1), new BN('3561058216020455690'), 'user1 tokens') + assert.equals(await token.balanceOf(user2), new BN('35610582160204556904'), 'user2 tokens') + assert.equals(await token.balanceOf(user3), new BN('75969241941769721395'), 'user3 tokens') - assert.equals(await token.balanceOf(treasuryAddr), new BN('2198550724637681159'), 'treasury tokens') - assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('2198550724637681159'), 'module1 tokens') + // treasuryTokenBalance = (oldTreasuryShares + mintedRewardShares * treasuryFeePoints / 10000) * sharePrice + + // oldTreasuryShares = 430531410045576260 + // mintedRewardShares = 0 + // sharePrice = 1187019405340151800 + // treasuryFeePoints = 500 + // treasuryTokenBalance = (43.0531410045576260 + (0 * 500) / 10000) * 1187019405340151800 = ~511049138332557056 + + assert.equals(await token.balanceOf(treasuryAddr), new BN('511049138332557056'), 'treasury tokens') + assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('511049138332557055'), 'module1 tokens') }) it('collect another 3 ETH execution layer rewards to the vault', async () => { @@ -610,27 +717,34 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('the oracle reports loss on Ethereum2 side (-3 ETH) and claims collected execution layer rewards (+3 ETH)', async () => { - const frame = 4 - // Total shares are equal to deposited eth before ratio change and fee mint const oldTotalShares = await token.getTotalShares() - assert.equals(oldTotalShares, new BN('99970126960418222554'), 'total shares') + assert.equals(oldTotalShares, new BN('98861062820091152563'), 'total shares') // Old total pooled Ether - const oldTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(oldTotalPooledEther, ETH(148), 'total pooled ether') + assert.equals(oldTotalPooledEther, ETH(117.35), 'total pooled ether') - // Reporting balance decrease (94ETH => 91ETH) - await oracleMock.submitReportData( + // Reporting balance decrease (62.35ETH => 59.35ETH) + const oneDay = 1 * 24 * 60 * 60 + await ethers.provider.send('evm_increaseTime', [oneDay]) + + await consensus.setQuorum(2) + const { refSlot } = await consensus.getCurrentFrame() + + const reportItems = getReportDataItems( makeAccountingReport({ - refSlot: frame * SLOTS_PER_FRAME - 1, + refSlot: +refSlot, numValidators: 2, - clBalanceGwei: gwei(91), + clBalanceGwei: gwei(59.35), elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), - }), - 1 + }) ) + const reportHash = calcReportDataHash(reportItems) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) + + await oracleMock.submitReportData(reportItems, 1, { from: signers[4].address }) // Execution layer rewards just claimed assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(0), 'Execution layer rewards vault balance') @@ -640,27 +754,31 @@ contract.skip('Lido: merge acceptance', (addresses) => { const newTotalShares = await token.getTotalShares() assert.equals(newTotalShares, oldTotalShares, 'total shares') - // Total pooled Ether increased by 5ETH - 2ETH const newTotalPooledEther = await pool.getTotalPooledEther() assert.equals(newTotalPooledEther, oldTotalPooledEther, 'total pooled ether') // Ether2 stat reported by the pool changed correspondingly const ether2Stat = await pool.getBeaconStat() assert.equals(ether2Stat.depositedValidators, 2, 'deposited ether2') - assert.equals(ether2Stat.beaconBalance, ETH(91), 'remote ether2') + assert.equals(ether2Stat.beaconBalance, ETH(59.35), 'remote ether2') // Buffered Ether amount changed on execution layer rewards - assert.equals(await pool.getBufferedEther(), ETH(54 + 3), 'buffered ether') + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 54 + 3), 'buffered ether') + + assert.equals(await token.totalSupply(), tokens(117.35), 'token total supply') - assert.equals(await token.totalSupply(), tokens(148), 'token total supply') + // oldTotalPooledEther = 117.35 + // newTotalPooledEther = 117.35 + // newTotalPooledEther/oldTotalPooledEther = 1 + // sharePrice = 1187019405340151800 // All of the balances should be the same as before cause overall changes sums to zero - assert.equals(await token.balanceOf(user1), new BN('4441326759300761990'), 'user1 tokens') - assert.equals(await token.balanceOf(user2), new BN('44413267593007619901'), 'user2 tokens') - assert.equals(await token.balanceOf(user3), new BN('94748304198416255789'), 'user3 tokens') + assert.equals(await token.balanceOf(user1), new BN('3561058216020455690'), 'user1 tokens') + assert.equals(await token.balanceOf(user2), new BN('35610582160204556904'), 'user2 tokens') + assert.equals(await token.balanceOf(user3), new BN('75969241941769721395'), 'user3 tokens') - assert.equals(await token.balanceOf(treasuryAddr), new BN('2198550724637681159'), 'treasury tokens') - assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('2198550724637681159'), 'module1 tokens') + assert.equals(await token.balanceOf(treasuryAddr), new BN('511049138332557056'), 'treasury tokens') + assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('511049138332557055'), 'module1 tokens') }) it('collect another 2 ETH execution layer rewards to the vault', async () => { @@ -669,27 +787,36 @@ contract.skip('Lido: merge acceptance', (addresses) => { }) it('the oracle reports loss on Ethereum2 side (-8 ETH) and claims collected execution layer rewards (+2 ETH)', async () => { - const frame = 5 - // Total shares are equal to deposited eth before ratio change and fee mint + const oldTotalShares = await token.getTotalShares() - assert.equals(oldTotalShares, new BN('99970126960418222554'), 'total shares') + assert.equals(oldTotalShares, new BN('98861062820091152563'), 'total shares') // Old total pooled Ether const oldTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(oldTotalPooledEther, ETH(148), 'total pooled ether') + assert.equals(oldTotalPooledEther, ETH(117.35), 'total pooled ether') + + // Reporting balance decrease (59.35ETH => 51.35ETH) + const oneDay = 1 * 24 * 60 * 60 + await ethers.provider.send('evm_increaseTime', [oneDay]) - // Reporting balance decrease (91ETH => 83ETH) - await oracleMock.submitReportData( + await consensus.setQuorum(2) + const { refSlot } = await consensus.getCurrentFrame() + + const reportItems = getReportDataItems( makeAccountingReport({ - refSlot: frame * SLOTS_PER_FRAME - 1, + refSlot: +refSlot, numValidators: 2, - clBalanceGwei: gwei(83), + clBalanceGwei: gwei(51.35), elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), - }), - 1 + }) ) + const reportHash = calcReportDataHash(reportItems) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) + + await oracleMock.submitReportData(reportItems, 1, { from: signers[4].address }) // Execution layer rewards just claimed assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(0), 'Execution layer rewards vault balance') @@ -701,26 +828,48 @@ contract.skip('Lido: merge acceptance', (addresses) => { // Total pooled Ether decreased by 8ETH-2ETH const newTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(newTotalPooledEther, ETH(142), 'total pooled ether') + assert.equals(newTotalPooledEther, ETH(111.35), 'total pooled ether') // Ether2 stat reported by the pool changed correspondingly const ether2Stat = await pool.getBeaconStat() assert.equals(ether2Stat.depositedValidators, 2, 'deposited ether2') - assert.equals(ether2Stat.beaconBalance, ETH(83), 'remote ether2') + assert.equals(ether2Stat.beaconBalance, ETH(51.35), 'remote ether2') // Buffered Ether amount changed on execution layer rewards - assert.equals(await pool.getBufferedEther(), ETH(57 + 2), 'buffered ether') + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 57 + 2), 'buffered ether') - assert.equals(await token.totalSupply(), tokens(142), 'token total supply') + assert.equals(await token.totalSupply(), tokens(111.35), 'token total supply') + + // oldTotalPooledEther = 117.35 + // newTotalPooledEther = 117.35 - 6 = 111.35 + // newTotalPooledEther/oldTotalPooledEther = 0,948870899 + // sharePrice = 1126328170299326100 + + // user1 balance = 3561058216020455690 * 0,948870899 = ~3378984510897978194 + // user1 balance = sharePrice * shares = 1126328170299326100 * 3 = ~3378984510897978194 + + // user2 balance = 35610582160204556904 * 0,948870899 = ~33789845108979781945 + // user2 balance = sharePrice * shares = 1126328170299326100 * 30 = ~33789845108979781945 + + // user3 balance = 75969241941769721395 * 0,948870899 = ~72085002899156868150 + // user3 balance = sharePrice * shares = 1126328170299326100 * 64 = ~72085002899156868150 // All of the balances should be decreased with proportion of newTotalPooledEther/oldTotalPooledEther (which is <1) // cause shares per user and overall shares number are preserved - assert.equals(await token.balanceOf(user1), new BN('4261272971761541909'), 'user1 tokens') - assert.equals(await token.balanceOf(user2), new BN('42612729717615419094'), 'user2 tokens') - assert.equals(await token.balanceOf(user3), new BN('90907156730912894068'), 'user3 tokens') + assert.equals(await token.balanceOf(user1), new BN('3378984510897978194'), 'user1 tokens') + assert.equals(await token.balanceOf(user2), new BN('33789845108979781945'), 'user2 tokens') + assert.equals(await token.balanceOf(user3), new BN('72085002899156868150'), 'user3 tokens') + + // treasuryTokenBalance = (oldTreasuryShares + mintedRewardShares * treasuryFeePoints / 10000) * sharePrice + + // oldTreasuryShares = 430531410045576260 + // mintedRewardShares = 0 + // sharePrice = 1126328170299326100 + // treasuryFeePoints = 500 + // treasuryTokenBalance = (43.0531410045576260 + (0 * 500) / 10000) * 1126328170299326100 = ~484919655333022823 - assert.equals(await token.balanceOf(treasuryAddr), new BN('2109420289855072463'), 'treasury tokens') - assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('2109420289855072463'), 'module1 tokens') + assert.equals(await token.balanceOf(treasuryAddr), new BN('484919655333022823'), 'treasury tokens') + assert.equals(await token.balanceOf(nodeOperatorsRegistry.address), new BN('484919655333022821'), 'module1 tokens') assert.equals(await token.balanceOf(nodeOperator1.address), 0, 'operator_1 tokens') assert.equals(await token.balanceOf(nodeOperator2.address), 0, 'operator_2 tokens') }) @@ -730,64 +879,96 @@ contract.skip('Lido: merge acceptance', (addresses) => { assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(3), 'Execution layer vault balance') }) - it('the oracle reports balance increase on Ethereum2 side (+2 ETH) and claims collected execution layer rewards (+3 ETH)', async () => { - const frame = 6 - + it('the oracle reports balance increase on Ethereum2 side (+0.14 ETH) and claims collected execution layer rewards (+3 ETH)', async () => { // Total shares are equal to deposited eth before ratio change and fee mint + const oldTotalShares = await token.getTotalShares() - assert.equals(oldTotalShares, new BN('99970126960418222554'), 'total shares') + assert.equals(oldTotalShares, new BN('98861062820091152563'), 'total shares') // Old total pooled Ether const oldTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(oldTotalPooledEther, ETH(142), 'total pooled ether') + assert.equals(oldTotalPooledEther, ETH(111.35), 'total pooled ether') + + // Reporting balance increase (51.35ETH => 51.49ETH) + const oneDay = 1 * 24 * 60 * 60 + await ethers.provider.send('evm_increaseTime', [oneDay]) - // Reporting balance increase (83ETH => 85ETH) - await oracleMock.submitReportData( + await consensus.setQuorum(2) + const { refSlot } = await consensus.getCurrentFrame() + + const reportItems = getReportDataItems( makeAccountingReport({ - refSlot: frame * SLOTS_PER_FRAME - 1, + refSlot: +refSlot, numValidators: 2, - clBalanceGwei: gwei(85), + clBalanceGwei: gwei(51.49), elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), - }), - 1 + }) ) + const reportHash = calcReportDataHash(reportItems) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) + + await oracleMock.submitReportData(reportItems, 1, { from: signers[4].address }) // Execution layer rewards just claimed + assert.equals(await web3.eth.getBalance(elRewardsVault.address), ETH(0), 'Execution layer rewards vault balance') // Total shares increased because fee minted (fee shares added) // shares ~= oldTotalShares + reward * oldTotalShares / (newTotalPooledEther - reward) + // + // totalFee = 1000 (10%) + // reward = 3140000000000000000 + // oldTotalShares = 98861062820091152563 + // newTotalPooledEther = 114490000000000000000 + // shares2mint = int(3140000000000000000 * 1000 * 98861062820091152563 / (114490000000000000000 * 10000 - 1000 * 3140000000000000000 )) + // shares2mint ~= 271881776603740030 + // newTotalShares = oldTotalShares + shares2mint = 98861062820091152563 + 271881776603740030 ~= 99132944596694892595 const newTotalShares = await token.getTotalShares() - assert.equals(newTotalShares, new BN('100311321932979376897'), 'total shares') + assert.equals(newTotalShares, new BN('99132944596694892595'), 'total shares') - // Total pooled Ether increased by 2ETH+3ETH + // Total pooled Ether increased by 0.14ETH+3ETH const newTotalPooledEther = await pool.getTotalPooledEther() - assert.equals(newTotalPooledEther, ETH(142 + 5), 'total pooled ether') + assert.equals(newTotalPooledEther, ETH(111.49 + 3), 'total pooled ether') // Ether2 stat reported by the pool changed correspondingly const ether2Stat = await pool.getBeaconStat() assert.equals(ether2Stat.depositedValidators, 2, 'deposited ether2') - assert.equals(ether2Stat.beaconBalance, ETH(85), 'remote ether2') + assert.equals(ether2Stat.beaconBalance, ETH(51.49), 'remote ether2') // Buffered Ether amount changed on execution layer rewards - assert.equals(await pool.getBufferedEther(), ETH(59 + 3), 'buffered ether') + assert.equals(await pool.getBufferedEther(), ETH(LIDO_INIT_BALANCE_ETH + 59 + 3), 'buffered ether') - assert.equals(await token.totalSupply(), tokens(142 + 5), 'token total supply') + assert.equals(await token.totalSupply(), tokens(111.49 + 3), 'token total supply') + + // newTotalPooledEther/oldTotalPooledEther = 1.0281993714 + // sharePrice = 1154913742003555000 + + // user1 balance = sharePrice * shares = 1154913742003555000 * 3 = ~3464741226010665095 + // user2 balance = sharePrice * shares = 1154913742003555000 * 30 = ~34647412260106650951 + // user3 balance = sharePrice * shares = 1154913742003555000 * 64 = ~73914479488227522028 // Token user balances increased - assert.equals(await token.balanceOf(user1), new BN('4396313312415956969'), 'user1 tokens') - assert.equals(await token.balanceOf(user2), new BN('43963133124159569699'), 'user2 tokens') - assert.equals(await token.balanceOf(user3), new BN('93788017331540415359'), 'user3 tokens') + assert.equals(await token.balanceOf(user1), new BN('3464741226010665095'), 'user1 tokens') + assert.equals(await token.balanceOf(user2), new BN('34647412260106650951'), 'user2 tokens') + assert.equals(await token.balanceOf(user3), new BN('73914479488227522028'), 'user3 tokens') // Fee, in the form of minted tokens, was distributed between treasury, insurance fund // and node operators // treasuryTokenBalance = (oldTreasuryShares + mintedRewardShares * treasuryFeePoints / 10000) * sharePrice - assert.equals((await token.balanceOf(treasuryAddr)).divn(10), new BN('242626811594202898'), 'treasury tokens') + + // oldTreasuryShares = 566472298347446300 + // mintedRewardShares = 0 + // sharePrice = 1154913742003555000 + // treasuryFeePoints = 500 + // treasuryTokenBalance = (56.6472298347446300 + (0 * 500) / 10000) * 1154913742003555000 = ~65422664182580344 + + assert.equals((await token.balanceOf(treasuryAddr)).divn(10), new BN('65422664182580344'), 'treasury tokens') assert.equals( (await token.balanceOf(nodeOperatorsRegistry.address)).divn(10), - new BN('242626811594202898'), + new BN('65422664182580344'), 'module1 tokens' ) }) @@ -814,7 +995,7 @@ contract.skip('Lido: merge acceptance', (addresses) => { assert.equals(await web3.eth.getBalance(elRewardsVault.address), elRewards, 'Execution layer rewards vault balance') let frame = 7 - let lastBeaconBalance = toBN(ETH(85)) + let lastBeaconBalance = toBN(ETH(51.45)) await pool.setMaxPositiveTokenRebase(getMaxPositiveRebaseForFrame(frame), { from: voting }) let maxPositiveRebase = await pool.getMaxPositiveTokenRebase() From d8bced17e8e5b855f235bbd915fcb3e190c61b14 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 17:47:47 +0200 Subject: [PATCH 066/236] fix: limit batches number by max extremum inside --- contracts/0.8.9/WithdrawalQueueBase.sol | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 4bc2e2a77..459d7e532 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -168,7 +168,6 @@ abstract contract WithdrawalQueueBase { } // TODO: 1-2 wei corner case use rebaseTimestamp - // TODO: [10, 10] batches (when last id is also a crossing point) function calculateFinalizationBatches(uint256 _maxShareRate, uint256 _maxTimestamp, CalcState memory _state) external view @@ -188,12 +187,21 @@ abstract contract WithdrawalQueueBase { prevRequestShareRate = _calcShareRate(_state.batches[_state.batches[0]], _maxShareRate); } uint256 lastRequestId = getLastRequestId(); - uint256 maxPossibleRequstId = requestId + MAX_REQUESTS_PER_CALL; + uint256 maxPossibleRequestId = requestId + MAX_REQUESTS_PER_CALL; + uint256 extemumStartIndex = _getLastCheckedExtremum() + 1; uint256 extremaCounter; - while (requestId < maxPossibleRequstId) { + while (requestId < maxPossibleRequestId) { if (requestId > lastRequestId) break; // if end of the queue + + if (requestId == _getExtrema()[extemumStartIndex + extremaCounter]) { + unchecked{ + ++extremaCounter; + } + if (extremaCounter > MAX_EXTREMA_PER_CALL) break; + } + WithdrawalRequest memory request = _getQueue()[requestId]; if (request.timestamp > _maxTimestamp) break; @@ -212,13 +220,6 @@ abstract contract WithdrawalQueueBase { _state.ethBudget -= etherRequested; - if (prevRequestShareRate != requestShareRate) { - ++extremaCounter; - // finalization batch is 36 days max - // todo: extrema counts - if (extremaCounter > MAX_EXTREMA_PER_CALL) break; - } - if (_state.batches[MAX_EXTREMA_PER_CALL] != 0 && ( // todo: check if we can omit `touching from above` case prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || @@ -234,7 +235,7 @@ abstract contract WithdrawalQueueBase { unchecked{ ++requestId; } } - _state.finished = requestId < maxPossibleRequstId || requestId == lastRequestId + 1; + _state.finished = requestId < maxPossibleRequestId || requestId == lastRequestId + 1; if (_state.finished) { assert(_state.batches[MAX_EXTREMA_PER_CALL] <= MAX_EXTREMA_PER_CALL); @@ -249,8 +250,6 @@ abstract contract WithdrawalQueueBase { return _state; } - // todo: move to finalizationValue or to requestWithdrawal - // read both request at once function onPreRebase() external { // Populate shareRate extrema list uint256 lastRequestId = getLastRequestId(); @@ -396,7 +395,7 @@ abstract contract WithdrawalQueueBase { } } - return extremumIndex; + return extremumIndex - 1; } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` From 218666ef4d97be6a6b486fd9b378b50bd1af6197 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 18:04:48 +0200 Subject: [PATCH 067/236] test: fix some ordinary tests --- test/0.8.9/withdrawal-queue.test.js | 104 +++++++++++++--------------- 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 83416c9de..602201fbf 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -300,10 +300,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('Finalizer can finalize a request', async () => { await assert.reverts( - withdrawalQueue.finalize(1, 0, { from: stranger }), + withdrawalQueue.finalize([1], 0, { from: stranger }), `AccessControl: account ${stranger.toLowerCase()} is missing role ${await withdrawalQueue.FINALIZE_ROLE()}` ) - await withdrawalQueue.finalize(1, 1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize([1], 1, { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), amount) assert.equals( @@ -313,7 +313,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('One can finalize requests with discount', async () => { - await withdrawalQueue.finalize(1, shareRate(150), { from: steth.address, value: ETH(150) }) + await withdrawalQueue.finalize([1], shareRate(150), { from: steth.address, value: ETH(150) }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(150)) assert.equals( @@ -327,11 +327,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.mintShares(user, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) - await withdrawalQueue.finalize(1, shareRate(10), { from: steth.address, value: ETH(10) }) + await withdrawalQueue.finalize([1], shareRate(10), { from: steth.address, value: ETH(10) }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(2, shareRate(10), { from: steth.address, value: ETH(10) }) + await withdrawalQueue.finalize([2], shareRate(10), { from: steth.address, value: ETH(10) }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) }) @@ -342,8 +342,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - const batch = await withdrawalQueue.finalizationValue([2], shareRate(300)) - await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([2], shareRate(300)) + await withdrawalQueue.finalize([2], shareRate(300), { from: steth.address, value: batch.ethToLock }) assert.equals(batch.sharesToBurn, shares(2)) assert.equals(await withdrawalQueue.getLastRequestId(), 2) @@ -362,7 +362,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([1], shareRate(300), { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 1) @@ -372,7 +372,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await ethers.provider.getBalance(withdrawalQueue.address) ) - await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([2], shareRate(300), { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 2) @@ -384,30 +384,30 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('batch reverts if share rate is zero', async () => { - await assert.reverts(withdrawalQueue.finalizationValue([1], shareRate(0)), 'ZeroShareRate()') + await assert.reverts(withdrawalQueue.prefinalize([1], shareRate(0)), 'ZeroShareRate()') }) it('reverts if request with given id did not even created', async () => { const idAhead = +(await withdrawalQueue.getLastRequestId()) + 1 await assert.reverts( - withdrawalQueue.finalize(idAhead, shareRate(300), { from: steth.address, value: amount }), + withdrawalQueue.finalize([idAhead], shareRate(300), { from: steth.address, value: amount }), `InvalidRequestId(${idAhead})` ) - await assert.reverts(withdrawalQueue.finalizationValue([idAhead], shareRate(300)), `InvalidRequestId(${idAhead})`) + await assert.reverts(withdrawalQueue.prefinalize([idAhead], shareRate(300)), `InvalidRequestId(${idAhead})`) }) it('reverts if request with given id was finalized already', async () => { const id = +(await withdrawalQueue.getLastRequestId()) - await withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([id], shareRate(300), { from: steth.address, value: amount }) await assert.reverts( - withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amount }), + withdrawalQueue.finalize([id], shareRate(300), { from: steth.address, value: amount }), `InvalidRequestId(${id})` ) - await assert.reverts(withdrawalQueue.finalizationValue([id], shareRate(300)), `InvalidRequestId(${id})`) + await assert.reverts(withdrawalQueue.prefinalize([id], shareRate(300)), `InvalidRequestId(${id})`) }) it('reverts if given amount to finalize exceeds requested', async () => { @@ -415,7 +415,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const amountExceeded = bn(ETH(400)) await assert.reverts( - withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amountExceeded }), + withdrawalQueue.finalize([id], shareRate(300), { from: steth.address, value: amountExceeded }), `TooMuchEtherToFinalize(${+amountExceeded}, ${+amount})` ) }) @@ -428,16 +428,16 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('works', async () => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize([1], shareRate(1), { from: steth.address, value: ETH(1) }) assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(1)) }) it('reverts if last hint checkpoint is ahead of requestId', async () => { - await withdrawalQueue.finalize(1, shareRate(0.5), { from: steth.address, value: ETH(0.5) }) + await withdrawalQueue.finalize([1], shareRate(0.5), { from: steth.address, value: ETH(0.5) }) await withdrawalQueue.requestWithdrawals([ETH(2)], owner, { from: user }) - await withdrawalQueue.finalize(2, shareRate(0.5), { from: steth.address, value: ETH(0.5) }) + await withdrawalQueue.finalize([2], shareRate(0.5), { from: steth.address, value: ETH(0.5) }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') }) @@ -448,7 +448,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('return 0 for claimed request', async () => { - await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize([1], shareRate(1), { from: steth.address, value: ETH(1) }) await withdrawalQueue.claimWithdrawals([1], [1], { from: owner }) assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(0)) @@ -459,7 +459,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts(withdrawalQueue.getClaimableEther([0], [1]), 'InvalidRequestId(0)') await assert.reverts(withdrawalQueue.getClaimableEther([2], [1]), 'InvalidRequestId(2)') - await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize([1], shareRate(1), { from: steth.address, value: ETH(1) }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') await assert.reverts(withdrawalQueue.getClaimableEther([1], [0]), 'InvalidHint(0)') @@ -467,8 +467,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') await withdrawalQueue.requestWithdrawals([ETH(1), ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize(2, shareRate(0.99), { from: steth.address, value: ETH(0.99) }) - await withdrawalQueue.finalize(3, shareRate(0.98), { from: steth.address, value: ETH(0.98) }) + await withdrawalQueue.finalize([2], shareRate(0.99), { from: steth.address, value: ETH(0.99) }) + await withdrawalQueue.finalize([3], shareRate(0.98), { from: steth.address, value: ETH(0.98) }) await assert.reverts(withdrawalQueue.getClaimableEther([3], [1]), 'InvalidHint(1)') }) @@ -481,7 +481,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('Owner can claim a finalized request to recipient address', async () => { - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([1], shareRate(300), { from: steth.address, value: amount }) const balanceBefore = bn(await ethers.provider.getBalance(user)) @@ -503,7 +503,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts if sender is not owner', async () => { - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([1], shareRate(300), { from: steth.address, value: amount }) await assert.reverts( withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: stranger }), `NotOwner("${stranger}", "${owner}")` @@ -511,14 +511,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts if there is not enough balance', async () => { - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([1], shareRate(300), { from: steth.address, value: amount }) await setBalance(withdrawalQueue.address, ETH(200)) await assert.reverts(withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: owner }), 'NotEnoughEther()') }) }) it('Owner can claim a finalized request without hint', async () => { - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([1], shareRate(300), { from: steth.address, value: amount }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) @@ -546,20 +546,20 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([2], shareRate(300), { from: steth.address, value: amount }) await assert.reverts(withdrawalQueue.claimWithdrawals([1], [0], { from: owner }), 'InvalidHint(0)') await assert.reverts(withdrawalQueue.claimWithdrawals([1], [2], { from: owner }), 'InvalidHint(2)') }) it('Cant withdraw token two times', async () => { - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) + await withdrawalQueue.finalize([1], shareRate(300), { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(1, { from: owner }) await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: owner }), 'RequestAlreadyClaimed(1)') }) it('Discounted withdrawals produce less eth', async () => { - await withdrawalQueue.finalize(1, shareRate(150), { from: steth.address, value: ETH(150) }) + await withdrawalQueue.finalize([1], shareRate(150), { from: steth.address, value: ETH(150) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(150)) @@ -612,7 +612,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('direct', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) + await withdrawalQueue.finalize([id], await currentRate(), { from: steth.address, value: total }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -624,7 +624,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('reverse', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) + await withdrawalQueue.finalize([id], await currentRate(), { from: steth.address, value: total }) for (let index = requestIds.length - 1; index >= 0; index--) { const requestId = requestIds[index] @@ -638,7 +638,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const randomIds = [...requestIds].sort(() => 0.5 - Math.random()) const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) + await withdrawalQueue.finalize([id], await currentRate(), { from: steth.address, value: total }) for (let index = 0; index < randomIds.length; index++) { const requestId = randomIds[index] @@ -653,14 +653,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const totalDistributedEth = bn(0) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] - await withdrawalQueue.finalize(requestId, await currentRate(), { + await withdrawalQueue.finalize([requestId], await currentRate(), { from: steth.address, value: ETH(1 / (index + 1)), }) totalDistributedEth.iadd(bn(ETH(1 / (index + 1)))) } const id = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(id, await currentRate(), { from: steth.address, value: total }) + await withdrawalQueue.finalize([id], await currentRate(), { from: steth.address, value: total }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -673,7 +673,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, context('caclulateFinalizationBatches()', () => { it('works', async () => { await withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }) - const batch = await withdrawalQueue.finalizationValue([1], shareRate(300)) + const batch = await withdrawalQueue.prefinalize.call([1], shareRate(300)) assert.equals(batch.ethToLock, ETH(300)) assert.equals(batch.sharesToBurn, shares(1)) @@ -689,8 +689,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, beforeEach(async () => { await withdrawalQueue.requestWithdrawals(requests, owner, { from: user }) - for (let i = 1; i <= numOfRequests; i++) { - await withdrawalQueue.finalize(i, { from: steth.address, value: ETH(discountedPrices[i]) }) + for (let i = 0; i < numOfRequests; i++) { + await withdrawalQueue.finalize([i + 1], shareRate(i), { + from: steth.address, + value: ETH(discountedPrices[i]), + }) } assert.equals(await withdrawalQueue.getLastCheckpointIndex(), numOfRequests) assert.equals( @@ -699,22 +702,13 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, ) }) - it('works unbounded', async () => { - assert.equals( - await withdrawalQueue.findCheckpointHintsUnbounded([10]), - await withdrawalQueue.getLastCheckpointIndex() - ) - }) - it('reverts if request is not finalized', async () => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) await assert.reverts(withdrawalQueue.findCheckpointHints([11], 1, 10), 'RequestNotFoundOrNotFinalized(11)') - await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([11]), 'RequestNotFoundOrNotFinalized(11)') }) it('reverts if there is no such a request', async () => { await assert.reverts(withdrawalQueue.findCheckpointHints([12], 1, 10), 'RequestNotFoundOrNotFinalized(12)') - await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([12]), 'RequestNotFoundOrNotFinalized(12)') }) it('range search (found)', async () => { @@ -756,7 +750,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, } }) - context('findCheckpointHints()', () => { + context('findCheckpointHints() 2', () => { let requestId const amount = ETH(20) @@ -793,8 +787,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns not found when indexes have negative overlap', async () => { - const batch = await withdrawalQueue.finalizationValue([requestId], shareRate(300)) - await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([requestId], shareRate(300)) + await withdrawalQueue.finalize([requestId], shareRate(300), { from: steth.address, value: batch.ethToLock }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints( [requestId], @@ -806,8 +800,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns hints array with one item for list from single request id', async () => { - const batch = await withdrawalQueue.finalizationValue([requestId], shareRate(300)) - await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([requestId], shareRate(300)) + await withdrawalQueue.finalize([requestId], shareRate(300), { from: steth.address, value: batch.ethToLock }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints([requestId], 1, lastCheckpointIndex) assert.equal(hints.length, 1) @@ -828,7 +822,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) const thirdRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(thirdRequestId, shareRate(20), { from: steth.address, value: ETH(40) }) + await withdrawalQueue.finalize([thirdRequestId], shareRate(20), { from: steth.address, value: ETH(40) }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints( @@ -856,7 +850,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) const thirdRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(thirdRequestId, shareRate(20), { from: steth.address, value: ETH(40) }) + await withdrawalQueue.finalize([thirdRequestId], shareRate(20), { from: steth.address, value: ETH(40) }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() await assert.reverts( @@ -880,7 +874,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const secondRequestAmount = ETH(10) await withdrawalQueue.requestWithdrawals([secondRequestAmount], owner, { from: owner }) const secondRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(secondRequestId, shareRate(30), { from: steth.address, value: ETH(30) }) + await withdrawalQueue.finalize([secondRequestId], shareRate(30), { from: steth.address, value: ETH(30) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) const tx = await withdrawalQueue.claimWithdrawals([1, 2], [1, 1], { from: owner }) From c4685a4302f2bf0b99edac26f63edd16dd012825 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Tue, 28 Feb 2023 19:08:51 +0200 Subject: [PATCH 068/236] hash consensus: allow updating a future initial epoch --- contracts/0.8.9/oracle/HashConsensus.sol | 27 ++++++++++- .../oracle/HashConsensusTimeTravellable.sol | 2 - lib/abi/HashConsensus.json | 2 +- .../hash-consensus-access-control.test.js | 37 +++++++++++++++ .../oracle/hash-consensus-deploy.test.js | 8 ++-- .../oracle/hash-consensus-frames.test.js | 45 ++++++++++++++++++- test/helpers/factories.js | 5 ++- 7 files changed, 115 insertions(+), 11 deletions(-) diff --git a/contracts/0.8.9/oracle/HashConsensus.sol b/contracts/0.8.9/oracle/HashConsensus.sol index 92161fc96..74b7cc817 100644 --- a/contracts/0.8.9/oracle/HashConsensus.sol +++ b/contracts/0.8.9/oracle/HashConsensus.sol @@ -76,6 +76,7 @@ contract HashConsensus is AccessControlEnumerable { error DuplicateMember(); error AddressCannotBeZero(); error InitialEpochIsYetToArrive(); + error InitialEpochAlreadyArrived(); error EpochsPerFrameCannotBeZero(); error NonMember(); error UnexpectedConsensusVersion(uint256 expected, uint256 received); @@ -205,7 +206,6 @@ contract HashConsensus is AccessControlEnumerable { uint256 secondsPerSlot, uint256 genesisTime, uint256 epochsPerFrame, - uint256 initialEpoch, uint256 fastLaneLengthSlots, address admin, address reportProcessor @@ -216,8 +216,12 @@ contract HashConsensus is AccessControlEnumerable { if (admin == address(0)) revert AdminCannotBeZero(); if (reportProcessor == address(0)) revert ReportProcessorCannotBeZero(); + _setupRole(DEFAULT_ADMIN_ROLE, admin); - _setFrameConfig(initialEpoch, epochsPerFrame, fastLaneLengthSlots, FrameConfig(0, 0, 0)); + + uint256 farFutureEpoch = _computeEpochAtTimestamp(type(uint64).max); + _setFrameConfig(farFutureEpoch, epochsPerFrame, fastLaneLengthSlots, FrameConfig(0, 0, 0)); + _reportProcessor = reportProcessor; } @@ -252,6 +256,25 @@ contract HashConsensus is AccessControlEnumerable { return (frame.refSlot, frame.reportProcessingDeadlineSlot); } + /// @notice Sets initial epoch given that the current initial epoch is in the future. + /// + /// @param initialEpoch The new initial epoch. + /// + function updateInitialEpoch(uint256 initialEpoch) external onlyRole(DEFAULT_ADMIN_ROLE) { + FrameConfig memory frameConfig = _frameConfig; + + if (_computeEpochAtTimestamp(_getTime()) >= frameConfig.initialEpoch) { + revert InitialEpochAlreadyArrived(); + } + + _setFrameConfig( + initialEpoch, + frameConfig.epochsPerFrame, + frameConfig.fastLaneLengthSlots, + frameConfig + ); + } + function setFrameConfig(uint256 epochsPerFrame, uint256 fastLaneLengthSlots) external onlyRole(MANAGE_FRAME_CONFIG_ROLE) { diff --git a/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol b/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol index 238cc9506..f4807747b 100644 --- a/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol +++ b/contracts/0.8.9/test_helpers/oracle/HashConsensusTimeTravellable.sol @@ -14,7 +14,6 @@ contract HashConsensusTimeTravellable is HashConsensus { uint256 secondsPerSlot, uint256 genesisTime, uint256 epochsPerFrame, - uint256 startEpoch, uint256 fastLaneLengthSlots, address admin, address reportProcessor @@ -23,7 +22,6 @@ contract HashConsensusTimeTravellable is HashConsensus { secondsPerSlot, genesisTime, epochsPerFrame, - startEpoch, fastLaneLengthSlots, admin, reportProcessor diff --git a/lib/abi/HashConsensus.json b/lib/abi/HashConsensus.json index 9704d5c43..ab3abbbbd 100644 --- a/lib/abi/HashConsensus.json +++ b/lib/abi/HashConsensus.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"reportProcessor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ConsensusReportAlreadyProcessing","type":"error"},{"inputs":[],"name":"DuplicateMember","type":"error"},{"inputs":[],"name":"DuplicateReport","type":"error"},{"inputs":[],"name":"EmptyReport","type":"error"},{"inputs":[],"name":"EpochsPerFrameCannotBeZero","type":"error"},{"inputs":[],"name":"FastLanePeriodCannotBeLongerThanFrame","type":"error"},{"inputs":[],"name":"InitialEpochIsYetToArrive","type":"error"},{"inputs":[],"name":"InvalidSlot","type":"error"},{"inputs":[],"name":"NewProcessorCannotBeTheSame","type":"error"},{"inputs":[],"name":"NonFastLaneMemberCannotReportWithinFastLaneInterval","type":"error"},{"inputs":[],"name":"NonMember","type":"error"},{"inputs":[],"name":"NumericOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"minQuorum","type":"uint256"},{"internalType":"uint256","name":"receivedQuorum","type":"uint256"}],"name":"QuorumTooSmall","type":"error"},{"inputs":[],"name":"ReportProcessorCannotBeZero","type":"error"},{"inputs":[],"name":"StaleReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"support","type":"uint256"}],"name":"ConsensusReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"FastLaneConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newInitialEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEpochsPerFrame","type":"uint256"}],"name":"FrameConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"prevQuorum","type":"uint256"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processor","type":"address"},{"indexed":true,"internalType":"address","name":"prevProcessor","type":"address"}],"name":"ReportProcessorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"}],"name":"ReportReceived","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISABLE_CONSENSUS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FAST_LANE_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FRAME_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_MEMBERS_AND_QUORUM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_REPORT_PROCESSOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableConsensus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusState","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"bytes32","name":"consensusReport","type":"bytes32"},{"internalType":"bool","name":"isReportProcessing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getConsensusStateForMember","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameConsensusReport","type":"bytes32"},{"internalType":"bool","name":"isMember","type":"bool"},{"internalType":"bool","name":"isFastLane","type":"bool"},{"internalType":"bool","name":"canReport","type":"bool"},{"internalType":"uint256","name":"lastMemberReportRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameMemberReport","type":"bytes32"}],"internalType":"struct HashConsensus.MemberConsensusState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastLaneMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsFastLaneMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportVariants","outputs":[{"internalType":"bytes32[]","name":"variants","type":"bytes32[]"},{"internalType":"uint256[]","name":"support","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":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"removeMember","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":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFastLaneLengthSlots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFrameConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"setQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProcessor","type":"address"}],"name":"setReportProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"bytes32","name":"report","type":"bytes32"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"submitReport","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":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"reportProcessor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ConsensusReportAlreadyProcessing","type":"error"},{"inputs":[],"name":"DuplicateMember","type":"error"},{"inputs":[],"name":"DuplicateReport","type":"error"},{"inputs":[],"name":"EmptyReport","type":"error"},{"inputs":[],"name":"EpochsPerFrameCannotBeZero","type":"error"},{"inputs":[],"name":"FastLanePeriodCannotBeLongerThanFrame","type":"error"},{"inputs":[],"name":"InitialEpochAlreadyArrived","type":"error"},{"inputs":[],"name":"InitialEpochIsYetToArrive","type":"error"},{"inputs":[],"name":"InvalidSlot","type":"error"},{"inputs":[],"name":"NewProcessorCannotBeTheSame","type":"error"},{"inputs":[],"name":"NonFastLaneMemberCannotReportWithinFastLaneInterval","type":"error"},{"inputs":[],"name":"NonMember","type":"error"},{"inputs":[],"name":"NumericOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"minQuorum","type":"uint256"},{"internalType":"uint256","name":"receivedQuorum","type":"uint256"}],"name":"QuorumTooSmall","type":"error"},{"inputs":[],"name":"ReportProcessorCannotBeZero","type":"error"},{"inputs":[],"name":"StaleReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"support","type":"uint256"}],"name":"ConsensusReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"FastLaneConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newInitialEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEpochsPerFrame","type":"uint256"}],"name":"FrameConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"prevQuorum","type":"uint256"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processor","type":"address"},{"indexed":true,"internalType":"address","name":"prevProcessor","type":"address"}],"name":"ReportProcessorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"}],"name":"ReportReceived","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISABLE_CONSENSUS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FAST_LANE_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FRAME_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_MEMBERS_AND_QUORUM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_REPORT_PROCESSOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableConsensus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusState","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"bytes32","name":"consensusReport","type":"bytes32"},{"internalType":"bool","name":"isReportProcessing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getConsensusStateForMember","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameConsensusReport","type":"bytes32"},{"internalType":"bool","name":"isMember","type":"bool"},{"internalType":"bool","name":"isFastLane","type":"bool"},{"internalType":"bool","name":"canReport","type":"bool"},{"internalType":"uint256","name":"lastMemberReportRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameMemberReport","type":"bytes32"}],"internalType":"struct HashConsensus.MemberConsensusState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastLaneMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsFastLaneMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportVariants","outputs":[{"internalType":"bytes32[]","name":"variants","type":"bytes32[]"},{"internalType":"uint256[]","name":"support","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":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"removeMember","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":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFastLaneLengthSlots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFrameConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"setQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProcessor","type":"address"}],"name":"setReportProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"bytes32","name":"report","type":"bytes32"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"submitReport","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":"initialEpoch","type":"uint256"}],"name":"updateInitialEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file 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 5a6577a6c..d3857ad13 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 @@ -1,6 +1,7 @@ const { ethers, contract, web3, artifacts } = require('hardhat') const { MaxUint256 } = require('@ethersproject/constants') +const { ZERO_BYTES32 } = require('../../helpers/constants') const { assert } = require('../../helpers/assert') const { EvmSnapshot } = require('../../helpers/blockchain') @@ -31,6 +32,42 @@ contract('HashConsensus', ([admin, account1, account2, member1, member2]) => { await snapshot.make() } + context('DEFAULT_ADMIN_ROLE', () => { + const DEFAULT_ADMIN_ROLE = ZERO_BYTES32 + + before(async () => { + await deploy({ initialEpoch: null }) + }) + + afterEach(async () => { + await snapshot.rollback() + }) + + context('updateInitialEpoch', () => { + it('reverts when called without DEFAULT_ADMIN_ROLE', async () => { + assert.revertsOZAccessControl( + consensus.updateInitialEpoch(10, { from: account1 }), + account1, + 'DEFAULT_ADMIN_ROLE' + ) + + await consensus.grantRole(manageFrameConfigRoleKeccak156, account2) + + assert.revertsOZAccessControl( + consensus.updateInitialEpoch(10, { from: account2 }), + account2, + 'DEFAULT_ADMIN_ROLE' + ) + }) + + it('allows calling from a possessor of DEFAULT_ADMIN_ROLE role', async () => { + await consensus.grantRole(DEFAULT_ADMIN_ROLE, account2, { from: admin }) + await consensus.updateInitialEpoch(10, { from: account2 }) + assert.equals((await consensus.getFrameConfig()).initialEpoch, 10) + }) + }) + }) + context('deploying', () => { before(deploy) 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 36885b604..13261f88a 100644 --- a/test/0.8.9/oracle/hash-consensus-deploy.test.js +++ b/test/0.8.9/oracle/hash-consensus-deploy.test.js @@ -56,14 +56,16 @@ async function deployHashConsensus( secondsPerSlot, genesisTime, epochsPerFrame, - initialEpoch, fastLaneLengthSlots, admin, reportProcessor.address, { from: admin } ) - await consensus.setTime(genesisTime + initialEpoch * slotsPerEpoch * secondsPerSlot) + if (initialEpoch !== null) { + await consensus.updateInitialEpoch(initialEpoch, { from: admin }) + await consensus.setTime(genesisTime + initialEpoch * slotsPerEpoch * secondsPerSlot) + } await consensus.grantRole(await consensus.MANAGE_MEMBERS_AND_QUORUM_ROLE(), admin, { from: admin }) await consensus.grantRole(await consensus.DISABLE_CONSENSUS_ROLE(), admin, { from: admin }) @@ -132,7 +134,6 @@ contract('HashConsensus', ([admin, member1]) => { SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - INITIAL_EPOCH, INITIAL_FAST_LANE_LENGTH_SLOTS, admin, ZERO_ADDRESS, @@ -150,7 +151,6 @@ contract('HashConsensus', ([admin, member1]) => { SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - INITIAL_EPOCH, INITIAL_FAST_LANE_LENGTH_SLOTS, ZERO_ADDRESS, reportProcessor.address, diff --git a/test/0.8.9/oracle/hash-consensus-frames.test.js b/test/0.8.9/oracle/hash-consensus-frames.test.js index 8be4232da..c967e5af1 100644 --- a/test/0.8.9/oracle/hash-consensus-frames.test.js +++ b/test/0.8.9/oracle/hash-consensus-frames.test.js @@ -1,9 +1,11 @@ const { contract } = require('hardhat') const { assert } = require('../../helpers/assert') +const { toBN } = require('../../helpers/utils') const { INITIAL_FAST_LANE_LENGTH_SLOTS, INITIAL_EPOCH, + GENESIS_TIME, EPOCHS_PER_FRAME, SLOTS_PER_EPOCH, SECONDS_PER_SLOT, @@ -96,10 +98,40 @@ contract('HashConsensus', ([admin, member1, member2]) => { let consensus before(async () => { - const deployed = await deployHashConsensus(admin, { initialEpoch: TEST_INITIAL_EPOCH }) + const deployed = await deployHashConsensus(admin, { initialEpoch: null }) consensus = deployed.consensus }) + it(`after deploy, the initial epoch is far in the future`, async () => { + const maxTimestamp = toBN(2).pow(toBN(64)).subn(1) + const maxEpoch = maxTimestamp.subn(GENESIS_TIME).divn(SECONDS_PER_SLOT).divn(SLOTS_PER_EPOCH) + assert.equals((await consensus.getFrameConfig()).initialEpoch, maxEpoch) + }) + + it(`after deploy, one can update initial epoch`, async () => { + const tx = await consensus.updateInitialEpoch(TEST_INITIAL_EPOCH, { from: admin }) + + assert.emits(tx, 'FrameConfigSet', { + newEpochsPerFrame: EPOCHS_PER_FRAME, + newInitialEpoch: TEST_INITIAL_EPOCH, + }) + + const frameConfig = await consensus.getFrameConfig() + assert.equals(frameConfig.initialEpoch, TEST_INITIAL_EPOCH) + assert.equals(frameConfig.epochsPerFrame, EPOCHS_PER_FRAME) + assert.equals(frameConfig.fastLaneLengthSlots, INITIAL_FAST_LANE_LENGTH_SLOTS) + }) + + it(`before the initial epoch arrives, one can update it freely`, async () => { + await consensus.setTimeInEpochs(TEST_INITIAL_EPOCH - 2) + + await consensus.updateInitialEpoch(TEST_INITIAL_EPOCH - 1, { from: admin }) + assert.equals((await consensus.getFrameConfig()).initialEpoch, TEST_INITIAL_EPOCH - 1) + + await consensus.updateInitialEpoch(TEST_INITIAL_EPOCH, { from: admin }) + assert.equals((await consensus.getFrameConfig()).initialEpoch, TEST_INITIAL_EPOCH) + }) + it('before the initial epoch arrives, members can be added and queried, and quorum increased', async () => { await consensus.setTimeInEpochs(TEST_INITIAL_EPOCH - 1) @@ -158,6 +190,17 @@ contract('HashConsensus', ([admin, member1, member2]) => { const tx = await consensus.submitReport(frame.refSlot, HASH_1, CONSENSUS_VERSION, { from: member1 }) assert.emits(tx, 'ReportReceived', { refSlot: frame.refSlot, member: member1, report: HASH_1 }) }) + + it('after the initial epoch comes, updating it via updateInitialEpoch is not possible anymore', async () => { + await assert.reverts( + consensus.updateInitialEpoch(TEST_INITIAL_EPOCH + 1, { from: admin }), + 'InitialEpochAlreadyArrived()' + ) + await assert.reverts( + consensus.updateInitialEpoch(TEST_INITIAL_EPOCH - 1, { from: admin }), + 'InitialEpochAlreadyArrived()' + ) + }) }) context('Reporting interval manipulation', () => { diff --git a/test/helpers/factories.js b/test/helpers/factories.js index c93c7d2ca..6a7a5832b 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -116,12 +116,13 @@ async function hashConsensusFactory({ voting, oracle, signers, legacyOracle, dep SECONDS_PER_SLOT, deployParams.genesisTime, EPOCHS_PER_FRAME, - initialEpoch, deployParams.hashConsensus.fastLaneLengthSlots, voting.address, oracle.address ) + await consensus.updateInitialEpoch(initialEpoch, { from: voting.address }) + await consensus.grantRole(await consensus.MANAGE_MEMBERS_AND_QUORUM_ROLE(), voting.address, { from: voting.address }) await consensus.grantRole(await consensus.DISABLE_CONSENSUS_ROLE(), voting.address, { from: voting.address }) await consensus.grantRole(await consensus.MANAGE_FRAME_CONFIG_ROLE(), voting.address, { from: voting.address }) @@ -161,6 +162,8 @@ async function hashConsensusTimeTravellableFactory({ oracle.address ) + await consensus.updateInitialEpoch(initialEpoch, { from: voting.address }) + await consensus.grantRole(await consensus.MANAGE_MEMBERS_AND_QUORUM_ROLE(), voting.address, { from: voting.address }) await consensus.grantRole(await consensus.DISABLE_CONSENSUS_ROLE(), voting.address, { from: voting.address }) await consensus.grantRole(await consensus.MANAGE_FRAME_CONFIG_ROLE(), voting.address, { from: voting.address }) From 21560e744630653223b5f74fe287f86ac47b4520 Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Wed, 1 Mar 2023 01:26:31 +0700 Subject: [PATCH 069/236] update sr tests --- .../staking-router/report-exited-keys.test.js | 447 ++++++++++++++++++ test/helpers/staking-modules.js | 7 + 2 files changed, 454 insertions(+) create mode 100644 test/0.8.9/staking-router/report-exited-keys.test.js diff --git a/test/0.8.9/staking-router/report-exited-keys.test.js b/test/0.8.9/staking-router/report-exited-keys.test.js new file mode 100644 index 000000000..d3a738827 --- /dev/null +++ b/test/0.8.9/staking-router/report-exited-keys.test.js @@ -0,0 +1,447 @@ +const { contract, ethers } = require('hardhat') +const { assert } = require('../../helpers/assert') +const { EvmSnapshot } = require('../../helpers/blockchain') +const { hexConcat, hex, ETH } = require('../../helpers/utils') +const { deployProtocol } = require('../../helpers/protocol') +const { setupNodeOperatorsRegistry } = require('../../helpers/staking-modules') + +const ADDRESS_1 = '0x0000000000000000000000000000000000000001' + +let router, voting +let operators, module2 +let module1Id, module2Id +let maxDepositsPerModule + +contract('StakingRouter', ([admin, depositor]) => { + const evmSnapshot = new EvmSnapshot(ethers.provider) + + const snapshot = () => evmSnapshot.make() + const revert = () => evmSnapshot.revert() + + before(async () => { + const deployed = await deployProtocol({ + depositSecurityModuleFactory: async () => { + return { address: depositor } + }, + }) + + router = deployed.stakingRouter + voting = deployed.voting.address + operators = await setupNodeOperatorsRegistry(deployed, true) + module2 = await setupNodeOperatorsRegistry(deployed, true) + + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await router.grantRole(await router.REPORT_EXITED_VALIDATORS_ROLE(), admin, { from: admin }) + + // get max allocation per module + maxDepositsPerModule = async () => { + const modulesIds = await router.getStakingModuleIds() + const maxDepositsPerModule = [] + for (let i = 0; i < modulesIds.length; i++) { + const maxCount = +(await router.getStakingModuleMaxDepositsCount(modulesIds[i], ETH(1000000 * 32))) + maxDepositsPerModule.push(maxCount) + } + return maxDepositsPerModule + } + }) + + describe('Report exited keys by module changes stake allocation', async () => { + before(async () => { + // add modules + await router.addStakingModule( + 'Module 1', + operators.address, + 10_000, // 100 % _targetShare + 500, // 10 % _moduleFee + 500, // 50 % _treasuryFee + { from: admin } + ) + module1Id = +(await router.getStakingModuleIds())[0] + + await router.addStakingModule( + 'Module 2', + module2.address, + 10_000, // 100 % _targetShare + 500, // 10 % _moduleFee + 500, // 50 % _treasuryFee + { from: admin } + ) + module2Id = +(await router.getStakingModuleIds())[1] + + // add operators + await operators.testing_addNodeOperator( + 'Operator1', + ADDRESS_1, // config.rewardAddress, + 100, // totalSigningKeysCount, + 60, // vettedSigningKeysCount, + 50, // depositedSigningKeysCount, + 0 // exitedSigningKeysCount + ) + await operators.testing_addNodeOperator( + 'Operator1', + ADDRESS_1, // config.rewardAddress, + 100, // totalSigningKeysCount, + 60, // vettedSigningKeysCount, + 50, // depositedSigningKeysCount, + 0 // exitedSigningKeysCount + ) + + await module2.testing_addNodeOperator( + 'Operator1', + ADDRESS_1, // config.rewardAddress, + 20, // totalSigningKeysCount, + 15, // vettedSigningKeysCount, + 10, // depositedSigningKeysCount, + 0 // exitedSigningKeysCount + ) + }) + + beforeEach(snapshot) + afterEach(revert) + + it('check initial keys of operators', async () => { + const moduleSummary1 = await router.getNodeOperatorSummary(module1Id, 0) + assert.equal(moduleSummary1.isTargetLimitActive, false) + assert.equal(moduleSummary1.targetValidatorsCount, 0) + assert.equal(moduleSummary1.stuckValidatorsCount, 0) + assert.equal(moduleSummary1.refundedValidatorsCount, 0) + assert.equal(moduleSummary1.stuckPenaltyEndTimestamp, 0) + assert.equal(moduleSummary1.totalExitedValidators, 0) + assert.equal(moduleSummary1.totalDepositedValidators, 50) + assert.equal(moduleSummary1.depositableValidatorsCount, 10) + + const moduleSummary2 = await router.getNodeOperatorSummary(module2Id, 0) + assert.equal(moduleSummary2.isTargetLimitActive, false) + assert.equal(moduleSummary2.targetValidatorsCount, 0) + assert.equal(moduleSummary2.stuckValidatorsCount, 0) + assert.equal(moduleSummary2.refundedValidatorsCount, 0) + assert.equal(moduleSummary2.stuckPenaltyEndTimestamp, 0) + assert.equal(moduleSummary2.totalExitedValidators, 0) + assert.equal(moduleSummary2.totalDepositedValidators, 10) + assert.equal(moduleSummary2.depositableValidatorsCount, 5) + }) + + it('report exited keys should change rewards distribution', async () => { + // check exited validators before + let moduleSummary1 = await router.getStakingModuleSummary(module1Id) + assert.equal(moduleSummary1.totalExitedValidators, 0) + assert.equal(moduleSummary1.totalDepositedValidators, 100) + assert.equal(moduleSummary1.depositableValidatorsCount, 20) + + let distribution + + const { + totalDepositedValidators: totalDepositedValidators1Before, + totalExitedValidators: totalExitedValidators1Before, + } = await router.getNodeOperatorSummary(module1Id, 0) + const { + totalDepositedValidators: totalDepositedValidators2Before, + totalExitedValidators: totalExitedValidators2Before, + } = await router.getNodeOperatorSummary(module1Id, 1) + + const totalActiveValidators1Before = totalDepositedValidators1Before - totalExitedValidators1Before + const totalActiveValidators2Before = totalDepositedValidators2Before - totalExitedValidators2Before + const totalActiveValidatorsBefore = totalActiveValidators1Before + totalActiveValidators2Before + + const op1shareBefore = totalActiveValidators1Before / totalActiveValidatorsBefore // should be 0.5 + const op2shareBefore = totalActiveValidators2Before / totalActiveValidatorsBefore // should be 0.5 + + assert.equal(op1shareBefore, 0.5) + assert.equal(op2shareBefore, 0.5) + + const sharesDistribute = ETH(1) + distribution = await operators.getRewardsDistribution(sharesDistribute) + assert.equal(+distribution.shares[0], op1shareBefore * sharesDistribute) + assert.equal(+distribution.shares[1], op2shareBefore * sharesDistribute) + + // //update exited validators + const exitValidatorsCount = 20 + await router.updateExitedValidatorsCountByStakingModule([module1Id], [exitValidatorsCount], { from: admin }) + + const nodeOpIds = [0] + const exitedValidatorsCounts = [exitValidatorsCount] + + const nodeOpIdsData = hexConcat(...nodeOpIds.map((i) => hex(i, 8))) + const keysData = hexConcat(...exitedValidatorsCounts.map((c) => hex(c, 16))) + + // report exited by module and node operator + await router.reportStakingModuleExitedValidatorsCountByNodeOperator(module1Id, nodeOpIdsData, keysData, { + from: admin, + }) + + moduleSummary1 = await router.getStakingModuleSummary(module1Id) + assert.equal(moduleSummary1.totalExitedValidators, exitValidatorsCount) + assert.equal(moduleSummary1.totalDepositedValidators, 100) + assert.equal(moduleSummary1.depositableValidatorsCount, 20) + + // get distribution after exited keys + const { + totalDepositedValidators: totalDepositedValidators1After, + totalExitedValidators: totalExitedValidators1After, + } = await router.getNodeOperatorSummary(module1Id, 0) + const { + totalDepositedValidators: totalDepositedValidators2After, + totalExitedValidators: totalExitedValidators2After, + } = await router.getNodeOperatorSummary(module1Id, 1) + + const totalActiveValidators1After = totalDepositedValidators1After - totalExitedValidators1After + const totalActiveValidators2After = totalDepositedValidators2After - totalExitedValidators2After + const totalActiveValidatorsAfter = totalActiveValidators1After + totalActiveValidators2After + + assert.notEqual(totalActiveValidatorsBefore, totalActiveValidatorsAfter) + assert.notEqual(totalActiveValidators1Before, totalActiveValidators1After) + assert.equal(totalDepositedValidators2Before, totalDepositedValidators2After) + + const op1shareAfter = totalActiveValidators1After / totalActiveValidatorsAfter // should be 0.375 + const op2shareAfter = totalActiveValidators2After / totalActiveValidatorsAfter // should be 0.625 + + assert.equal(op1shareAfter, 0.375) + assert.equal(op2shareAfter, 0.625) + + assert(op1shareBefore > op1shareAfter) + assert(op2shareBefore < op2shareAfter) + assert(op1shareBefore < op2shareAfter) + + distribution = await operators.getRewardsDistribution(sharesDistribute) + assert.equal(+distribution.shares[0], op1shareAfter * sharesDistribute) + assert.equal(+distribution.shares[1], op2shareAfter * sharesDistribute) + }) + + it('report exited keys without target limit should not change allocation', async () => { + // check exited validators before + let moduleSummary1 = await router.getStakingModuleSummary(module1Id) + assert.equal(moduleSummary1.totalExitedValidators, 0) + assert.equal(moduleSummary1.totalDepositedValidators, 100) + assert.equal(moduleSummary1.depositableValidatorsCount, 20) + + const maxDepositsPerModuleBefore = await maxDepositsPerModule() + assert.deepEqual([20, 5], maxDepositsPerModuleBefore) + + // //update exited validators + const exitValidatorsCount = 20 + await router.updateExitedValidatorsCountByStakingModule([module1Id], [exitValidatorsCount], { from: admin }) + + const nodeOpIds = [0] + const exitedValidatorsCounts = [exitValidatorsCount] + + const nodeOpIdsData = hexConcat(...nodeOpIds.map((i) => hex(i, 8))) + const keysData = hexConcat(...exitedValidatorsCounts.map((c) => hex(c, 16))) + + // report exited by module and node operator + await router.reportStakingModuleExitedValidatorsCountByNodeOperator(module1Id, nodeOpIdsData, keysData, { + from: admin, + }) + + moduleSummary1 = await router.getStakingModuleSummary(module1Id) + assert.equal(moduleSummary1.totalExitedValidators, exitValidatorsCount) + assert.equal(moduleSummary1.totalDepositedValidators, 100) + assert.equal(moduleSummary1.depositableValidatorsCount, 20) + + const maxDepositsPerModuleAfter = await maxDepositsPerModule() + assert.deepEqual(maxDepositsPerModuleBefore, maxDepositsPerModuleAfter) + }) + + it('report exited keys with target limit should change allocation', async () => { + // check exited validators before + const moduleSummary1Before = await router.getStakingModuleSummary(module1Id) + assert.equal(moduleSummary1Before.totalExitedValidators, 0) + assert.equal(moduleSummary1Before.totalDepositedValidators, 100) + assert.equal(moduleSummary1Before.depositableValidatorsCount, 20) + + let keyStats = await router.getNodeOperatorSummary(module1Id, 0) + assert.equals(keyStats.isTargetLimitActive, false) + assert.equals(keyStats.targetValidatorsCount, 0) + assert.equals(keyStats.totalExitedValidators, 0) + assert.equals(keyStats.totalDepositedValidators, 50) + assert.equals(keyStats.depositableValidatorsCount, 10) + + // get max allocation before set target limit + const maxDepositsPerModuleBefore = await maxDepositsPerModule() + assert.deepEqual([20, 5], maxDepositsPerModuleBefore) + + await operators.updateTargetValidatorsLimits(0, true, 50, { from: voting }) + + // + keyStats = await router.getNodeOperatorSummary(module1Id, 0) + assert.equals(keyStats.isTargetLimitActive, true) + assert.equals(keyStats.targetValidatorsCount, 50) + assert.equals(keyStats.totalExitedValidators, 0) + assert.equals(keyStats.totalDepositedValidators, 50) + assert.equals(keyStats.depositableValidatorsCount, 0) + + // check exited validators after + let moduleSummary1After = await router.getStakingModuleSummary(module1Id) + assert.equal(moduleSummary1After.totalExitedValidators, 0) + assert.equal(moduleSummary1After.totalDepositedValidators, 100) + assert.equal(moduleSummary1After.depositableValidatorsCount, 10) + + // decreases + const maxDepositsPerModuleAfter = await maxDepositsPerModule() + assert.deepEqual([10, 5], maxDepositsPerModuleAfter) + + // increase target limit 50 -> 55 + await operators.updateTargetValidatorsLimits(0, true, 55, { from: voting }) + keyStats = await router.getNodeOperatorSummary(module1Id, 0) + moduleSummary1After = await router.getStakingModuleSummary(module1Id) + + assert.equals(keyStats.depositableValidatorsCount, 5) + assert.equal(moduleSummary1After.depositableValidatorsCount, 15) + assert.deepEqual([15, 5], await maxDepositsPerModule()) + + // update exited validators + let exitValidatorsCount = 1 + await router.updateExitedValidatorsCountByStakingModule([module1Id], [exitValidatorsCount], { from: admin }) + + const nodeOpIds = [0] + let exitedValidatorsCounts = [exitValidatorsCount] + + const nodeOpIdsData = hexConcat(...nodeOpIds.map((i) => hex(i, 8))) + let keysData = hexConcat(...exitedValidatorsCounts.map((c) => hex(c, 16))) + + // report exited by module and node operator + await router.reportStakingModuleExitedValidatorsCountByNodeOperator(module1Id, nodeOpIdsData, keysData, { + from: admin, + }) + + // check allocation + keyStats = await router.getNodeOperatorSummary(module1Id, 0) + moduleSummary1After = await router.getStakingModuleSummary(module1Id) + + assert.equals(keyStats.depositableValidatorsCount, 6) + assert.equal(moduleSummary1After.depositableValidatorsCount, 16) + + const maxDepositsPerModuleAfterAlloc = await maxDepositsPerModule() + assert.deepEqual([16, 5], maxDepositsPerModuleAfterAlloc) + + // update next exited validators + exitValidatorsCount = 30 + exitedValidatorsCounts = [exitValidatorsCount] + keysData = hexConcat(...exitedValidatorsCounts.map((c) => hex(c, 16))) + + await router.updateExitedValidatorsCountByStakingModule([module1Id], [exitValidatorsCount], { from: admin }) + // report exited by module and node operator + await router.reportStakingModuleExitedValidatorsCountByNodeOperator(module1Id, nodeOpIdsData, keysData, { + from: admin, + }) + + // check allocation + keyStats = await router.getNodeOperatorSummary(module1Id, 0) + moduleSummary1After = await router.getStakingModuleSummary(module1Id) + + assert.equals(keyStats.depositableValidatorsCount, 10) // we can't change + assert.equal(moduleSummary1After.depositableValidatorsCount, 20) + + const maxDepositsPerModuleAfterReport = await maxDepositsPerModule() + assert.deepEqual([20, 5], maxDepositsPerModuleAfterReport) + + // small explanation: + // vetted - 60 keys + // deposited - 50 keys + // exited - 0 keys + // + // for allocation, we need to know how many keys are available for deposit - depositableKeys + // in common case, when targetLimit is not active `depositableKeys` = vetted - deposited + // + // but if targetLimit is active and targetLimit=50, then depositableKeys==0, + // because there are 50 active keys already. + // + // when we report exitedKeys=10, thats mean active keys decrease to 40 keys, and depositableKeys=10 now + // BUT depositableKeys cannot be more than vetted-deposited + // so if we report exitedKeys=10 depositableKeys should be still 10 + }) + + it('report stuck keys should not change rewards distribution, but return penalized table', async () => { + let distribution + + const { + totalDepositedValidators: totalDepositedValidators1Before, + totalExitedValidators: totalExitedValidators1Before, + } = await router.getNodeOperatorSummary(module1Id, 0) + const { + totalDepositedValidators: totalDepositedValidators2Before, + totalExitedValidators: totalExitedValidators2Before, + } = await router.getNodeOperatorSummary(module1Id, 1) + + const totalActiveValidators1Before = totalDepositedValidators1Before - totalExitedValidators1Before + const totalActiveValidators2Before = totalDepositedValidators2Before - totalExitedValidators2Before + const totalActiveValidatorsBefore = totalActiveValidators1Before + totalActiveValidators2Before + + const op1shareBefore = totalActiveValidators1Before / totalActiveValidatorsBefore // should be 0.5 + const op2shareBefore = totalActiveValidators2Before / totalActiveValidatorsBefore // should be 0.5 + + assert.equal(op1shareBefore, 0.5) + assert.equal(op2shareBefore, 0.5) + + const sharesDistribute = ETH(1) + distribution = await operators.getRewardsDistribution(sharesDistribute) + assert.equal(+distribution.shares[0], op1shareBefore * sharesDistribute) + assert.equal(+distribution.shares[1], op2shareBefore * sharesDistribute) + + // update stuck validators + const stuckValidatorsCount = 1 + + const nodeOpIds = [0] + const exitedValidatorsCounts = [stuckValidatorsCount] + + const nodeOpIdsData = hexConcat(...nodeOpIds.map((i) => hex(i, 8))) + const keysData = hexConcat(...exitedValidatorsCounts.map((c) => hex(c, 16))) + + // report stuck by module and node operator + await router.reportStakingModuleStuckValidatorsCountByNodeOperator(module1Id, nodeOpIdsData, keysData, { + from: admin, + }) + + // get distribution after exited keys + const { + totalDepositedValidators: totalDepositedValidators1After, + totalExitedValidators: totalExitedValidators1After, + } = await router.getNodeOperatorSummary(module1Id, 0) + const { + totalDepositedValidators: totalDepositedValidators2After, + totalExitedValidators: totalExitedValidators2After, + } = await router.getNodeOperatorSummary(module1Id, 1) + + const totalActiveValidators1After = totalDepositedValidators1After - totalExitedValidators1After + const totalActiveValidators2After = totalDepositedValidators2After - totalExitedValidators2After + const totalActiveValidatorsAfter = totalActiveValidators1After + totalActiveValidators2After + + assert.equal(totalActiveValidatorsBefore, totalActiveValidatorsAfter) + assert.equal(totalActiveValidators1Before, totalActiveValidators1After) + assert.equal(totalDepositedValidators2Before, totalDepositedValidators2After) + + const op1shareAfter = totalActiveValidators1After / totalActiveValidatorsAfter + const op2shareAfter = totalActiveValidators2After / totalActiveValidatorsAfter + + // when penalized shares still the same + assert.equal(op1shareBefore, op1shareAfter) + assert.equal(op2shareBefore, op2shareAfter) + + distribution = await operators.getRewardsDistribution(sharesDistribute) + assert.deepEqual([+distribution.shares[0], distribution.penalized[0]], [op1shareAfter * sharesDistribute, true]) + assert.deepEqual([+distribution.shares[1], distribution.penalized[1]], [op2shareAfter * sharesDistribute, false]) + }) + + it.skip('report stuck keys should not affect stake allocation', async () => { + // get max allocation before + const maxDepositsPerModuleBefore = await maxDepositsPerModule() + assert.deepEqual([20, 5], maxDepositsPerModuleBefore) + + // update stuck validators + const stuckValidatorsCount = 20 + + const nodeOpIds = [0] + const exitedValidatorsCounts = [stuckValidatorsCount] + + const nodeOpIdsData = hexConcat(...nodeOpIds.map((i) => hex(i, 8))) + const keysData = hexConcat(...exitedValidatorsCounts.map((c) => hex(c, 16))) + + // report exited by module and node operator + await router.reportStakingModuleStuckValidatorsCountByNodeOperator(module1Id, nodeOpIdsData, keysData, { + from: admin, + }) + + const maxDepositsPerModuleAfter = await maxDepositsPerModule() + assert.deepEqual(maxDepositsPerModuleBefore, maxDepositsPerModuleAfter) + }) + }) +}) diff --git a/test/helpers/staking-modules.js b/test/helpers/staking-modules.js index ec9ee3905..edc4ecce9 100644 --- a/test/helpers/staking-modules.js +++ b/test/helpers/staking-modules.js @@ -87,6 +87,13 @@ async function setupNodeOperatorsRegistry({ dao, acl, lidoLocator, stakingRouter { from: appManager.address } ) + await acl.grantPermission( + stakingRouter.address, + nodeOperatorsRegistry.address, + NODE_OPERATOR_REGISTRY_MANAGE_NODE_OPERATOR_ROLE, + { from: appManager.address } + ) + return nodeOperatorsRegistry } From ea60b63ec8d6d59fca47334ddfca275cc5d934e6 Mon Sep 17 00:00:00 2001 From: Logachev Nikita Date: Wed, 1 Mar 2023 01:40:33 +0700 Subject: [PATCH 070/236] update skipped test --- .../0.8.9/staking-router/report-exited-keys.test.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/staking-router/report-exited-keys.test.js b/test/0.8.9/staking-router/report-exited-keys.test.js index d3a738827..ff34a0db7 100644 --- a/test/0.8.9/staking-router/report-exited-keys.test.js +++ b/test/0.8.9/staking-router/report-exited-keys.test.js @@ -421,11 +421,15 @@ contract('StakingRouter', ([admin, depositor]) => { assert.deepEqual([+distribution.shares[1], distribution.penalized[1]], [op2shareAfter * sharesDistribute, false]) }) - it.skip('report stuck keys should not affect stake allocation', async () => { + it('report stuck keys should not affect stake allocation', async () => { // get max allocation before const maxDepositsPerModuleBefore = await maxDepositsPerModule() assert.deepEqual([20, 5], maxDepositsPerModuleBefore) + const moduleSummary1Before = await router.getNodeOperatorSummary(module1Id, 0) + assert.equal(moduleSummary1Before.stuckValidatorsCount, 0) + assert.equal(moduleSummary1Before.depositableValidatorsCount, 10) + // update stuck validators const stuckValidatorsCount = 20 @@ -440,8 +444,13 @@ contract('StakingRouter', ([admin, depositor]) => { from: admin, }) + // we remove allocation from operator, if he has stuck keys const maxDepositsPerModuleAfter = await maxDepositsPerModule() - assert.deepEqual(maxDepositsPerModuleBefore, maxDepositsPerModuleAfter) + assert.deepEqual([10, 5], maxDepositsPerModuleAfter) + + const moduleSummary1After = await router.getNodeOperatorSummary(module1Id, 0) + assert.equal(moduleSummary1After.stuckValidatorsCount, 20) + assert.equal(moduleSummary1After.depositableValidatorsCount, 0) }) }) }) From 7f7980aed0966649f28dedc6bbd9d6f562c16d1a Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 28 Feb 2023 11:09:17 +0300 Subject: [PATCH 071/236] fix: naming fixes within sanity checker contract --- .../0.8.9/sanity_checks/OracleReportSanityChecker.sol | 8 ++++---- lib/abi/OracleReportSanityChecker.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index e402b19ba..297fa8402 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -531,9 +531,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { function _checkSharesRequestedToBurn(uint256 _sharesRequestedToBurn) internal view { (uint256 coverShares, uint256 nonCoverShares) = IBurner(LIDO_LOCATOR.burner()).getSharesRequestedToBurn(); - uint256 actualBurnerRequests = coverShares + nonCoverShares; - if (_sharesRequestedToBurn > actualBurnerRequests) { - revert IncorrectBurnerRequests(actualBurnerRequests); + uint256 actualSharesToBurn = coverShares + nonCoverShares; + if (_sharesRequestedToBurn > actualSharesToBurn) { + revert IncorrectSharesRequestedToBurn(actualSharesToBurn); } } @@ -695,7 +695,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { error IncorrectLimitValue(uint256 value, uint256 maxAllowedValue); error IncorrectWithdrawalsVaultBalance(uint256 actualWithdrawalVaultBalance); error IncorrectELRewardsVaultBalance(uint256 actualELRewardsVaultBalance); - error IncorrectBurnerRequests(uint256 actualBurnerRequests); + error IncorrectSharesRequestedToBurn(uint256 actualSharesToBurn); error IncorrectCLBalanceDecrease(uint256 oneOffCLBalanceDecreaseBP); error IncorrectCLBalanceIncrease(uint256 annualBalanceDiff); error IncorrectAppearedValidators(uint256 churnLimit); diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index a824c32f6..db7f6a9b8 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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"actualBurnerRequests","type":"uint256"}],"name":"IncorrectBurnerRequests","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"actualSharesToBurn","type":"uint256"}],"name":"IncorrectSharesRequestedToBurn","type":"error"},{"inputs":[{"internalType":"uint256","name":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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 081273829e3365974c6b9a0f3ff4151acf0e2697 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 28 Feb 2023 11:11:08 +0300 Subject: [PATCH 072/236] chore: remove extra awaits --- .../lido_rewards_distribution_math.test.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/scenario/lido_rewards_distribution_math.test.js b/test/scenario/lido_rewards_distribution_math.test.js index c4a73c3cb..4fb0ccf27 100644 --- a/test/scenario/lido_rewards_distribution_math.test.js +++ b/test/scenario/lido_rewards_distribution_math.test.js @@ -729,10 +729,10 @@ contract('Lido: rewards distribution math', (addresses) => { const rewardsAmount = ETH(1) const newBeaconBalance = totalPooledEtherBefore.sub(bufferedBefore).add(toBN(rewardsAmount)) - const treasurySharesBefore = await await token.sharesOf(treasuryAddr) - const nodeOperator1SharesBefore = await await token.sharesOf(nodeOperator1.address) - const nodeOperator2SharesBefore = await await token.sharesOf(nodeOperator2.address) - const nodeOperator3SharesBefore = await await token.sharesOf(nodeOperator3.address) + const treasurySharesBefore = await token.sharesOf(treasuryAddr) + const nodeOperator1SharesBefore = await token.sharesOf(nodeOperator1.address) + const nodeOperator2SharesBefore = await token.sharesOf(nodeOperator2.address) + const nodeOperator3SharesBefore = await token.sharesOf(nodeOperator3.address) await reportBeacon(3, newBeaconBalance) @@ -786,10 +786,10 @@ contract('Lido: rewards distribution math', (addresses) => { await stakingRouter.setStakingModuleStatus(firstModule.id, StakingModuleStatus.Stopped, { from: voting }) - const treasurySharesBefore = await await token.sharesOf(treasuryAddr) - const nodeOperator1SharesBefore = await await token.sharesOf(nodeOperator1.address) - const nodeOperator2SharesBefore = await await token.sharesOf(nodeOperator2.address) - const nodeOperator3SharesBefore = await await token.sharesOf(nodeOperator3.address) + const treasurySharesBefore = await token.sharesOf(treasuryAddr) + const nodeOperator1SharesBefore = await token.sharesOf(nodeOperator1.address) + const nodeOperator2SharesBefore = await token.sharesOf(nodeOperator2.address) + const nodeOperator3SharesBefore = await token.sharesOf(nodeOperator3.address) await reportBeacon(3, newBeaconBalance) @@ -828,10 +828,10 @@ contract('Lido: rewards distribution math', (addresses) => { await stakingRouter.setStakingModuleStatus(secondModule.id, StakingModuleStatus.Stopped, { from: voting }) - const treasurySharesBefore = await await token.sharesOf(treasuryAddr) - const nodeOperator1SharesBefore = await await token.sharesOf(nodeOperator1.address) - const nodeOperator2SharesBefore = await await token.sharesOf(nodeOperator2.address) - const nodeOperator3SharesBefore = await await token.sharesOf(nodeOperator3.address) + const treasurySharesBefore = await token.sharesOf(treasuryAddr) + const nodeOperator1SharesBefore = await token.sharesOf(nodeOperator1.address) + const nodeOperator2SharesBefore = await token.sharesOf(nodeOperator2.address) + const nodeOperator3SharesBefore = await token.sharesOf(nodeOperator3.address) await reportBeacon(3, newBeaconBalance) From 7622ad55dcecc948dcbe3a8ad4210da255ac1507 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 28 Feb 2023 11:11:50 +0300 Subject: [PATCH 073/236] test: refactor handle-oracle-report test --- test/0.4.24/lido-handle-oracle-report.test.js | 355 +++++++++++++++--- 1 file changed, 307 insertions(+), 48 deletions(-) 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 e10672daa..08ba6f238 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1,7 +1,7 @@ const { artifacts, contract, ethers } = require('hardhat') const { assert } = require('../helpers/assert') -const { ETH, toBN, genKeys, StETH, calcSharesMintedAsFees } = require('../helpers/utils') +const { shareRate, ETH, toBN, genKeys, StETH, calcSharesMintedAsFees } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') const { EvmSnapshot, setBalance } = require('../helpers/blockchain') const { ZERO_ADDRESS, INITIAL_HOLDER } = require('../helpers/constants') @@ -23,6 +23,18 @@ const ORACLE_REPORT_LIMITS_BOILERPLATE = { maxPositiveTokenRebase: 1000000000, } +const DEFAULT_LIDO_ORACLE_REPORT = { + reportTimestamp: 0, // uint256, seconds + timeElapsed: 0, // uint256, seconds + clValidators: 0, // uint256, counter + postCLBalance: ETH(0), // uint256, wei + withdrawalVaultBalance: ETH(0), // uint256, wei + elRewardsVaultBalance: ETH(0), // uint256, wei + sharesRequestedToBurn: StETH(0), // uint256, wad + withdrawalFinalizationBatches: [], // uint256[], indexes + simulatedShareRate: shareRate(0), // uint256, 10e27 +} + const checkEvents = async ({ tx, reportTimestamp = 0, @@ -212,16 +224,22 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another } it('handleOracleReport access control', async () => { - await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, [], 0, { from: stranger }), 'APP_AUTH_FAILED') + await assert.reverts( + lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: stranger }), + 'APP_AUTH_FAILED' + ) }) - it('handleOracleReport reverts whe protocol stopped', async () => { + it('handleOracleReport reverts when protocol is 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') + await assert.reverts( + lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: stranger }), + 'CONTRACT_IS_STOPPED' + ) }) it('zero report should do nothing', async () => { - const tx = await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, [], 0, { from: oracle }) + const tx = await lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -252,7 +270,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another describe('clBalance', () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -265,7 +283,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit without rewards', async () => { - const tx = await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, [], 0, { from: oracle }) + const tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 1, postCLBalance: ETH(32) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 0, @@ -295,7 +316,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit with rewards', async () => { - const tx = await lido.handleOracleReport(0, ONE_YEAR, 1, ETH(33), 0, 0, 0, [], 0, { from: oracle }) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 1, + postCLBalance: ETH(33), + }), + { from: oracle } + ) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) await checkEvents({ tx, @@ -329,41 +358,60 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another describe('sanity checks', async () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) }) it('reverts on reported more than deposited', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 4, 0, 0, 0, 0, [], 0, { from: oracle }), + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 4 }), { from: oracle }), 'REPORTED_MORE_DEPOSITED' ) }) it('reverts on reported less than reported previously', async () => { - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await assert.reverts( - lido.handleOracleReport(0, 0, 2, 0, 0, 0, 0, [], 0, { from: oracle }), + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 2 }), { from: oracle }), 'REPORTED_LESS_VALIDATORS' ) }) it('withdrawal vault balance check', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, [], 0, { from: oracle }), + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, withdrawalVaultBalance: 1 }), { + from: oracle, + }), 'IncorrectWithdrawalsVaultBalance(0)' ) }) - it('withdrawal vault balance check 2', async () => { + it('execution layer rewards vault balance check', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, [], 0, { from: oracle }), - 'IncorrectWithdrawalsVaultBalance(0)' + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, elRewardsVaultBalance: 1 }), { + from: oracle, + }), + 'IncorrectELRewardsVaultBalance(0)' + ) + }) + + it('burner shares to burn check', async () => { + await assert.reverts( + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, sharesRequestedToBurn: 1 }), { + from: oracle, + }), + 'IncorrectSharesRequestedToBurn(0)' ) }) it('does not revert on new total balance stay the same', async () => { - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) + let tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 0, @@ -389,7 +437,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) + tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 3, @@ -421,7 +472,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) + let tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 0, @@ -447,7 +501,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, [], 0, { from: oracle }) + tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(95.04) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 3, @@ -480,7 +537,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -491,7 +551,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, [], 0, { from: oracle }), + lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(95.03) }), + { from: oracle } + ), 'IncorrectCLBalanceDecrease(101)' ) }) @@ -506,7 +569,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -516,7 +582,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - const tx = await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, [], 0, { from: oracle }) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.96), + }), + { from: oracle } + ) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.96), 10, 100, ETH(100), ETH(100.96)) await checkEvents({ tx, @@ -556,7 +630,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, [], 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -567,7 +644,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, [], 0, { from: oracle }), + lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.97), + }), + { from: oracle } + ), 'IncorrectCLBalanceIncrease(101)' ) }) @@ -584,7 +669,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 100, ETH(3200), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 100, + postCLBalance: ETH(3200), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 100, beaconValidators: 100, beaconBalance: ETH(3200) }) }) @@ -600,7 +693,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) await assert.reverts( - lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }), + lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 101, + postCLBalance: ETH(3200), + }), + { from: oracle, gasPrice: 1 } + ), 'IncorrectAppearedValidators(101)' ) }) @@ -608,7 +709,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another describe('smooth report', async () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -628,7 +729,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(97), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(97) }) }) @@ -640,7 +749,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(100), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(100), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(100) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(4), @@ -663,7 +780,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -687,7 +813,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1.1), 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -712,7 +847,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1), 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -738,7 +882,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { 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 lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(95.5), + elRewardsVaultBalance: ETH(1.5), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.5) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -763,7 +916,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1.1), 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -787,7 +949,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { 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 lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.9), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ @@ -813,7 +984,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { 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 lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -829,7 +1009,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) describe('daily reports', () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -851,7 +1031,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(1.1), 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -872,7 +1061,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.0027), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.0027), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.0027) }) }) @@ -885,7 +1082,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96 + 0.0028), 0, 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.0028), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96 + clIncrease) }) assert( 0.00014 + 0.0028 * 0.9 * 0.3 + 0.0028 * 0.9 * 0.69 + 0.0028 * 0.01 * 0.9 + 0.00014 === clIncrease, @@ -912,7 +1117,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1), 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -936,7 +1150,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1.1), 0, 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -961,7 +1184,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1), 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -987,7 +1219,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(95.5), 0, ETH(1.5), 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(95.5), + elRewardsVaultBalance: ETH(1.5), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.5) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -1012,7 +1253,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1.1), 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -1036,7 +1286,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(0.9), 0, [], 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.9), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ From ff168dc424276b8800490ba299777642aa3253d6 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 00:52:48 +0300 Subject: [PATCH 074/236] test: implement utils for handleOracleReport tests --- test/helpers/utils.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/helpers/utils.js b/test/helpers/utils.js index f72e879c9..1474a0ecd 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -119,6 +119,41 @@ const calcSharesMintedAsFees = (rewards, fee, feePoints, prevTotalShares, newTot ) } +const limitRebase = (limitE9, preTotalPooledEther, preTotalShares, clBalanceUpdate, elBalanceUpdate, sharesToBurn) => { + const bnE9 = toBN(e9(1)) + + let accumulatedRebase = toBN(0) + const clRebase = toBN(clBalanceUpdate).mul(bnE9).div(toBN(preTotalPooledEther)) + accumulatedRebase = accumulatedRebase.add(clRebase) + if (limitE9.lte(accumulatedRebase)) { + return { elBalanceUpdate: 0, sharesToBurn: 0 } + } + + let remainLimit = limitE9.sub(accumulatedRebase) + const remainEther = remainLimit.mul(toBN(preTotalPooledEther)).div(bnE9) + if (remainEther.lte(toBN(elBalanceUpdate))) { + return { elBalanceUpdate: remainEther, sharesToBurn: 0 } + } + + const elRebase = toBN(elBalanceUpdate).mul(bnE9).div(toBN(preTotalPooledEther)) + accumulatedRebase = accumulatedRebase.add(elRebase) + remainLimit = toBN(limitE9).sub(accumulatedRebase) + + const remainShares = remainLimit.mul(toBN(preTotalShares)).div(bnE9.add(remainLimit)) + + if (remainShares.lte(toBN(sharesToBurn))) { + return { elBalanceUpdate, sharesToBurn: remainShares } + } + + return { elBalanceUpdate, sharesToBurn } +} + +const calcShareRateDeltaE27 = (preTotalPooledEther, postTotalPooledEther, preTotalShares, postTotalShares) => { + const oldShareRateE27 = toBN(e27(1)).mul(toBN(preTotalPooledEther)).div(toBN(preTotalShares)) + const newShareRatesE27 = toBN(e27(1)).mul(toBN(postTotalPooledEther)).div(toBN(postTotalShares)) + return newShareRatesE27.sub(oldShareRateE27) +} + function getFirstEventArgs(receipt, eventName, abi = undefined) { const events = getEvents(receipt, eventName, { decodeForAbi: abi }) chai.assert(events.length !== 0, () => `Expected event ${eventName} wasn't emitted`) @@ -152,4 +187,6 @@ module.exports = { prepIdsCountsPayload, calcSharesMintedAsFees, getFirstEventArgs, + calcShareRateDeltaE27, + limitRebase, } From a34c5425a455a777faab7fe2b24ce03966741404 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 00:55:08 +0300 Subject: [PATCH 075/236] test: assign REQUEST_BURN_SHARES_ROLE in factory --- test/helpers/factories.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index bedf0d187..4a277e0d3 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -297,13 +297,15 @@ async function guardiansFactory({ deployParams }) { async function burnerFactory({ appManager, treasury, pool, voting }) { const burner = await Burner.new(appManager.address, treasury.address, pool.address, 0, 0) - const [REQUEST_BURN_MY_STETH_ROLE, RECOVER_ASSETS_ROLE] = await Promise.all([ + const [REQUEST_BURN_MY_STETH_ROLE, REQUEST_BURN_SHARES_ROLE, RECOVER_ASSETS_ROLE] = await Promise.all([ burner.REQUEST_BURN_MY_STETH_ROLE(), + burner.REQUEST_BURN_SHARES_ROLE(), burner.RECOVER_ASSETS_ROLE(), ]) await burner.grantRole(REQUEST_BURN_MY_STETH_ROLE, voting.address, { from: appManager.address }) await burner.grantRole(RECOVER_ASSETS_ROLE, voting.address, { from: appManager.address }) + await burner.grantRole(REQUEST_BURN_SHARES_ROLE, voting.address, { from: appManager.address }) return burner } From 32dcef079c1c8f66945d9746a77264292d5ce5cd Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 00:55:51 +0300 Subject: [PATCH 076/236] test: handleOracleReport with shares burning --- test/0.4.24/lido-handle-oracle-report.test.js | 401 +++++++++++++++++- 1 file changed, 395 insertions(+), 6 deletions(-) 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 08ba6f238..df5679741 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1,7 +1,17 @@ const { artifacts, contract, ethers } = require('hardhat') const { assert } = require('../helpers/assert') -const { shareRate, ETH, toBN, genKeys, StETH, calcSharesMintedAsFees } = require('../helpers/utils') +const { + e9, + shareRate, + ETH, + toBN, + genKeys, + StETH, + calcSharesMintedAsFees, + calcShareRateDeltaE27, + limitRebase, +} = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') const { EvmSnapshot, setBalance } = require('../helpers/blockchain') const { ZERO_ADDRESS, INITIAL_HOLDER } = require('../helpers/constants') @@ -97,8 +107,8 @@ const checkEvents = async ({ ) } -contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, anotherStranger, depositor, operator]) => { - let deployed, snapshot, lido, treasury, voting, oracle +contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anotherStranger, depositor, operator]) => { + let deployed, snapshot, lido, treasury, voting, oracle, burner let curatedModule, oracleReportSanityChecker, elRewardsVault let withdrawalVault let strangerBalanceBefore, @@ -137,6 +147,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another await curatedModule.setNodeOperatorStakingLimit(0, keysAmount, { from: deployed.voting.address }) lido = deployed.pool + burner = deployed.burner treasury = deployed.treasury.address voting = deployed.voting.address oracle = deployed.oracle.address @@ -268,7 +279,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) }) - describe('clBalance', () => { + describe('clBalance', async () => { beforeEach(async () => { await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) @@ -340,7 +351,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another preTotalEther: ETH(100), postTotalShares: toBN(ETH(100)).add(sharesMintedAsFees).toString(), postTotalEther: ETH(101), - sharesMintedAsFees, + sharesMintedAsFees: sharesMintedAsFees.toString(), }) await checkStat({ depositedValidators: 3, beaconValidators: 1, beaconBalance: ETH(33) }) @@ -1006,8 +1017,306 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.2)) }) + + it('does not smooth shares to burn if report in limit with shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + + const sharesToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + sharesRequestedToBurn: sharesToBurn, + }), + { from: oracle, gasPrice: 1 } + ) + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0), + postBufferedEther: ETH(5), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: toBN(ETH(101)).sub(sharesToBurn).toString(), + postTotalEther: ETH(101), + sharesMintedAsFees: 0, + }) + + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), // bob's deposit + treasuryBalanceDiff: ETH(0), // no rewards reported + strangerBalanceDiff: ETH(0.3), // though, bob has sacrificed stETH shares for all users + anotherStrangerBalanceDiff: ETH(0.69), + curatedModuleBalanceDiff: ETH(0), // no rewards reported + initialHolderBalanceDiff: ETH(0.01), + }) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(coverShares.add(nonCoverShares), StETH(0)) + assert.equals(await lido.balanceOf(burner.address), StETH(0)) + }) + + it('smooth shares to burn if report in limit without shares and no fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.5)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(0.5), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0), + ETH(0.5), + sharesRequestedToBurn + ) + + const postTotalShares = toBN(ETH(101)).sub(toBN(sharesToBurn)) + const postTotalEther = toBN(ETH(101)).add(toBN(elBalanceUpdate)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.5), + postBufferedEther: ETH(5.5), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: 0, // no rewards on CL side => no minted fee + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: ETH(0), // no fee minted + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), // though, bob has sacrificed stETH shares for all users + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: ETH(0), // no fee minted + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) + }) + + it('smooth shares to burn if report in limit without shares and fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.4)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.4), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(0.4), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.5), 10, 100, ETH(101), postTotalEther) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.4), + postBufferedEther: ETH(5.4), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), // no rewards on CL side => no minted fee + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) + }) + + it('postpone all shares to burn if report out of limit even without shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(4.9)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(4.9), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(4.9), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees( + toBN(ETH(0.1)).add(elBalanceUpdate), + 10, + 100, + ETH(101), + postTotalEther + ) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: elBalanceUpdate.toString(), + postBufferedEther: toBN(ETH(5)).add(elBalanceUpdate).toString(), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: toBN(ETH(1.1)).add(elBalanceUpdate), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), toBN(ETH(4.9)).sub(elBalanceUpdate)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesToBurn, 0) + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + assert.equals(await lido.balanceOf(burner.address), await lido.getPooledEthByShares(sharesRequestedToBurn)) + }) }) - describe('daily reports', () => { + + describe('daily reports', async () => { beforeEach(async () => { await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) @@ -1309,5 +1618,85 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.1)) }) + + it.skip('does not smooth shares to burn if report in limit with shares', async () => { + // TODO + }) + + it.skip('smooth shares to burn if report in limit without shares', async () => { + // TODO + }) + + it.skip('postpone all shares to burn if report out of limit without shares', async () => { + // TODO + }) + }) + + describe('reports with withdrawals finalization', () => { + beforeEach(async () => { + 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, + initialHolderBalanceDiff: 0, + }) + }) + + it('dry-run eth_call works and returns proper values', async () => { + await setBalance(elRewardsVault, ETH(0.5)) + await setBalance(withdrawalVault, ETH(0.5)) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + churnValidatorsPerDayLimit: 100, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + + const [postTotalPooledEther, postTotalShares, withdrawals, elRewards] = await lido.handleOracleReport.call( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.5), + withdrawalVaultBalance: ETH(0.5), + }), + { from: oracle, gasPrice: 1 } + ) + + await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: ETH(0) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(0), + treasuryBalanceDiff: ETH(0), + strangerBalanceDiff: ETH(0), + anotherStrangerBalanceDiff: ETH(0), + curatedModuleBalanceDiff: ETH(0), + initialHolderBalanceDiff: ETH(0), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.5)) + assert.equals(await ethers.provider.getBalance(withdrawalVault), ETH(0.5)) + + const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) + + assert.equals(postTotalPooledEther, ETH(101)) + assert.equals(postTotalShares, toBN(ETH(100)).add(sharesMintedAsFees)) + assert.equals(withdrawals, ETH(0.5)) + assert.equals(elRewards, ETH(0.4)) + }) + + it.skip('withdrawal finalization works after dry-run call', async () => { + // TODO + }) + + it.skip('check simulated share rate correctness when limit is higher due to withdrawals', async () => { + // TODO + }) }) }) From cf9f3265db74ac0f65b91cc12f4b0b256ddb4ab8 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 01:03:45 +0300 Subject: [PATCH 077/236] chore: minor contract updates --- contracts/0.4.24/Lido.sol | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index fe34812b2..4b6b76dfe 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -1217,11 +1217,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { } } - uint256 withdrawals; - uint256 elRewards; - // Step 4. // Pass the accounting values to sanity checker to smoothen positive token rebase + + uint256 withdrawals; + uint256 elRewards; ( withdrawals, elRewards, reportContext.simulatedSharesToBurn, reportContext.sharesToBurn ) = IOracleReportSanityChecker(contracts.oracleReportSanityChecker).smoothenTokenRebase( @@ -1272,14 +1272,11 @@ contract Lido is Versioned, StETHPermit, AragonApp { _burnShares(contracts.burner, reportContext.sharesToBurn); } - uint256 postTotalShares; - uint256 postTotalPooledEther; - // Step 8. // Complete token rebase by informing observers (emit an event and call the external receivers if any) ( - postTotalShares, - postTotalPooledEther + uint256 postTotalShares, + uint256 postTotalPooledEther ) = _completeTokenRebase( _reportedData, reportContext, From 8c345bc766d3a3ec685ec17d961cee6928644045 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 1 Mar 2023 16:37:45 +0700 Subject: [PATCH 078/236] feat: adopted OZ tests for AccessControl --- .../AccessControlEnumerableMock.sol | 21 ++ .../utils/access-control-enumerable.test.js | 218 ++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 contracts/0.8.9/test_helpers/AccessControlEnumerableMock.sol create mode 100644 test/0.8.9/utils/access-control-enumerable.test.js diff --git a/contracts/0.8.9/test_helpers/AccessControlEnumerableMock.sol b/contracts/0.8.9/test_helpers/AccessControlEnumerableMock.sol new file mode 100644 index 000000000..c8e5b8487 --- /dev/null +++ b/contracts/0.8.9/test_helpers/AccessControlEnumerableMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (access/AccessControlEnumerable.sol) +// +// Mock contract for AccessControlEnumerable. Copied from tree: +// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/6bd6b76d1156e20e45d1016f355d154141c7e5b9/contracts/mocks/AccessControlEnumerableMock.sol +// +pragma solidity 0.8.9; + +import "../utils/access/AccessControlEnumerable.sol"; + +contract AccessControlEnumerableMock is AccessControlEnumerable { + constructor() { + _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); + } + + function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) public { + _setRoleAdmin(roleId, adminRoleId); + } + + function senderProtected(bytes32 roleId) public onlyRole(roleId) {} +} diff --git a/test/0.8.9/utils/access-control-enumerable.test.js b/test/0.8.9/utils/access-control-enumerable.test.js new file mode 100644 index 000000000..84b18dc57 --- /dev/null +++ b/test/0.8.9/utils/access-control-enumerable.test.js @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 +// +// Adopted AccessControl tests from: +// https://github.com/OpenZeppelin/openzeppelin-contracts/tree/dad73159df3d3053c72b5e430fa8164330f18068/test/access +// + +const { makeInterfaceId } = require('@openzeppelin/test-helpers') +const { artifacts, contract, web3, ethers } = require('hardhat') + +const { assert } = require('../../helpers/assert') +const { EvmSnapshot } = require('../../helpers/blockchain') + +const AccessControlEnumerableMock = artifacts.require('AccessControlEnumerableMock.sol') + +const DEFAULT_ADMIN_ROLE = '0x0000000000000000000000000000000000000000000000000000000000000000' +const ROLE = web3.utils.soliditySha3('ROLE') +const OTHER_ROLE = web3.utils.soliditySha3('OTHER_ROLE') + +const AccessControlInterface = [ + 'hasRole(bytes32,address)', + 'getRoleAdmin(bytes32)', + 'grantRole(bytes32,address)', + 'revokeRole(bytes32,address)', + 'renounceRole(bytes32,address)', +] + +const AccessControlEnumerableInterface = [ + 'hasRole(bytes32,address)', + 'getRoleAdmin(bytes32)', + 'grantRole(bytes32,address)', + 'revokeRole(bytes32,address)', + 'renounceRole(bytes32,address)', +] + +const deployAccessControlEnumerable = async ({ owner }) => { + const ac = await AccessControlEnumerableMock.new({ from: owner }) + return ac +} + +contract('AccessControlEnumerable', ([admin, authorized, other, otherAdmin, otherAuthorized]) => { + let ac + const snapshot = new EvmSnapshot(ethers.provider) + + before('deploy', async () => { + ac = await deployAccessControlEnumerable({ admin }) + await snapshot.make() + }) + + afterEach(async () => { + await snapshot.rollback() + }) + + it('supports interfaces', async () => { + assert(await ac.supportsInterface(makeInterfaceId.ERC165(AccessControlInterface))) + assert(await ac.supportsInterface(makeInterfaceId.ERC165(AccessControlEnumerableInterface))) + }) + + describe('default admin', function () { + it('deployer has default admin role', async function () { + assert(await ac.hasRole(DEFAULT_ADMIN_ROLE, admin)) + }) + + it("other roles's admin is the default admin role", async function () { + assert.equals(await ac.getRoleAdmin(admin), DEFAULT_ADMIN_ROLE) + }) + + it("default admin role's admin is itself", async function () { + assert.equals(await ac.getRoleAdmin(DEFAULT_ADMIN_ROLE), DEFAULT_ADMIN_ROLE) + }) + }) + + describe('granting', function () { + beforeEach(async function () { + await ac.grantRole(ROLE, authorized, { from: admin }) + }) + + it('non-admin cannot grant role to other accounts', async function () { + await assert.reverts( + ac.grantRole(ROLE, authorized, { from: other }), + `AccessControl: account ${other.toLowerCase()} is missing role ${DEFAULT_ADMIN_ROLE}` + ) + }) + + it('accounts can be granted a role multiple times', async function () { + await ac.grantRole(ROLE, authorized, { from: admin }) + const receipt = await ac.grantRole(ROLE, authorized, { from: admin }) + assert.notEmits(receipt, 'RoleGranted') + }) + }) + + describe('renouncing', function () { + it('roles that are not had can be renounced', async function () { + const receipt = await ac.renounceRole(ROLE, authorized, { from: authorized }) + assert.notEmits(receipt, 'RoleRevoked') + }) + + context('with granted role', function () { + beforeEach(async function () { + await ac.grantRole(ROLE, authorized, { from: admin }) + }) + + it('bearer can renounce role', async function () { + const receipt = await ac.renounceRole(ROLE, authorized, { from: authorized }) + assert.emits(receipt, 'RoleRevoked', { account: authorized, role: ROLE, sender: authorized }) + + assert(!(await ac.hasRole(ROLE, authorized))) + }) + + it('only the sender can renounce their roles', async function () { + await assert.reverts( + ac.renounceRole(ROLE, authorized, { from: admin }), + 'AccessControl: can only renounce roles for self' + ) + }) + + it('a role can be renounced multiple times', async function () { + await ac.renounceRole(ROLE, authorized, { from: authorized }) + + const receipt = await ac.renounceRole(ROLE, authorized, { from: authorized }) + assert.notEmits(receipt, 'RoleRevoked') + }) + }) + }) + + describe('setting role admin', function () { + beforeEach(async function () { + const receipt = await ac.setRoleAdmin(ROLE, OTHER_ROLE) + assert.emits(receipt, 'RoleAdminChanged', { + role: ROLE, + previousAdminRole: DEFAULT_ADMIN_ROLE, + newAdminRole: OTHER_ROLE, + }) + + await ac.grantRole(OTHER_ROLE, otherAdmin, { from: admin }) + }) + + it("a role's admin role can be changed", async function () { + assert.equals(await ac.getRoleAdmin(ROLE), OTHER_ROLE) + }) + + it('the new admin can grant roles', async function () { + const receipt = await ac.grantRole(ROLE, authorized, { from: otherAdmin }) + assert.emits(receipt, 'RoleGranted', { account: authorized, role: ROLE, sender: otherAdmin }) + }) + + it('the new admin can revoke roles', async function () { + await ac.grantRole(ROLE, authorized, { from: otherAdmin }) + const receipt = await ac.revokeRole(ROLE, authorized, { from: otherAdmin }) + assert.emits(receipt, 'RoleRevoked', { account: authorized, role: ROLE, sender: otherAdmin }) + }) + + it("a role's previous admins no longer grant roles", async function () { + await assert.reverts( + ac.grantRole(ROLE, authorized, { from: admin }), + `AccessControl: account ${admin.toLowerCase()} is missing role ${OTHER_ROLE}` + ) + }) + + it("a role's previous admins no longer revoke roles", async function () { + await assert.reverts( + ac.revokeRole(ROLE, authorized, { from: admin }), + `AccessControl: account ${admin.toLowerCase()} is missing role ${OTHER_ROLE}` + ) + }) + }) + + describe('onlyRole modifier', function () { + beforeEach(async function () { + await ac.grantRole(ROLE, authorized, { from: admin }) + }) + + it('do not revert if sender has role', async function () { + await ac.senderProtected(ROLE, { from: authorized }) + }) + + it("revert if sender doesn't have role #1", async function () { + await assert.reverts( + ac.senderProtected(ROLE, { from: other }), + `AccessControl: account ${other.toLowerCase()} is missing role ${ROLE}` + ) + }) + + it("revert if sender doesn't have role #2", async function () { + await assert.reverts( + ac.senderProtected(OTHER_ROLE, { from: authorized }), + `AccessControl: account ${authorized.toLowerCase()} is missing role ${OTHER_ROLE}` + ) + }) + }) + + describe('enumerating', function () { + it('role bearers can be enumerated', async function () { + await ac.grantRole(ROLE, authorized, { from: admin }) + await ac.grantRole(ROLE, other, { from: admin }) + await ac.grantRole(ROLE, otherAuthorized, { from: admin }) + await ac.revokeRole(ROLE, other, { from: admin }) + + const memberCount = await ac.getRoleMemberCount(ROLE) + assert.equals(memberCount, 2) + + const bearers = [] + for (let i = 0; i < memberCount; ++i) { + bearers.push(await ac.getRoleMember(ROLE, i)) + } + + assert(bearers.includes(authorized)) + assert(bearers.includes(otherAuthorized)) + }) + it('role enumeration should be in sync after renounceRole call', async function () { + assert.equals(await ac.getRoleMemberCount(ROLE), 0) + await ac.grantRole(ROLE, admin, { from: admin }) + assert.equals(await ac.getRoleMemberCount(ROLE), 1) + await ac.renounceRole(ROLE, admin, { from: admin }) + assert.equals(await ac.getRoleMemberCount(ROLE), 0) + }) + }) +}) From 7d364b6d1b62860e3b8507c0119fc755913e9db6 Mon Sep 17 00:00:00 2001 From: Andrei Date: Wed, 1 Mar 2023 18:51:25 +0700 Subject: [PATCH 079/236] test: scenario: el rewards: move utils to helpers --- .../oracle/accounting-oracle-deploy.test.js | 30 +--------------- test/helpers/reportData.js | 34 +++++++++++++++++++ ...tion_layer_rewards_after_the_merge.test.js | 28 +-------------- 3 files changed, 36 insertions(+), 56 deletions(-) create mode 100644 test/helpers/reportData.js diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index 380db9e49..4ce2b7e19 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -6,6 +6,7 @@ const { updateLocatorImplementation, deployLocatorWithDummyAddressesImplementation, } = require('../../helpers/locator-deploy') +const { calcReportDataHash, getReportDataItems } = require('../../helpers/reportData') const { SLOTS_PER_EPOCH, @@ -46,35 +47,6 @@ const EXTRA_DATA_FORMAT_LIST = 1 const EXTRA_DATA_TYPE_STUCK_VALIDATORS = 1 const EXTRA_DATA_TYPE_EXITED_VALIDATORS = 2 -function getReportDataItems(r) { - return [ - r.consensusVersion, - +r.refSlot, - r.numValidators, - r.clBalanceGwei, - r.stakingModuleIdsWithNewlyExitedValidators, - r.numExitedValidatorsByStakingModule, - r.withdrawalVaultBalance, - r.elRewardsVaultBalance, - r.lastWithdrawalRequestIdToFinalize, - r.finalizationShareRate, - r.isBunkerMode, - r.extraDataFormat, - r.extraDataHash, - r.extraDataItemsCount, - ] -} - -function calcReportDataHash(reportItems) { - const data = web3.eth.abi.encodeParameters( - [ - '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)', - ], - [reportItems] - ) - return web3.utils.keccak256(data) -} - function encodeExtraDataItem(itemIndex, itemType, moduleId, nodeOperatorIds, keysCounts) { const itemHeader = hex(itemIndex, 3) + hex(itemType, 2) const payloadHeader = hex(moduleId, 3) + hex(nodeOperatorIds.length, 8) diff --git a/test/helpers/reportData.js b/test/helpers/reportData.js new file mode 100644 index 000000000..eca317a27 --- /dev/null +++ b/test/helpers/reportData.js @@ -0,0 +1,34 @@ +const { web3 } = require('hardhat') + +function calcReportDataHash(reportItems) { + const data = web3.eth.abi.encodeParameters( + [ + '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)', + ], + [reportItems] + ) + return web3.utils.keccak256(data) +} +function getReportDataItems(r) { + return [ + r.consensusVersion, + +r.refSlot, + r.numValidators, + r.clBalanceGwei, + r.stakingModuleIdsWithNewlyExitedValidators, + r.numExitedValidatorsByStakingModule, + r.withdrawalVaultBalance, + r.elRewardsVaultBalance, + r.lastWithdrawalRequestIdToFinalize, + r.finalizationShareRate, + r.isBunkerMode, + r.extraDataFormat, + r.extraDataHash, + r.extraDataItemsCount, + ] +} + +module.exports = { + calcReportDataHash, + getReportDataItems, +} diff --git a/test/scenario/execution_layer_rewards_after_the_merge.test.js b/test/scenario/execution_layer_rewards_after_the_merge.test.js index cf62877ff..a2245ab85 100644 --- a/test/scenario/execution_layer_rewards_after_the_merge.test.js +++ b/test/scenario/execution_layer_rewards_after_the_merge.test.js @@ -9,6 +9,7 @@ const { waitBlocks, setBalance } = require('../helpers/blockchain') const { deployProtocol } = require('../helpers/protocol') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') const { SLOTS_PER_FRAME } = require('../helpers/constants') +const { calcReportDataHash, getReportDataItems } = require('../helpers/reportData') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') @@ -33,33 +34,6 @@ const makeAccountingReport = ({ refSlot, numValidators, clBalanceGwei, elRewards extraDataHash: ZERO_HASH, extraDataItemsCount: 0, }) -function calcReportDataHash(reportItems) { - const data = web3.eth.abi.encodeParameters( - [ - '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)', - ], - [reportItems] - ) - return web3.utils.keccak256(data) -} -function getReportDataItems(r) { - return [ - r.consensusVersion, - +r.refSlot, - r.numValidators, - r.clBalanceGwei, - r.stakingModuleIdsWithNewlyExitedValidators, - r.numExitedValidatorsByStakingModule, - r.withdrawalVaultBalance, - r.elRewardsVaultBalance, - r.lastWithdrawalRequestIdToFinalize, - r.finalizationShareRate, - r.isBunkerMode, - r.extraDataFormat, - r.extraDataHash, - r.extraDataItemsCount, - ] -} contract('Lido: merge acceptance', (addresses) => { const [ From ab54cba1c755e843b640bdb25df757c1c0bb3402 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 18:50:05 +0200 Subject: [PATCH 080/236] fix: remove unnecessary corner case. --- contracts/0.8.9/WithdrawalQueueBase.sol | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 459d7e532..8d3ab8f5c 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -378,16 +378,7 @@ abstract contract WithdrawalQueueBase { // avg batch rate before crossing point and after crossing point // can't be both above `_maxShareRate` - // except the case when crossing point is extremum and touching `_maxShareRate` from above - // | • • - // |---*---- maxShareRate - // +--------> - if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) { - // TODO: get rid of this corner case - if (!(extremumId == batchEndId && _calcShareRate(_batches[batchIndex]) != _maxShareRate)) { - revert InvalidBatches(); - } - } + if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) revert InvalidBatches(); batchShareRate = nextBatchShareRate; batchPreStartId = batchEndId; From a02fd6bf7ea6445b228b190248ac2e2ed159ff9f Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Wed, 1 Mar 2023 14:43:11 +0200 Subject: [PATCH 081/236] store last report ts in each request and check it on batching --- contracts/0.8.9/WithdrawalQueueBase.sol | 61 +++++++++++++++++-------- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 8d3ab8f5c..7ec32aaa3 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -50,6 +50,9 @@ abstract contract WithdrawalQueueBase { /// last extreum index that was already checked for finalization bytes32 internal constant LAST_CHECKED_EXTREMUM_POSITION = keccak256("lido.WithdrawalQueue.lastCheckedExtremum"); + bytes32 internal constant LAST_REPORT_TIMESTAMP_POSITION = keccak256("lido.WithdrawalQueue.lastReportTimestamp"); + + /// @notice structure representing a request for withdrawal. struct WithdrawalRequest { /// @notice sum of the all stETH submitted for withdrawals up to this request @@ -63,7 +66,7 @@ abstract contract WithdrawalQueueBase { /// @notice flag if the request was claimed bool claimed; - //reportTimestamp; + uint64 reportTimestamp; } /// @notice structure to store discounts for requests that are affected by negative rebase @@ -167,7 +170,6 @@ abstract contract WithdrawalQueueBase { uint256[] batches; } - // TODO: 1-2 wei corner case use rebaseTimestamp function calculateFinalizationBatches(uint256 _maxShareRate, uint256 _maxTimestamp, CalcState memory _state) external view @@ -208,20 +210,20 @@ abstract contract WithdrawalQueueBase { WithdrawalRequest memory prevRequest = _getQueue()[requestId - 1]; - uint256 etherRequested = request.cumulativeStETH - prevRequest.cumulativeStETH; + uint256 ethToFinalize = request.cumulativeStETH - prevRequest.cumulativeStETH; uint256 shareRequested = request.cumulativeShares - prevRequest.cumulativeShares; - uint256 requestShareRate = etherRequested * E27_PRECISION_BASE / shareRequested; + uint256 requestShareRate = ethToFinalize * E27_PRECISION_BASE / shareRequested; if (requestShareRate > _maxShareRate) { - etherRequested = shareRequested * _maxShareRate / E27_PRECISION_BASE; + ethToFinalize = shareRequested * _maxShareRate / E27_PRECISION_BASE; } - if (etherRequested > _state.ethBudget) break; + if (ethToFinalize > _state.ethBudget) break; - _state.ethBudget -= etherRequested; + _state.ethBudget -= ethToFinalize; if (_state.batches[MAX_EXTREMA_PER_CALL] != 0 && ( - // todo: check if we can omit `touching from above` case + prevRequest.reportTimestamp == request.reportTimestamp || prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || prevRequestShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { @@ -250,8 +252,11 @@ abstract contract WithdrawalQueueBase { return _state; } - function onPreRebase() external { + function onPreRebase(uint256 reportTimestamp) external { + _setLastReportTimestamp(reportTimestamp); + // Populate shareRate extrema list + // TODO: move it to withdrawal request creation moment uint256 lastRequestId = getLastRequestId(); uint256[] storage extrema = _getExtrema(); // first request is an extremum by default @@ -264,17 +269,22 @@ abstract contract WithdrawalQueueBase { // no new requests => no new exrema if (lastExtremumId == lastRequestId) return; - uint256 lastRequestShareRate = _calcShareRate(lastRequestId); - uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId); + WithdrawalRequest memory lastRequest = _getQueue()[lastRequestId]; + WithdrawalRequest memory lastExtremum = _getQueue()[lastExtremumId]; + + if (lastRequest.reportTimestamp == lastExtremum.reportTimestamp) return; + + uint256 lastRequestShareRate = _calcShareRate(lastRequestId, lastRequest); + uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId, lastExtremum); - if (lastRequestShareRate == lastExtremumShareRate) return; // todo: 1-2 wei corner case + if (lastRequestShareRate == lastExtremumShareRate) return; // first met request in a sequence with equal shareRate is an extremum if (extrema.length == 2) { // first two different rates are always extrema extrema.push(lastRequestId); } else { - uint256 prevExtremumShareRate = _calcShareRate(lastExtremumId - 1); + uint256 prevExtremumShareRate = _calcShareRate(lastExtremumId - 1, SHARE_RATE_UNLIMITED); bool wasGrowing = lastExtremumShareRate > prevExtremumShareRate; // | • @@ -360,7 +370,7 @@ abstract contract WithdrawalQueueBase { if (extremumId < batchEndId) { extremumId = _getExtrema()[extremumIndex]; // check extremum - uint256 extremumShareRate = _calcShareRate(extremumId); + uint256 extremumShareRate = _calcShareRate(extremumId, SHARE_RATE_UNLIMITED); if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); @@ -448,7 +458,8 @@ abstract contract WithdrawalQueueBase { _setLastRequestId(requestId); _getQueue()[requestId] = - WithdrawalRequest(cumulativeStETH, cumulativeShares, _owner, uint64(block.timestamp), false); + WithdrawalRequest(cumulativeStETH, cumulativeShares, _owner, uint64(block.timestamp), false, + uint64(_getLastReportTimestamp())); assert(_getRequestsByOwner()[_owner].add(requestId)); emit WithdrawalRequested(requestId, msg.sender, _owner, _amountOfStETH, _amountOfShares); @@ -589,7 +600,7 @@ abstract contract WithdrawalQueueBase { // setting dummy zero structs in checkpoints and queue beginning // to avoid uint underflows and related if-branches // 0-index is reserved as 'not_found' response in the interface everywhere - _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint64(block.number), true); + _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint64(block.number), true, 0); _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, 0); _getExtrema().push(0); } @@ -621,8 +632,14 @@ abstract contract WithdrawalQueueBase { return _calcShareRate(prevRequest, lastRequest, _maxShareRate); } - function _calcShareRate(uint256 _requestId) internal view returns (uint256) { - return _calcShareRate(_requestId, SHARE_RATE_UNLIMITED); + function _calcShareRate(uint256 _requestId, WithdrawalRequest memory request) + internal + view + returns (uint256) + { + WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; + + return _calcShareRate(prevRequest, request, SHARE_RATE_UNLIMITED); } // @@ -661,6 +678,10 @@ abstract contract WithdrawalQueueBase { return LAST_CHECKED_EXTREMUM_POSITION.getStorageUint256(); } + function _getLastReportTimestamp() internal view returns (uint256) { + return LAST_REPORT_TIMESTAMP_POSITION.getStorageUint256(); + } + function _setLastRequestId(uint256 _lastRequestId) internal { LAST_REQUEST_ID_POSITION.setStorageUint256(_lastRequestId); } @@ -680,4 +701,8 @@ abstract contract WithdrawalQueueBase { function _setLastCheckedExtremum(uint256 _lastCheckedExtremum) internal { LAST_CHECKED_EXTREMUM_POSITION.setStorageUint256(_lastCheckedExtremum); } + + function _setLastReportTimestamp(uint256 _lastReportTimestamp) internal { + LAST_REPORT_TIMESTAMP_POSITION.setStorageUint256(_lastReportTimestamp); + } } diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 37127a7e0..fc1c97790 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"reportTimestamp","type":"uint256"}],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index 1779db035..e4ad83217 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"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":"uint256","name":"reportTimestamp","type":"uint256"}],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 11e022394..b6351d5cd 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":[],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"reportTimestamp","type":"uint256"}],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 76167a81abb6c99c94d8adbb087ec009bcebefe7 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 16:19:24 +0300 Subject: [PATCH 082/236] test: refactor tests to have reportData isolated --- .../accounting-oracle-access-control.test.js | 8 ++-- .../oracle/accounting-oracle-deploy.test.js | 6 +-- .../accounting-oracle-happy-path.test.js | 16 +++---- ...counting-oracle-submit-report-data.test.js | 48 +++++++++---------- ...ng-oracle-submit-report-extra-data.test.js | 12 ++--- ...ors-exit-bus-oracle-access-control.test.js | 8 ++-- .../validators-exit-bus-oracle-deploy.test.js | 16 ++----- .../validators-exit-bus-oracle-gas.test.js | 8 ++-- ...idators-exit-bus-oracle-happy-path.test.js | 12 ++--- ...exit-bus-oracle-submit-report-data.test.js | 22 ++++----- test/helpers/reportData.js | 19 ++++++-- .../changing_oracles_during_epoch.test.js | 12 ++--- ...tion_layer_rewards_after_the_merge.test.js | 26 +++++----- 13 files changed, 109 insertions(+), 104 deletions(-) diff --git a/test/0.8.9/oracle/accounting-oracle-access-control.test.js b/test/0.8.9/oracle/accounting-oracle-access-control.test.js index 4c3eff0da..b7148c76c 100644 --- a/test/0.8.9/oracle/accounting-oracle-access-control.test.js +++ b/test/0.8.9/oracle/accounting-oracle-access-control.test.js @@ -5,11 +5,11 @@ const { e9, e18, e27 } = require('../../helpers/utils') const { CONSENSUS_VERSION, deployAndConfigureAccountingOracle, - getReportDataItems, + getAccountingReportDataItems, encodeExtraDataItems, packExtraDataList, calcExtraDataListHash, - calcReportDataHash, + calcAccountingReportDataHash, EXTRA_DATA_FORMAT_EMPTY, EXTRA_DATA_FORMAT_LIST, ZERO_HASH, @@ -61,8 +61,8 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra extraDataHash: emptyExtraData ? ZERO_HASH : extraDataHash, extraDataItemsCount: emptyExtraData ? 0 : extraDataItems.length, } - reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) await deployed.consensus.addMember(member1, 1, { from: admin }) await deployed.consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index 4ce2b7e19..fc943e768 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -6,7 +6,7 @@ const { updateLocatorImplementation, deployLocatorWithDummyAddressesImplementation, } = require('../../helpers/locator-deploy') -const { calcReportDataHash, getReportDataItems } = require('../../helpers/reportData') +const { calcAccountingReportDataHash, getAccountingReportDataItems } = require('../../helpers/reportData') const { SLOTS_PER_EPOCH, @@ -122,8 +122,8 @@ module.exports = { initAccountingOracle, deployMockLegacyOracle, deployMockLidoAndStakingRouter, - getReportDataItems, - calcReportDataHash, + getAccountingReportDataItems, + calcAccountingReportDataHash, encodeExtraDataItem, encodeExtraDataItems, packExtraDataList, diff --git a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js index 539033bac..f514ba126 100644 --- a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js +++ b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js @@ -15,8 +15,8 @@ const { EXTRA_DATA_FORMAT_EMPTY, EXTRA_DATA_FORMAT_LIST, deployAndConfigureAccountingOracle, - getReportDataItems, - calcReportDataHash, + getAccountingReportDataItems, + calcAccountingReportDataHash, encodeExtraDataItems, packExtraDataList, calcExtraDataListHash, @@ -127,8 +127,8 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { extraDataItemsCount: extraDataItems.length, } - reportItems = getReportDataItems(reportFields) - reportHash = calcReportDataHash(reportItems) + reportItems = getAccountingReportDataItems(reportFields) + reportHash = calcAccountingReportDataHash(reportItems) await triggerConsensusOnHash(reportHash) }) @@ -174,8 +174,8 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { it(`a data not matching the consensus hash cannot be submitted`, async () => { const invalidReport = { ...reportFields, numValidators: reportFields.numValidators + 1 } - const invalidReportItems = getReportDataItems(invalidReport) - const invalidReportHash = calcReportDataHash(invalidReportItems) + const invalidReportItems = getAccountingReportDataItems(invalidReport) + const invalidReportHash = calcAccountingReportDataHash(invalidReportItems) await assert.reverts( oracle.submitReportData(invalidReportItems, oracleVersion, { from: member1 }), `UnexpectedDataHash("${reportHash}", "${invalidReportHash}")` @@ -393,8 +393,8 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { extraDataHash: ZERO_HASH, extraDataItemsCount: 0, } - reportItems = getReportDataItems(reportFields) - reportHash = calcReportDataHash(reportItems) + reportItems = getAccountingReportDataItems(reportFields) + reportHash = calcAccountingReportDataHash(reportItems) await triggerConsensusOnHash(reportHash) diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js index 3818656a4..87aab8c9c 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js @@ -7,11 +7,11 @@ const AccountingOracleAbi = require('../../../lib/abi/AccountingOracle.json') const { CONSENSUS_VERSION, deployAndConfigureAccountingOracle, - getReportDataItems, + getAccountingReportDataItems, encodeExtraDataItems, packExtraDataList, calcExtraDataListHash, - calcReportDataHash, + calcAccountingReportDataHash, EXTRA_DATA_FORMAT_LIST, EXTRA_DATA_FORMAT_EMPTY, SLOTS_PER_FRAME, @@ -77,8 +77,8 @@ contract('AccountingOracle', ([admin, member1]) => { reportFields = getReportFields({ refSlot: +refSlot, }) - reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) await deployed.consensus.addMember(member1, 1, { from: admin }) await deployed.consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) @@ -97,8 +97,8 @@ contract('AccountingOracle', ([admin, member1]) => { async function prepareNextReport(newReportFields) { await consensus.setTime(deadline) - const newReportItems = getReportDataItems(newReportFields) - const reportHash = calcReportDataHash(newReportItems) + const newReportItems = getAccountingReportDataItems(newReportFields) + const reportHash = calcAccountingReportDataHash(newReportItems) await consensus.advanceTimeToNextFrameStart() await consensus.submitReport(newReportFields.refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) @@ -177,7 +177,7 @@ contract('AccountingOracle', ([admin, member1]) => { ...reportFields, refSlot: incorrectRefSlot, } - const reportItems = getReportDataItems(newReportFields) + const reportItems = getAccountingReportDataItems(newReportFields) await assert.reverts( oracle.submitReportData(reportItems, oracleVersion, { from: member1 }), @@ -216,10 +216,10 @@ contract('AccountingOracle', ([admin, member1]) => { ...reportFields, consensusVersion: incorrectNextVersion, } - const reportItems = getReportDataItems(newReportFields) + const reportItems = getAccountingReportDataItems(newReportFields) const reportFieldsPrevVersion = { ...reportFields, consensusVersion: incorrectPrevVersion } - const reportItemsPrevVersion = getReportDataItems(reportFieldsPrevVersion) + const reportItemsPrevVersion = getAccountingReportDataItems(reportFieldsPrevVersion) await assert.reverts( oracle.submitReportData(reportItems, oracleVersion, { from: member1 }), @@ -246,8 +246,8 @@ contract('AccountingOracle', ([admin, member1]) => { refSlot: nextRefSlot, consensusVersion: newConsensusVersion, } - const newReportItems = getReportDataItems(newReportFields) - const newReportHash = calcReportDataHash(newReportItems) + const newReportItems = getAccountingReportDataItems(newReportFields) + const newReportHash = calcAccountingReportDataHash(newReportItems) await oracle.setConsensusVersion(newConsensusVersion, { from: admin }) await consensus.advanceTimeToNextFrameStart() @@ -301,13 +301,13 @@ contract('AccountingOracle', ([admin, member1]) => { context('checks data hash', () => { it('reverts with UnexpectedDataHash', async () => { - const incorrectReportItems = getReportDataItems({ + const incorrectReportItems = getAccountingReportDataItems({ ...reportFields, numValidators: reportFields.numValidators - 1, }) - const correctDataHash = calcReportDataHash(reportItems) - const incorrectDataHash = calcReportDataHash(incorrectReportItems) + const correctDataHash = calcAccountingReportDataHash(reportItems) + const incorrectDataHash = calcAccountingReportDataHash(incorrectReportItems) await assert.reverts( oracle.submitReportData(incorrectReportItems, oracleVersion, { from: member1 }), @@ -516,13 +516,13 @@ contract('AccountingOracle', ([admin, member1]) => { await oracle.submitReportData(reportItems, oracleVersion, { from: member1 }) const nextRefSlot = reportFields.refSlot + SLOTS_PER_FRAME - const changedReportItems = getReportDataItems({ + const changedReportItems = getAccountingReportDataItems({ ...reportFields, refSlot: nextRefSlot, extraDataFormat: EXTRA_DATA_FORMAT_LIST + 1, }) - const changedReportHash = calcReportDataHash(changedReportItems) + const changedReportHash = calcAccountingReportDataHash(changedReportItems) await consensus.advanceTimeToNextFrameStart() await consensus.submitReport(nextRefSlot, changedReportHash, CONSENSUS_VERSION, { from: member1, @@ -541,8 +541,8 @@ contract('AccountingOracle', ([admin, member1]) => { refSlot: +refSlot, extraDataItemsCount: 0, }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) await assert.revertsWithCustomError( oracle.submitReportData(reportItems, oracleVersion, { from: member1 }), @@ -557,8 +557,8 @@ contract('AccountingOracle', ([admin, member1]) => { refSlot: +refSlot, extraDataHash: ZERO_HASH, }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) await assert.revertsWithCustomError( oracle.submitReportData(reportItems, oracleVersion, { from: member1 }), @@ -579,8 +579,8 @@ contract('AccountingOracle', ([admin, member1]) => { extraDataHash: nonZeroHash, extraDataItemsCount: 0, }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) await assert.revertsWithCustomError( oracle.submitReportData(reportItems, oracleVersion, { from: member1 }), @@ -598,8 +598,8 @@ contract('AccountingOracle', ([admin, member1]) => { extraDataHash: ZERO_HASH, extraDataItemsCount: 10, }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) await assert.revertsWithCustomError( oracle.submitReportData(reportItems, oracleVersion, { from: member1 }), diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js index abe68f109..5371f2227 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-extra-data.test.js @@ -5,12 +5,12 @@ const { e9, e18, e27, hex } = require('../../helpers/utils') const { CONSENSUS_VERSION, deployAndConfigureAccountingOracle, - getReportDataItems, + getAccountingReportDataItems, encodeExtraDataItem, encodeExtraDataItems, packExtraDataList, calcExtraDataListHash, - calcReportDataHash, + calcAccountingReportDataHash, ZERO_HASH, EXTRA_DATA_FORMAT_EMPTY, EXTRA_DATA_FORMAT_LIST, @@ -81,8 +81,8 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra ...reportFieldsArg, }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) return { extraData, @@ -533,8 +533,8 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra refSlot, }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(reportFields.refSlot, reportHash, CONSENSUS_VERSION, { from: member1, diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js index cc0acfe26..3835c82d7 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js @@ -5,8 +5,8 @@ const { ZERO_ADDRESS } = require('../../helpers/constants') const { CONSENSUS_VERSION, DATA_FORMAT_LIST, - getReportDataItems, - calcReportDataHash, + getValidatorsExitBusReportDataItems, + calcValidatorsExitBusReportDataHash, encodeExitRequestsDataList, deployExitBusOracle, } = require('./validators-exit-bus-oracle-deploy.test') @@ -60,8 +60,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, account1 data: encodeExitRequestsDataList(exitRequests), }) - reportItems = getReportDataItems(reportFields) - reportHash = calcReportDataHash(reportItems) + reportItems = getValidatorsExitBusReportDataItems(reportFields) + reportHash = calcValidatorsExitBusReportDataHash(reportItems) await deployed.consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member1 }) await deployed.consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: member3 }) 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 3cab5a7a7..f047e7740 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 @@ -1,4 +1,4 @@ -const { contract, artifacts, web3 } = require('hardhat') +const { contract, artifacts } = require('hardhat') const { assert } = require('../../helpers/assert') const { hex, strip0x } = require('../../helpers/utils') const { ZERO_ADDRESS } = require('../../helpers/constants') @@ -23,17 +23,11 @@ const { deployHashConsensus, } = require('./hash-consensus-deploy.test') +const { calcValidatorsExitBusReportDataHash, getValidatorsExitBusReportDataItems } = require('../../helpers/reportData') + const ValidatorsExitBusOracle = artifacts.require('ValidatorsExitBusTimeTravellable') const DATA_FORMAT_LIST = 1 -function getReportDataItems(r) { - return [r.consensusVersion, r.refSlot, r.requestsCount, r.dataFormat, r.data] -} - -function calcReportDataHash(reportItems) { - const data = web3.eth.abi.encodeParameters(['(uint256,uint256,uint256,uint256,bytes)'], [reportItems]) - return web3.utils.keccak256(data) -} function encodeExitRequestHex({ moduleId, nodeOpId, valIndex, valPubkey }) { const pubkeyHex = strip0x(valPubkey) @@ -72,8 +66,8 @@ module.exports = { ZERO_HASH, CONSENSUS_VERSION, DATA_FORMAT_LIST, - getReportDataItems, - calcReportDataHash, + getValidatorsExitBusReportDataItems, + calcValidatorsExitBusReportDataHash, encodeExitRequestHex, encodeExitRequestsDataList, deployExitBusOracle, diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-gas.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-gas.test.js index ddc91d4ef..8361c317a 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-gas.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-gas.test.js @@ -8,8 +8,8 @@ const { ZERO_HASH, CONSENSUS_VERSION, DATA_FORMAT_LIST, - getReportDataItems, - calcReportDataHash, + getValidatorsExitBusReportDataItems, + calcValidatorsExitBusReportDataHash, encodeExitRequestsDataList, deployExitBusOracle, } = require('./validators-exit-bus-oracle-deploy.test') @@ -116,8 +116,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger data: encodeExitRequestsDataList(exitRequests.requests), } - reportItems = getReportDataItems(reportFields) - reportHash = calcReportDataHash(reportItems) + reportItems = getValidatorsExitBusReportDataItems(reportFields) + reportHash = calcValidatorsExitBusReportDataHash(reportItems) await triggerConsensusOnHash(reportHash) }) diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-happy-path.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-happy-path.test.js index ae553285d..535872a04 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-happy-path.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-happy-path.test.js @@ -9,8 +9,8 @@ const { ZERO_HASH, CONSENSUS_VERSION, DATA_FORMAT_LIST, - getReportDataItems, - calcReportDataHash, + getValidatorsExitBusReportDataItems, + calcValidatorsExitBusReportDataHash, encodeExitRequestsDataList, deployExitBusOracle, } = require('./validators-exit-bus-oracle-deploy.test') @@ -100,8 +100,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger data: encodeExitRequestsDataList(exitRequests), } - reportItems = getReportDataItems(reportFields) - reportHash = calcReportDataHash(reportItems) + reportItems = getValidatorsExitBusReportDataItems(reportFields) + reportHash = calcValidatorsExitBusReportDataHash(reportItems) await triggerConsensusOnHash(reportHash) }) @@ -153,8 +153,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger it(`a data not matching the consensus hash cannot be submitted`, async () => { const invalidReport = { ...reportFields, requestsCount: reportFields.requestsCount + 1 } - const invalidReportItems = getReportDataItems(invalidReport) - const invalidReportHash = calcReportDataHash(invalidReportItems) + const invalidReportItems = getValidatorsExitBusReportDataItems(invalidReport) + const invalidReportHash = calcValidatorsExitBusReportDataHash(invalidReportItems) await assert.reverts( oracle.submitReportData(invalidReportItems, oracleVersion, { from: member1 }), `UnexpectedDataHash("${reportHash}", "${invalidReportHash}")` diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js index f7140cb26..bc9c75b2e 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js @@ -4,8 +4,8 @@ const { assert } = require('../../helpers/assert') const { CONSENSUS_VERSION, DATA_FORMAT_LIST, - getReportDataItems, - calcReportDataHash, + getValidatorsExitBusReportDataItems, + calcValidatorsExitBusReportDataHash, encodeExitRequestsDataList, deployExitBusOracle, computeTimestampAtSlot, @@ -84,8 +84,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger ...reportFieldsArg, }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getValidatorsExitBusReportDataItems(reportFields) + const reportHash = calcValidatorsExitBusReportDataHash(reportItems) await triggerConsensusOnHash(reportHash) @@ -146,8 +146,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger }) reportFields.data += 'aaaaaaaaaaaaaaaaaa' - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getValidatorsExitBusReportDataItems(reportFields) + const reportHash = calcValidatorsExitBusReportDataHash(reportItems) await triggerConsensusOnHash(reportHash) await assert.reverts( @@ -166,8 +166,8 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger }) reportFields.data = reportFields.data.slice(0, reportFields.data.length - 18) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const reportItems = getValidatorsExitBusReportDataItems(reportFields) + const reportHash = calcValidatorsExitBusReportDataHash(reportItems) await triggerConsensusOnHash(reportHash) await assert.reverts( @@ -448,10 +448,10 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger it('reverts on hash mismatch', async () => { const report = await prepareReportAndSubmitHash() - const actualReportHash = calcReportDataHash(report) + const actualReportHash = calcValidatorsExitBusReportDataHash(report) // mess with data field to change hash report[report.length - 1] = report[report.length - 1] + 'ff' - const changedReportHash = calcReportDataHash(report) + const changedReportHash = calcValidatorsExitBusReportDataHash(report) await assert.reverts( oracle.submitReportData(report, oracleVersion, { from: member1 }), `UnexpectedDataHash("${actualReportHash}", "${changedReportHash}")` @@ -531,7 +531,7 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger { moduleId: 5, nodeOpId: 1, valIndex: 10, valPubkey: PUBKEYS[2] }, { moduleId: 5, nodeOpId: 3, valIndex: 1, valPubkey: PUBKEYS[3] }, ]) - hash = calcReportDataHash(report) + hash = calcValidatorsExitBusReportDataHash(report) const state = await oracle.getProcessingState() assertEqualsObject(state, { currentFrameRefSlot: (await consensus.getCurrentFrame()).refSlot, diff --git a/test/helpers/reportData.js b/test/helpers/reportData.js index eca317a27..c3c8d6e3e 100644 --- a/test/helpers/reportData.js +++ b/test/helpers/reportData.js @@ -1,6 +1,15 @@ const { web3 } = require('hardhat') -function calcReportDataHash(reportItems) { +function calcValidatorsExitBusReportDataHash(reportItems) { + const data = web3.eth.abi.encodeParameters(['(uint256,uint256,uint256,uint256,bytes)'], [reportItems]) + return web3.utils.keccak256(data) +} + +function getValidatorsExitBusReportDataItems(r) { + return [r.consensusVersion, r.refSlot, r.requestsCount, r.dataFormat, r.data] +} + +function calcAccountingReportDataHash(reportItems) { const data = web3.eth.abi.encodeParameters( [ '(uint256,uint256,uint256,uint256,uint256[],uint256[],uint256,uint256,uint256,uint256,bool,uint256,bytes32,uint256)', @@ -9,7 +18,7 @@ function calcReportDataHash(reportItems) { ) return web3.utils.keccak256(data) } -function getReportDataItems(r) { +function getAccountingReportDataItems(r) { return [ r.consensusVersion, +r.refSlot, @@ -29,6 +38,8 @@ function getReportDataItems(r) { } module.exports = { - calcReportDataHash, - getReportDataItems, + calcAccountingReportDataHash, + getAccountingReportDataItems, + getValidatorsExitBusReportDataItems, + calcValidatorsExitBusReportDataHash, } diff --git a/test/scenario/changing_oracles_during_epoch.test.js b/test/scenario/changing_oracles_during_epoch.test.js index 2c0de7380..b8db04804 100644 --- a/test/scenario/changing_oracles_during_epoch.test.js +++ b/test/scenario/changing_oracles_during_epoch.test.js @@ -10,8 +10,8 @@ const { CONSENSUS_VERSION, HASH_1, ZERO_HASH, - getReportDataItems, - calcReportDataHash, + getAccountingReportDataItems, + calcAccountingReportDataHash, } = require('../0.8.9/oracle/accounting-oracle-deploy.test') const SLOTS_PER_EPOCH = 32 @@ -81,10 +81,10 @@ contract('AccountingOracle', ([voting, malicious1, malicious2, member1, member2, await consensus.addMember(malicious1, 4, { from: voting }) await consensus.addMember(malicious2, 4, { from: voting }) - const goodDataItems = getReportDataItems({ ...GOOD_DATA, refSlot: SLOTS_PER_FRAME - 1 }) - const badDataItems = getReportDataItems({ ...BAD_DATA, refSlot: SLOTS_PER_FRAME - 1 }) - const goodDataHash = calcReportDataHash(goodDataItems) - const badDataHash = calcReportDataHash(badDataItems) + const goodDataItems = getAccountingReportDataItems({ ...GOOD_DATA, refSlot: SLOTS_PER_FRAME - 1 }) + const badDataItems = getAccountingReportDataItems({ ...BAD_DATA, refSlot: SLOTS_PER_FRAME - 1 }) + const goodDataHash = calcAccountingReportDataHash(goodDataItems) + const badDataHash = calcAccountingReportDataHash(badDataItems) await consensus.submitReport(SLOTS_PER_FRAME - 1, badDataHash, CONSENSUS_VERSION, { from: malicious1 }) await consensus.submitReport(SLOTS_PER_FRAME - 1, badDataHash, CONSENSUS_VERSION, { from: malicious2 }) diff --git a/test/scenario/execution_layer_rewards_after_the_merge.test.js b/test/scenario/execution_layer_rewards_after_the_merge.test.js index a2245ab85..2e9f2f4d2 100644 --- a/test/scenario/execution_layer_rewards_after_the_merge.test.js +++ b/test/scenario/execution_layer_rewards_after_the_merge.test.js @@ -9,7 +9,7 @@ const { waitBlocks, setBalance } = require('../helpers/blockchain') const { deployProtocol } = require('../helpers/protocol') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') const { SLOTS_PER_FRAME } = require('../helpers/constants') -const { calcReportDataHash, getReportDataItems } = require('../helpers/reportData') +const { calcAccountingReportDataHash, getAccountingReportDataItems } = require('../helpers/reportData') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') @@ -401,7 +401,7 @@ contract('Lido: merge acceptance', (addresses) => { const { refSlot } = await consensus.getCurrentFrame() - const reportItems = getReportDataItems( + const reportItems = getAccountingReportDataItems( makeAccountingReport({ refSlot: +refSlot, numValidators: 2, @@ -409,7 +409,7 @@ contract('Lido: merge acceptance', (addresses) => { elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), }) ) - const reportHash = calcReportDataHash(reportItems) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) @@ -517,7 +517,7 @@ contract('Lido: merge acceptance', (addresses) => { await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() - const reportItems = getReportDataItems( + const reportItems = getAccountingReportDataItems( makeAccountingReport({ refSlot: +refSlot, numValidators: 2, @@ -525,7 +525,7 @@ contract('Lido: merge acceptance', (addresses) => { elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), }) ) - const reportHash = calcReportDataHash(reportItems) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) @@ -616,7 +616,7 @@ contract('Lido: merge acceptance', (addresses) => { await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() - const reportItems = getReportDataItems( + const reportItems = getAccountingReportDataItems( makeAccountingReport({ refSlot: +refSlot, numValidators: 2, @@ -624,7 +624,7 @@ contract('Lido: merge acceptance', (addresses) => { elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), }) ) - const reportHash = calcReportDataHash(reportItems) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) @@ -706,7 +706,7 @@ contract('Lido: merge acceptance', (addresses) => { await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() - const reportItems = getReportDataItems( + const reportItems = getAccountingReportDataItems( makeAccountingReport({ refSlot: +refSlot, numValidators: 2, @@ -714,7 +714,7 @@ contract('Lido: merge acceptance', (addresses) => { elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), }) ) - const reportHash = calcReportDataHash(reportItems) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) @@ -778,7 +778,7 @@ contract('Lido: merge acceptance', (addresses) => { await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() - const reportItems = getReportDataItems( + const reportItems = getAccountingReportDataItems( makeAccountingReport({ refSlot: +refSlot, numValidators: 2, @@ -786,7 +786,7 @@ contract('Lido: merge acceptance', (addresses) => { elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), }) ) - const reportHash = calcReportDataHash(reportItems) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) @@ -871,7 +871,7 @@ contract('Lido: merge acceptance', (addresses) => { await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() - const reportItems = getReportDataItems( + const reportItems = getAccountingReportDataItems( makeAccountingReport({ refSlot: +refSlot, numValidators: 2, @@ -879,7 +879,7 @@ contract('Lido: merge acceptance', (addresses) => { elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), }) ) - const reportHash = calcReportDataHash(reportItems) + const reportHash = calcAccountingReportDataHash(reportItems) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) From 589ed4c0cc3c4ac46eafcfa03793a45e6b042637 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Wed, 1 Mar 2023 15:38:48 +0200 Subject: [PATCH 083/236] oracles: fix revert on accounting oracle upgrade --- contracts/0.8.9/oracle/BaseOracle.sol | 10 +- contracts/0.8.9/oracle/HashConsensus.sol | 32 +++- .../oracle/MockConsensusContract.sol | 13 ++ .../oracle/accounting-oracle-deploy.test.js | 177 +++++++++++++----- .../oracle/base-oracle-access-control.test.js | 2 +- test/0.8.9/oracle/base-oracle-deploy.test.js | 2 +- .../oracle/base-oracle-set-consensus.test.js | 23 ++- .../oracle/hash-consensus-frames.test.js | 26 ++- .../changing_oracles_during_epoch.test.js | 37 ++-- 9 files changed, 227 insertions(+), 95 deletions(-) diff --git a/contracts/0.8.9/oracle/BaseOracle.sol b/contracts/0.8.9/oracle/BaseOracle.sol index 1292db0d2..e44057cfc 100644 --- a/contracts/0.8.9/oracle/BaseOracle.sol +++ b/contracts/0.8.9/oracle/BaseOracle.sol @@ -26,6 +26,8 @@ interface IConsensusContract { ); function getFrameConfig() external view returns (uint256 initialEpoch, uint256 epochsPerFrame); + + function getInitialRefSlot() external view returns (uint256); } @@ -38,7 +40,7 @@ abstract contract BaseOracle is IReportAsyncProcessor, AccessControlEnumerable, error VersionCannotBeSame(); error UnexpectedChainConfig(); error OnlyConsensusContractCanSubmitReport(); - error RefSlotCannotBeLessThanProcessingOne(uint256 refSlot, uint256 processingRefSlot); + error InitialRefSlotCannotBeLessThanProcessingOne(uint256 initialRefSlot, uint256 processingRefSlot); error RefSlotMustBeGreaterThanProcessingOne(uint256 refSlot, uint256 processingRefSlot); error RefSlotCannotDecrease(uint256 refSlot, uint256 prevRefSlot); error ProcessingDeadlineMissed(uint256 deadline); @@ -319,9 +321,9 @@ abstract contract BaseOracle is IReportAsyncProcessor, AccessControlEnumerable, revert UnexpectedChainConfig(); } - (uint256 refSlot, ) = IConsensusContract(addr).getCurrentFrame(); - if (refSlot < lastProcessingRefSlot) { - revert RefSlotCannotBeLessThanProcessingOne(refSlot, lastProcessingRefSlot); + uint256 initialRefSlot = IConsensusContract(addr).getInitialRefSlot(); + if (initialRefSlot < lastProcessingRefSlot) { + revert InitialRefSlotCannotBeLessThanProcessingOne(initialRefSlot, lastProcessingRefSlot); } CONSENSUS_CONTRACT_POSITION.setStorageAddress(addr); diff --git a/contracts/0.8.9/oracle/HashConsensus.sol b/contracts/0.8.9/oracle/HashConsensus.sol index 74b7cc817..b8a949d85 100644 --- a/contracts/0.8.9/oracle/HashConsensus.sol +++ b/contracts/0.8.9/oracle/HashConsensus.sol @@ -77,6 +77,7 @@ contract HashConsensus is AccessControlEnumerable { error AddressCannotBeZero(); error InitialEpochIsYetToArrive(); error InitialEpochAlreadyArrived(); + error InitialEpochRefSlotCannotBeEarlierThanProcessingSlot(); error EpochsPerFrameCannotBeZero(); error NonMember(); error UnexpectedConsensusVersion(uint256 expected, uint256 received); @@ -256,23 +257,33 @@ contract HashConsensus is AccessControlEnumerable { return (frame.refSlot, frame.reportProcessingDeadlineSlot); } + /// @notice Returns the earliest possible reference slot. + /// + function getInitialRefSlot() external view returns (uint256) { + return _getInitialFrame().refSlot; + } + /// @notice Sets initial epoch given that the current initial epoch is in the future. /// /// @param initialEpoch The new initial epoch. /// function updateInitialEpoch(uint256 initialEpoch) external onlyRole(DEFAULT_ADMIN_ROLE) { - FrameConfig memory frameConfig = _frameConfig; + FrameConfig memory prevConfig = _frameConfig; - if (_computeEpochAtTimestamp(_getTime()) >= frameConfig.initialEpoch) { + if (_computeEpochAtTimestamp(_getTime()) >= prevConfig.initialEpoch) { revert InitialEpochAlreadyArrived(); } _setFrameConfig( initialEpoch, - frameConfig.epochsPerFrame, - frameConfig.fastLaneLengthSlots, - frameConfig + prevConfig.epochsPerFrame, + prevConfig.fastLaneLengthSlots, + prevConfig ); + + if (_getInitialFrame().refSlot < _getLastProcessingRefSlot()) { + revert InitialEpochRefSlotCannotBeEarlierThanProcessingSlot(); + } } function setFrameConfig(uint256 epochsPerFrame, uint256 fastLaneLengthSlots) @@ -555,10 +566,19 @@ contract HashConsensus is AccessControlEnumerable { return _getFrameAtTimestamp(_getTime(), config); } + function _getInitialFrame() internal view returns (ConsensusFrame memory) { + return _getFrameAtIndex(0, _frameConfig); + } + function _getFrameAtTimestamp(uint256 timestamp, FrameConfig memory config) internal view returns (ConsensusFrame memory) { - uint256 frameIndex = _computeFrameIndex(timestamp, config); + return _getFrameAtIndex(_computeFrameIndex(timestamp, config), config); + } + + function _getFrameAtIndex(uint256 frameIndex, FrameConfig memory config) + internal view returns (ConsensusFrame memory) + { uint256 frameStartEpoch = _computeStartEpochOfFrameWithIndex(frameIndex, config); uint256 frameStartSlot = _computeStartSlotAtEpoch(frameStartEpoch); uint256 nextFrameStartSlot = frameStartSlot + config.epochsPerFrame * SLOTS_PER_EPOCH; diff --git a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol index 01cb51864..5e8a36916 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockConsensusContract.sol @@ -23,13 +23,16 @@ contract MockConsensusContract is IConsensusContract { uint256 refSlot; uint256 reportProcessingDeadlineSlot; } + struct FrameConfig { uint64 initialEpoch; uint64 epochsPerFrame; uint64 fastLaneLengthSlots; } + FrameConfig internal _frameConfig; ConsensusFrame internal _consensusFrame; + uint256 internal _initialRefSlot; constructor( uint256 slotsPerEpoch, @@ -50,6 +53,8 @@ contract MockConsensusContract is IConsensusContract { _consensusFrame.index = 10; _consensusFrame.refSlot = 1; _consensusFrame.reportProcessingDeadlineSlot = 7001; + + _initialRefSlot = initialEpoch * slotsPerEpoch - 1; } function getIsMember(address addr) external view returns (bool) { @@ -66,6 +71,10 @@ contract MockConsensusContract is IConsensusContract { _consensusFrame.reportProcessingDeadlineSlot = reportProcessingDeadlineSlot; } + function setInitialRefSlot(uint256 initialRefSlot) external { + _initialRefSlot = initialRefSlot; + } + function getChainConfig() external view @@ -78,6 +87,10 @@ contract MockConsensusContract is IConsensusContract { return (_frameConfig.initialEpoch, _frameConfig.epochsPerFrame); } + function getInitialRefSlot() external view returns (uint256) { + return _initialRefSlot; + } + 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/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index 380db9e49..328ea0343 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -1,7 +1,8 @@ -const { artifacts, contract, web3 } = require('hardhat') +const { ethers, artifacts, contract, web3 } = require('hardhat') const { ZERO_ADDRESS } = require('../../helpers/constants') const { assert } = require('../../helpers/assert') -const { hex } = require('../../helpers/utils') +const { hex, toBN } = require('../../helpers/utils') +const { EvmSnapshot } = require('../../helpers/blockchain') const { updateLocatorImplementation, deployLocatorWithDummyAddressesImplementation, @@ -99,24 +100,6 @@ function packExtraDataList(extraDataItems) { function calcExtraDataListHash(packedExtraDataList) { return web3.utils.keccak256(packedExtraDataList) } -async function deployOracleReportSanityCheckerForAccounting(lidoLocator, admin) { - const churnValidatorsPerDayLimit = 100 - const limitsList = [churnValidatorsPerDayLimit, 0, 0, 0, 32 * 12, 15, 16, 0, 0] - const managersRoster = [[admin], [admin], [admin], [admin], [admin], [admin], [admin], [admin], [admin], [admin]] - - const OracleReportSanityChecker = artifacts.require('OracleReportSanityChecker') - - const oracleReportSanityChecker = await OracleReportSanityChecker.new( - lidoLocator, - admin, - limitsList, - managersRoster, - { - from: admin, - } - ) - return oracleReportSanityChecker -} module.exports = { SLOTS_PER_EPOCH, @@ -148,6 +131,7 @@ module.exports = { deployAndConfigureAccountingOracle, deployAccountingOracleSetup, initAccountingOracle, + configureAccountingOracleSetup, deployMockLegacyOracle, deployMockLidoAndStakingRouter, getReportDataItems, @@ -156,7 +140,28 @@ module.exports = { encodeExtraDataItems, packExtraDataList, calcExtraDataListHash, + getInitialFrameStartTime, +} + +async function deployOracleReportSanityCheckerForAccounting(lidoLocator, admin) { + const churnValidatorsPerDayLimit = 100 + const limitsList = [churnValidatorsPerDayLimit, 0, 0, 0, 32 * 12, 15, 16, 0, 0] + const managersRoster = [[admin], [admin], [admin], [admin], [admin], [admin], [admin], [admin], [admin], [admin]] + + const OracleReportSanityChecker = artifacts.require('OracleReportSanityChecker') + + const oracleReportSanityChecker = await OracleReportSanityChecker.new( + lidoLocator, + admin, + limitsList, + managersRoster, + { + from: admin, + } + ) + return oracleReportSanityChecker } + async function deployMockLegacyOracle({ epochsPerFrame = EPOCHS_PER_FRAME, slotsPerEpoch = SLOTS_PER_EPOCH, @@ -179,15 +184,14 @@ async function deployMockLidoAndStakingRouter() { async function deployAccountingOracleSetup( admin, { - initialEpoch = null, epochsPerFrame = EPOCHS_PER_FRAME, slotsPerEpoch = SLOTS_PER_EPOCH, secondsPerSlot = SECONDS_PER_SLOT, genesisTime = GENESIS_TIME, getLidoAndStakingRouter = deployMockLidoAndStakingRouter, getLegacyOracle = deployMockLegacyOracle, - lidoLocatorAddr: lidoLocatorAddrArg, - legacyOracleAddr: legacyOracleAddrArg, + lidoLocatorAddr = null, + legacyOracleAddr = null, } = {} ) { const locatorAddr = (await deployLocatorWithDummyAddressesImplementation(admin)).address @@ -203,32 +207,29 @@ async function deployAccountingOracleSetup( const legacyOracle = await getLegacyOracle() - if (initialEpoch == null) { - initialEpoch = +(await legacyOracle.getLastCompletedEpochId()) + epochsPerFrame - } - const oracle = await AccountingOracle.new( - lidoLocatorAddrArg || locatorAddr, + lidoLocatorAddr || locatorAddr, lido.address, - legacyOracleAddrArg || legacyOracle.address, + legacyOracleAddr || legacyOracle.address, secondsPerSlot, genesisTime, { from: admin } ) + // deploy hash consensus without setting the initial epoch since we won't know at the moment of the actual deploy const { consensus } = await deployHashConsensus(admin, { reportProcessor: oracle, + initialEpoch: null, epochsPerFrame, slotsPerEpoch, secondsPerSlot, genesisTime, - initialEpoch, }) - // pretend we're at the first slot of the initial frame's epoch - await consensus.setTime(genesisTime + initialEpoch * slotsPerEpoch * secondsPerSlot) + await consensus.setTime(genesisTime) return { + admin, lido, stakingRouter, withdrawalQueue, @@ -240,6 +241,25 @@ async function deployAccountingOracleSetup( } } +async function configureAccountingOracleSetup({ + admin, + consensus, + oracle, + legacyOracle, + dataSubmitter = null, + consensusVersion = CONSENSUS_VERSION, +} = {}) { + // this is done as a part of the protocol upgrade voting execution + + const frameConfig = await consensus.getFrameConfig() + const initialEpoch = +(await legacyOracle.getLastCompletedEpochId()) + +frameConfig.epochsPerFrame + + const updateInitialEpochIx = await consensus.updateInitialEpoch(initialEpoch, { from: admin }) + const initTx = await initAccountingOracle({ admin, oracle, consensus, dataSubmitter, consensusVersion }) + + return { updateInitialEpochIx, initTx } +} + async function initAccountingOracle({ admin, oracle, @@ -265,9 +285,37 @@ async function initAccountingOracle({ } async function deployAndConfigureAccountingOracle(admin) { + /// this is done (far) before the protocol upgrade voting initiation: + /// 1. deploy HashConsensus + /// 2. deploy AccountingOracle impl const deployed = await deployAccountingOracleSetup(admin) - const initTx = await initAccountingOracle({ admin, ...deployed }) - return { ...deployed, initTx } + + // pretend we're after the legacy oracle's last proc epoch but before the new oracle's initial epoch + assert.isAbove(EPOCHS_PER_FRAME, 1) + const voteExecTime = GENESIS_TIME + (V1_ORACLE_LAST_COMPLETED_EPOCH + 1) * SLOTS_PER_EPOCH * SECONDS_PER_SLOT + await deployed.consensus.setTime(voteExecTime) + + /// this is done as a part of the protocol upgrade voting execution: + /// 1. calculate HashConsensus initial epoch as the last finalized legacy epoch + frame size + /// 2. set HashConsensus initial epoch + /// 3. deploy AccountingOracle proxy (skipped in these tests as they're not testing the proxy setup) + /// 4. initialize AccountingOracle + const finalizeResult = await configureAccountingOracleSetup(deployed) + + // pretend we're at the first slot of the new oracle's initial epoch + const initialEpoch = V1_ORACLE_LAST_COMPLETED_EPOCH + EPOCHS_PER_FRAME + await deployed.consensus.setTime(GENESIS_TIME + initialEpoch * SLOTS_PER_EPOCH * SECONDS_PER_SLOT) + + return { ...deployed, ...finalizeResult } +} + +async function getInitialFrameStartTime(consensus) { + const chainConfig = await consensus.getChainConfig() + const frameConfig = await consensus.getFrameConfig() + return toBN(frameConfig.initialEpoch) + .muln(+chainConfig.slotsPerEpoch) + .muln(+chainConfig.secondsPerSlot) + .add(toBN(chainConfig.genesisTime)) } contract('AccountingOracle', ([admin, member1]) => { @@ -279,20 +327,30 @@ contract('AccountingOracle', ([admin, member1]) => { let legacyOracle context('Deployment and initial configuration', () => { + const updateInitialEpoch = async (consensus) => { + // pretend we're after the legacy oracle's last proc epoch but before the new oracle's initial epoch + const voteExecTime = GENESIS_TIME + (V1_ORACLE_LAST_COMPLETED_EPOCH + 1) * SLOTS_PER_EPOCH * SECONDS_PER_SLOT + await consensus.setTime(voteExecTime) + await consensus.updateInitialEpoch(V1_ORACLE_LAST_COMPLETED_EPOCH + EPOCHS_PER_FRAME) + } + it('init fails if the chain config is different from the one of the legacy oracle', async () => { let deployed = await deployAccountingOracleSetup(admin, { getLegacyOracle: () => deployMockLegacyOracle({ slotsPerEpoch: SLOTS_PER_EPOCH + 1 }), }) + await updateInitialEpoch(deployed.consensus) await assert.reverts(initAccountingOracle({ admin, ...deployed }), 'IncorrectOracleMigration(0)') deployed = await deployAccountingOracleSetup(admin, { getLegacyOracle: () => deployMockLegacyOracle({ secondsPerSlot: SECONDS_PER_SLOT + 1 }), }) + await updateInitialEpoch(deployed.consensus) await assert.reverts(initAccountingOracle({ admin, ...deployed }), 'IncorrectOracleMigration(0)') deployed = await deployAccountingOracleSetup(admin, { getLegacyOracle: () => deployMockLegacyOracle({ genesisTime: GENESIS_TIME + 1 }), }) + await updateInitialEpoch(deployed.consensus) await assert.reverts(initAccountingOracle({ admin, ...deployed }), 'IncorrectOracleMigration(0)') }) @@ -300,26 +358,41 @@ contract('AccountingOracle', ([admin, member1]) => { const deployed = await deployAccountingOracleSetup(admin, { getLegacyOracle: () => deployMockLegacyOracle({ epochsPerFrame: EPOCHS_PER_FRAME - 1 }), }) + await updateInitialEpoch(deployed.consensus) await assert.reverts(initAccountingOracle({ admin, ...deployed }), 'IncorrectOracleMigration(1)') }) it(`init fails if the initial epoch of the new oracle is not the next frame's first epoch`, async () => { - const deployed = await deployAccountingOracleSetup(admin, { initialEpoch: 3 + 10 * EPOCHS_PER_FRAME }) + const deployed = await deployAccountingOracleSetup(admin) + + const voteExecTime = GENESIS_TIME + (V1_ORACLE_LAST_COMPLETED_EPOCH + 1) * SLOTS_PER_EPOCH * SECONDS_PER_SLOT + await deployed.consensus.setTime(voteExecTime) - await deployed.legacyOracle.setLastCompletedEpochId(3 + 11 * EPOCHS_PER_FRAME) + const snapshot = new EvmSnapshot(ethers.provider) + await snapshot.make() + + await deployed.consensus.updateInitialEpoch(V1_ORACLE_LAST_COMPLETED_EPOCH + EPOCHS_PER_FRAME - 1) await assert.reverts(initAccountingOracle({ admin, ...deployed }), 'IncorrectOracleMigration(2)') + await snapshot.rollback() - await deployed.legacyOracle.setLastCompletedEpochId(3 + 10 * EPOCHS_PER_FRAME) + await deployed.consensus.updateInitialEpoch(V1_ORACLE_LAST_COMPLETED_EPOCH + EPOCHS_PER_FRAME + 1) await assert.reverts(initAccountingOracle({ admin, ...deployed }), 'IncorrectOracleMigration(2)') + await snapshot.rollback() - await deployed.legacyOracle.setLastCompletedEpochId(3 + 9 * EPOCHS_PER_FRAME + 1) + await deployed.consensus.updateInitialEpoch(V1_ORACLE_LAST_COMPLETED_EPOCH + 2 * EPOCHS_PER_FRAME) await assert.reverts(initAccountingOracle({ admin, ...deployed }), 'IncorrectOracleMigration(2)') + await snapshot.rollback() }) it('deployment and init finishes successfully otherwise', async () => { - const deployed = await deployAccountingOracleSetup(admin, { initialEpoch: 3 + 10 * EPOCHS_PER_FRAME }) - await deployed.legacyOracle.setLastCompletedEpochId(3 + 9 * EPOCHS_PER_FRAME) + const deployed = await deployAccountingOracleSetup(admin) + + const voteExecTime = GENESIS_TIME + (V1_ORACLE_LAST_COMPLETED_EPOCH + 1) * SLOTS_PER_EPOCH * SECONDS_PER_SLOT + await deployed.consensus.setTime(voteExecTime) + await deployed.consensus.updateInitialEpoch(V1_ORACLE_LAST_COMPLETED_EPOCH + EPOCHS_PER_FRAME) + await initAccountingOracle({ admin, ...deployed }) + const refSlot = await deployed.oracle.getLastProcessingRefSlot() const epoch = await deployed.legacyOracle.getLastCompletedEpochId() assert.equals(refSlot, epoch.muln(SLOTS_PER_EPOCH)) @@ -371,14 +444,14 @@ contract('AccountingOracle', ([admin, member1]) => { assert.equals(await oracle.SECONDS_PER_SLOT(), SECONDS_PER_SLOT) }) - it('reverts if lido locator address is zero', async () => { + it('constructor reverts if lido locator address is zero', async () => { await assert.reverts( deployAccountingOracleSetup(admin, { lidoLocatorAddr: ZERO_ADDRESS }), 'LidoLocatorCannotBeZero()' ) }) - it('reverts if legacy oracle address is zero', async () => { + it('constructor reverts if legacy oracle address is zero', async () => { await assert.reverts( deployAccountingOracleSetup(admin, { legacyOracleAddr: ZERO_ADDRESS }), 'LegacyOracleCannotBeZero()' @@ -386,26 +459,30 @@ contract('AccountingOracle', ([admin, member1]) => { }) it('initialize reverts if admin address is zero', async () => { - const { consensus } = await deployAccountingOracleSetup(admin) + const deployed = await deployAccountingOracleSetup(admin) + await updateInitialEpoch(deployed.consensus) await assert.reverts( - oracle.initialize(ZERO_ADDRESS, consensus.address, CONSENSUS_VERSION, { from: admin }), + deployed.oracle.initialize(ZERO_ADDRESS, deployed.consensus.address, CONSENSUS_VERSION, { from: admin }), 'AdminCannotBeZero()' ) }) it('initializeWithoutMigration reverts if admin address is zero', async () => { - const { consensus } = await deployAccountingOracleSetup(admin) - const { refSlot } = await consensus.getCurrentFrame() + const deployed = await deployAccountingOracleSetup(admin) + await updateInitialEpoch(deployed.consensus) + await assert.reverts( - oracle.initializeWithoutMigration(ZERO_ADDRESS, consensus.address, CONSENSUS_VERSION, refSlot, { from: admin }), + deployed.oracle.initializeWithoutMigration(ZERO_ADDRESS, deployed.consensus.address, CONSENSUS_VERSION, 0, { + from: admin, + }), 'AdminCannotBeZero()' ) }) - it('initializeWithoutMigration succeeds', async () => { + it('initializeWithoutMigration succeeds otherwise', async () => { const deployed = await deployAccountingOracleSetup(admin) - const { refSlot } = await deployed.consensus.getCurrentFrame() - await deployed.oracle.initializeWithoutMigration(admin, deployed.consensus.address, CONSENSUS_VERSION, refSlot, { + await updateInitialEpoch(deployed.consensus) + await deployed.oracle.initializeWithoutMigration(admin, deployed.consensus.address, CONSENSUS_VERSION, 0, { from: admin, }) }) 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 eb6a4ff73..ed526424e 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 @@ -57,8 +57,8 @@ contract('BaseOracle', ([admin, account1, account2, member1, member2]) => { SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - INITIAL_FAST_LANE_LENGTH_SLOTS, INITIAL_EPOCH, + INITIAL_FAST_LANE_LENGTH_SLOTS, 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 067039e90..6432eaacf 100644 --- a/test/0.8.9/oracle/base-oracle-deploy.test.js +++ b/test/0.8.9/oracle/base-oracle-deploy.test.js @@ -53,8 +53,8 @@ async function deployBaseOracle( secondsPerSlot, genesisTime, epochsPerFrame, - fastLaneLengthSlots, initialEpoch, + fastLaneLengthSlots, mockMember, { from: admin } ) 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 28e857dee..cbd55a5bf 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 @@ -9,7 +9,6 @@ const { SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - SLOTS_PER_FRAME, HASH_1, HASH_2, CONSENSUS_VERSION, @@ -52,7 +51,7 @@ contract('BaseOracle', ([admin, member, notMember]) => { SECONDS_PER_SLOT + 1, GENESIS_TIME + 1, EPOCHS_PER_FRAME, - 0, + 1, 0, admin, { from: admin } @@ -63,24 +62,28 @@ contract('BaseOracle', ([admin, member, notMember]) => { ) }) - it('reverts on consensus current frame behind current processing', async () => { + it('reverts on consensus initial ref slot behind currently processing', async () => { + const processingRefSlot = 100 + + await consensus.submitReportAsConsensus(HASH_1, processingRefSlot, +(await baseOracle.getTime()) + 1) + await baseOracle.startProcessing() + const wrongConsensusContract = await MockConsensusContract.new( SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - 0, + 1, 0, admin, { from: admin } ) - await wrongConsensusContract.setCurrentFrame(10, 1, 2000) - await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) - await baseOracle.startProcessing() + + await wrongConsensusContract.setInitialRefSlot(processingRefSlot - 1) await assert.revertsWithCustomError( baseOracle.setConsensusContract(wrongConsensusContract.address), - `RefSlotCannotBeLessThanProcessingOne(1, ${initialRefSlot})` + `InitialRefSlotCannotBeLessThanProcessingOne(${processingRefSlot - 1}, ${processingRefSlot})` ) }) @@ -90,12 +93,12 @@ contract('BaseOracle', ([admin, member, notMember]) => { SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - 0, + 1, 0, admin, { from: admin } ) - await newConsensusContract.setCurrentFrame(10, initialRefSlot + 1, initialRefSlot + SLOTS_PER_FRAME) + await newConsensusContract.setInitialRefSlot(initialRefSlot) const tx = await baseOracle.setConsensusContract(newConsensusContract.address) assert.emits(tx, 'ConsensusHashContractSet', { addr: newConsensusContract.address, prevAddr: consensus.address }) const addressAtStorage = await baseOracle.getConsensusContract() diff --git a/test/0.8.9/oracle/hash-consensus-frames.test.js b/test/0.8.9/oracle/hash-consensus-frames.test.js index c967e5af1..d1120ccbd 100644 --- a/test/0.8.9/oracle/hash-consensus-frames.test.js +++ b/test/0.8.9/oracle/hash-consensus-frames.test.js @@ -95,17 +95,21 @@ contract('HashConsensus', ([admin, member1, member2]) => { }) context('State before initial epoch', () => { - let consensus + let consensus, reportProcessor before(async () => { const deployed = await deployHashConsensus(admin, { initialEpoch: null }) consensus = deployed.consensus + reportProcessor = deployed.reportProcessor }) it(`after deploy, the initial epoch is far in the future`, async () => { const maxTimestamp = toBN(2).pow(toBN(64)).subn(1) const maxEpoch = maxTimestamp.subn(GENESIS_TIME).divn(SECONDS_PER_SLOT).divn(SLOTS_PER_EPOCH) assert.equals((await consensus.getFrameConfig()).initialEpoch, maxEpoch) + + const initialRefSlot = await consensus.getInitialRefSlot() + assert.equals(initialRefSlot, maxEpoch.muln(SLOTS_PER_EPOCH).subn(1)) }) it(`after deploy, one can update initial epoch`, async () => { @@ -120,6 +124,23 @@ contract('HashConsensus', ([admin, member1, member2]) => { assert.equals(frameConfig.initialEpoch, TEST_INITIAL_EPOCH) assert.equals(frameConfig.epochsPerFrame, EPOCHS_PER_FRAME) assert.equals(frameConfig.fastLaneLengthSlots, INITIAL_FAST_LANE_LENGTH_SLOTS) + + const initialRefSlot = await consensus.getInitialRefSlot() + assert.equals(initialRefSlot, +frameConfig.initialEpoch * SLOTS_PER_EPOCH - 1) + }) + + it(`one cannot update initial epoch so that initial ref slot is less than processed one`, async () => { + await consensus.setTimeInEpochs(TEST_INITIAL_EPOCH - 2) + + const initialRefSlot = TEST_INITIAL_EPOCH * SLOTS_PER_EPOCH - 1 + await reportProcessor.setLastProcessingStartedRefSlot(initialRefSlot + 1) + + assert.reverts( + consensus.updateInitialEpoch(TEST_INITIAL_EPOCH, { from: admin }), + 'InitialEpochRefSlotCannotBeEarlierThanProcessingSlot()' + ) + + await reportProcessor.setLastProcessingStartedRefSlot(0) }) it(`before the initial epoch arrives, one can update it freely`, async () => { @@ -130,6 +151,9 @@ contract('HashConsensus', ([admin, member1, member2]) => { await consensus.updateInitialEpoch(TEST_INITIAL_EPOCH, { from: admin }) assert.equals((await consensus.getFrameConfig()).initialEpoch, TEST_INITIAL_EPOCH) + + const initialRefSlot = await consensus.getInitialRefSlot() + assert.equals(initialRefSlot, TEST_INITIAL_EPOCH * SLOTS_PER_EPOCH - 1) }) it('before the initial epoch arrives, members can be added and queried, and quorum increased', async () => { diff --git a/test/scenario/changing_oracles_during_epoch.test.js b/test/scenario/changing_oracles_during_epoch.test.js index 2c0de7380..2372ee16c 100644 --- a/test/scenario/changing_oracles_during_epoch.test.js +++ b/test/scenario/changing_oracles_during_epoch.test.js @@ -5,10 +5,10 @@ const { e9 } = require('../helpers/utils') const { deployAccountingOracleSetup, - initAccountingOracle, + configureAccountingOracleSetup, + getInitialFrameStartTime, deployMockLegacyOracle, CONSENSUS_VERSION, - HASH_1, ZERO_HASH, getReportDataItems, calcReportDataHash, @@ -19,9 +19,6 @@ const SECONDS_PER_SLOT = 12 const GENESIS_TIME = 1606824000 const EPOCHS_PER_FRAME = 225 -const SLOTS_PER_FRAME = EPOCHS_PER_FRAME * SLOTS_PER_EPOCH -const SECONDS_PER_FRAME = SLOTS_PER_FRAME * SECONDS_PER_SLOT - contract('AccountingOracle', ([voting, malicious1, malicious2, member1, member2, member3]) => { let lido, consensus, oracle @@ -64,48 +61,44 @@ contract('AccountingOracle', ([voting, malicious1, malicious2, member1, member2, consensus = deployed.consensus oracle = deployed.oracle - await initAccountingOracle({ ...deployed, admin: voting }) - - assert.equals(await oracle.getTime(), GENESIS_TIME + SECONDS_PER_FRAME) + await configureAccountingOracleSetup({ ...deployed, admin: voting }) + await consensus.setTime(await getInitialFrameStartTime(consensus)) await consensus.addMember(member1, 4, { from: voting }) await consensus.addMember(member2, 4, { from: voting }) }) - it('reverts with zero ref. slot', async () => { - assert.equals((await consensus.getCurrentFrame()).refSlot, 1 * SLOTS_PER_FRAME - 1) - await assert.reverts(consensus.submitReport(0, HASH_1, CONSENSUS_VERSION, { from: member1 }), 'InvalidSlot()') - }) + it('oracle contract handles changing the oracles during epoch', async () => { + const { refSlot } = await consensus.getCurrentFrame() - it('oracle conract handles changing the oracles during epoch', async () => { await consensus.addMember(malicious1, 4, { from: voting }) await consensus.addMember(malicious2, 4, { from: voting }) - const goodDataItems = getReportDataItems({ ...GOOD_DATA, refSlot: SLOTS_PER_FRAME - 1 }) - const badDataItems = getReportDataItems({ ...BAD_DATA, refSlot: SLOTS_PER_FRAME - 1 }) + const goodDataItems = getReportDataItems({ ...GOOD_DATA, refSlot }) + const badDataItems = getReportDataItems({ ...BAD_DATA, refSlot }) const goodDataHash = calcReportDataHash(goodDataItems) const badDataHash = calcReportDataHash(badDataItems) - await consensus.submitReport(SLOTS_PER_FRAME - 1, badDataHash, CONSENSUS_VERSION, { from: malicious1 }) - await consensus.submitReport(SLOTS_PER_FRAME - 1, badDataHash, CONSENSUS_VERSION, { from: malicious2 }) - await consensus.submitReport(SLOTS_PER_FRAME - 1, goodDataHash, CONSENSUS_VERSION, { from: member1 }) - await consensus.submitReport(SLOTS_PER_FRAME - 1, goodDataHash, CONSENSUS_VERSION, { from: member2 }) + await consensus.submitReport(refSlot, badDataHash, CONSENSUS_VERSION, { from: malicious1 }) + await consensus.submitReport(refSlot, badDataHash, CONSENSUS_VERSION, { from: malicious2 }) + await consensus.submitReport(refSlot, goodDataHash, CONSENSUS_VERSION, { from: member1 }) + await consensus.submitReport(refSlot, goodDataHash, CONSENSUS_VERSION, { from: member2 }) await consensus.removeMember(malicious1, 3, { from: voting }) await consensus.removeMember(malicious2, 3, { from: voting }) await consensus.addMember(member3, 3, { from: voting }) - let tx = await consensus.submitReport(SLOTS_PER_FRAME - 1, goodDataHash, CONSENSUS_VERSION, { from: member3 }) + let tx = await consensus.submitReport(refSlot, goodDataHash, CONSENSUS_VERSION, { from: member3 }) assert.emits(tx, 'ConsensusReached', { - refSlot: SLOTS_PER_FRAME - 1, + refSlot: +refSlot, report: goodDataHash, support: 3, }) tx = await oracle.submitReportData(goodDataItems, await oracle.getContractVersion(), { from: member3 }) - assert.emits(tx, 'ProcessingStarted', { refSlot: SLOTS_PER_FRAME - 1 }) + assert.emits(tx, 'ProcessingStarted', { refSlot: +refSlot }) const lastHandleOracleReportCall = await lido.getLastCall_handleOracleReport() assert.equals(lastHandleOracleReportCall.clBalance, e9(GOOD_DATA.clBalanceGwei)) From 2a5606c83ff14fae251276abcb93dbe21269609c Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Wed, 1 Mar 2023 16:02:43 +0200 Subject: [PATCH 084/236] abi: update --- lib/abi/AccountingOracle.json | 2 +- lib/abi/BaseOracle.json | 2 +- lib/abi/HashConsensus.json | 2 +- lib/abi/IConsensusContract.json | 2 +- lib/abi/ValidatorsExitBusOracle.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/abi/AccountingOracle.json b/lib/abi/AccountingOracle.json index 6def379da..689550193 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":"ExtraDataHashCannotBeZeroForNonEmptyData","type":"error"},{"inputs":[],"name":"ExtraDataItemsCountCannotBeZeroForNonEmptyData","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":[],"name":"RefSlotAlreadyProcessing","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":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedExtraDataHash","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_EMPTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"bool","name":"extraDataSubmitted","type":"bool"},{"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":[],"name":"submitReportExtraDataEmpty","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":"ExtraDataHashCannotBeZeroForNonEmptyData","type":"error"},{"inputs":[],"name":"ExtraDataItemsCountCannotBeZeroForNonEmptyData","type":"error"},{"inputs":[],"name":"ExtraDataListOnlySupportsSingleTx","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"IncorrectOracleMigration","type":"error"},{"inputs":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","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":[],"name":"RefSlotAlreadyProcessing","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":"bytes32","name":"consensusHash","type":"bytes32"},{"internalType":"bytes32","name":"receivedHash","type":"bytes32"}],"name":"UnexpectedExtraDataHash","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_EMPTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"bool","name":"extraDataSubmitted","type":"bool"},{"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":[],"name":"submitReportExtraDataEmpty","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 e667ae05c..bf2b9de68 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":[],"name":"RefSlotAlreadyProcessing","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 +[{"inputs":[],"name":"AddressCannotBeSame","type":"error"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","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":[],"name":"RefSlotAlreadyProcessing","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/HashConsensus.json b/lib/abi/HashConsensus.json index ab3abbbbd..d286ffdf6 100644 --- a/lib/abi/HashConsensus.json +++ b/lib/abi/HashConsensus.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"reportProcessor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ConsensusReportAlreadyProcessing","type":"error"},{"inputs":[],"name":"DuplicateMember","type":"error"},{"inputs":[],"name":"DuplicateReport","type":"error"},{"inputs":[],"name":"EmptyReport","type":"error"},{"inputs":[],"name":"EpochsPerFrameCannotBeZero","type":"error"},{"inputs":[],"name":"FastLanePeriodCannotBeLongerThanFrame","type":"error"},{"inputs":[],"name":"InitialEpochAlreadyArrived","type":"error"},{"inputs":[],"name":"InitialEpochIsYetToArrive","type":"error"},{"inputs":[],"name":"InvalidSlot","type":"error"},{"inputs":[],"name":"NewProcessorCannotBeTheSame","type":"error"},{"inputs":[],"name":"NonFastLaneMemberCannotReportWithinFastLaneInterval","type":"error"},{"inputs":[],"name":"NonMember","type":"error"},{"inputs":[],"name":"NumericOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"minQuorum","type":"uint256"},{"internalType":"uint256","name":"receivedQuorum","type":"uint256"}],"name":"QuorumTooSmall","type":"error"},{"inputs":[],"name":"ReportProcessorCannotBeZero","type":"error"},{"inputs":[],"name":"StaleReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"support","type":"uint256"}],"name":"ConsensusReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"FastLaneConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newInitialEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEpochsPerFrame","type":"uint256"}],"name":"FrameConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"prevQuorum","type":"uint256"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processor","type":"address"},{"indexed":true,"internalType":"address","name":"prevProcessor","type":"address"}],"name":"ReportProcessorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"}],"name":"ReportReceived","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISABLE_CONSENSUS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FAST_LANE_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FRAME_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_MEMBERS_AND_QUORUM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_REPORT_PROCESSOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableConsensus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusState","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"bytes32","name":"consensusReport","type":"bytes32"},{"internalType":"bool","name":"isReportProcessing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getConsensusStateForMember","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameConsensusReport","type":"bytes32"},{"internalType":"bool","name":"isMember","type":"bool"},{"internalType":"bool","name":"isFastLane","type":"bool"},{"internalType":"bool","name":"canReport","type":"bool"},{"internalType":"uint256","name":"lastMemberReportRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameMemberReport","type":"bytes32"}],"internalType":"struct HashConsensus.MemberConsensusState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastLaneMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsFastLaneMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportVariants","outputs":[{"internalType":"bytes32[]","name":"variants","type":"bytes32[]"},{"internalType":"uint256[]","name":"support","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":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"removeMember","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":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFastLaneLengthSlots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFrameConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"setQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProcessor","type":"address"}],"name":"setReportProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"bytes32","name":"report","type":"bytes32"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"submitReport","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":"initialEpoch","type":"uint256"}],"name":"updateInitialEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"reportProcessor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"AdminCannotBeZero","type":"error"},{"inputs":[],"name":"ConsensusReportAlreadyProcessing","type":"error"},{"inputs":[],"name":"DuplicateMember","type":"error"},{"inputs":[],"name":"DuplicateReport","type":"error"},{"inputs":[],"name":"EmptyReport","type":"error"},{"inputs":[],"name":"EpochsPerFrameCannotBeZero","type":"error"},{"inputs":[],"name":"FastLanePeriodCannotBeLongerThanFrame","type":"error"},{"inputs":[],"name":"InitialEpochAlreadyArrived","type":"error"},{"inputs":[],"name":"InitialEpochIsYetToArrive","type":"error"},{"inputs":[],"name":"InitialEpochRefSlotCannotBeEarlierThanProcessingSlot","type":"error"},{"inputs":[],"name":"InvalidSlot","type":"error"},{"inputs":[],"name":"NewProcessorCannotBeTheSame","type":"error"},{"inputs":[],"name":"NonFastLaneMemberCannotReportWithinFastLaneInterval","type":"error"},{"inputs":[],"name":"NonMember","type":"error"},{"inputs":[],"name":"NumericOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"minQuorum","type":"uint256"},{"internalType":"uint256","name":"receivedQuorum","type":"uint256"}],"name":"QuorumTooSmall","type":"error"},{"inputs":[],"name":"ReportProcessorCannotBeZero","type":"error"},{"inputs":[],"name":"StaleReport","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedConsensusVersion","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"support","type":"uint256"}],"name":"ConsensusReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"FastLaneConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newInitialEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEpochsPerFrame","type":"uint256"}],"name":"FrameConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"newTotalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"}],"name":"MemberRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newQuorum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalMembers","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"prevQuorum","type":"uint256"}],"name":"QuorumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processor","type":"address"},{"indexed":true,"internalType":"address","name":"prevProcessor","type":"address"}],"name":"ReportProcessorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refSlot","type":"uint256"},{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"bytes32","name":"report","type":"bytes32"}],"name":"ReportReceived","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISABLE_CONSENSUS_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FAST_LANE_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_FRAME_CONFIG_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_MEMBERS_AND_QUORUM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_REPORT_PROCESSOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableConsensus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusState","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"bytes32","name":"consensusReport","type":"bytes32"},{"internalType":"bool","name":"isReportProcessing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getConsensusStateForMember","outputs":[{"components":[{"internalType":"uint256","name":"currentFrameRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameConsensusReport","type":"bytes32"},{"internalType":"bool","name":"isMember","type":"bool"},{"internalType":"bool","name":"isFastLane","type":"bool"},{"internalType":"bool","name":"canReport","type":"bool"},{"internalType":"uint256","name":"lastMemberReportRefSlot","type":"uint256"},{"internalType":"bytes32","name":"currentFrameMemberReport","type":"bytes32"}],"internalType":"struct HashConsensus.MemberConsensusState","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastLaneMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInitialRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsFastLaneMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMembers","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"lastReportedRefSlots","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportVariants","outputs":[{"internalType":"bytes32[]","name":"variants","type":"bytes32[]"},{"internalType":"uint256[]","name":"support","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":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"removeMember","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":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFastLaneLengthSlots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"},{"internalType":"uint256","name":"fastLaneLengthSlots","type":"uint256"}],"name":"setFrameConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"setQuorum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProcessor","type":"address"}],"name":"setReportProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"bytes32","name":"report","type":"bytes32"},{"internalType":"uint256","name":"consensusVersion","type":"uint256"}],"name":"submitReport","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":"initialEpoch","type":"uint256"}],"name":"updateInitialEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/IConsensusContract.json b/lib/abi/IConsensusContract.json index fc4dd8feb..f579c86d0 100644 --- a/lib/abi/IConsensusContract.json +++ b/lib/abi/IConsensusContract.json @@ -1 +1 @@ -[{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[],"name":"getChainConfig","outputs":[{"internalType":"uint256","name":"slotsPerEpoch","type":"uint256"},{"internalType":"uint256","name":"secondsPerSlot","type":"uint256"},{"internalType":"uint256","name":"genesisTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentFrame","outputs":[{"internalType":"uint256","name":"refSlot","type":"uint256"},{"internalType":"uint256","name":"reportProcessingDeadlineSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrameConfig","outputs":[{"internalType":"uint256","name":"initialEpoch","type":"uint256"},{"internalType":"uint256","name":"epochsPerFrame","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInitialRefSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getIsMember","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 2b226780f..8a8260583 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":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":[],"name":"getResumeSinceTimestamp","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":"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":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":[],"name":"getResumeSinceTimestamp","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":"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 From 843a14e242e823b113b469207741330d560b0ece Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 1 Mar 2023 20:10:43 +0400 Subject: [PATCH 085/236] Always cache staking module active keys --- contracts/0.8.9/StakingRouter.sol | 58 +++++++------ ...ing-router-allocation-combinations.test.js | 83 ++++++++++++++++++- 2 files changed, 110 insertions(+), 31 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index c8f8de204..fdff95cdc 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -856,7 +856,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 precisionPoints ) { - (uint256 totalActiveValidators, StakingModuleCache[] memory stakingModulesCache) = _loadStakingModulesCache(false); + (uint256 totalActiveValidators, StakingModuleCache[] memory stakingModulesCache) = _loadStakingModulesCache(); uint256 stakingModulesCount = stakingModulesCache.length; /// @dev return empty response if there are no staking modules or active validators yet @@ -1043,24 +1043,18 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version } } - /** - * @dev load modules into a memory cache - * - * @param _zeroValidatorsCountsOfInactiveModules if true, active and available validators for - * inactive modules are set to zero - * - * @return totalActiveValidators total active validators across all modules (excluding inactive - * if _zeroValidatorsCountsOfInactiveModules is true) - * @return stakingModulesCache array of StakingModuleCache structs - */ - function _loadStakingModulesCache(bool _zeroValidatorsCountsOfInactiveModules) internal view returns ( + /// @dev load modules into a memory cache + /// + /// @return totalActiveValidators total active validators across all modules + /// @return stakingModulesCache array of StakingModuleCache structs + function _loadStakingModulesCache() internal view returns ( uint256 totalActiveValidators, StakingModuleCache[] memory stakingModulesCache ) { uint256 stakingModulesCount = getStakingModulesCount(); stakingModulesCache = new StakingModuleCache[](stakingModulesCount); for (uint256 i; i < stakingModulesCount; ) { - stakingModulesCache[i] = _loadStakingModulesCacheItem(i, _zeroValidatorsCountsOfInactiveModules); + stakingModulesCache[i] = _loadStakingModulesCacheItem(i); totalActiveValidators += stakingModulesCache[i].activeValidatorsCount; unchecked { ++i; @@ -1068,10 +1062,11 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version } } - function _loadStakingModulesCacheItem( - uint256 _stakingModuleIndex, - bool _zeroValidatorsCountsIfInactive - ) internal view returns (StakingModuleCache memory cacheItem) { + function _loadStakingModulesCacheItem(uint256 _stakingModuleIndex) + internal + view + returns (StakingModuleCache memory cacheItem) + { StakingModule storage stakingModuleData = _getStakingModuleByIndex(_stakingModuleIndex); cacheItem.stakingModuleAddress = stakingModuleData.stakingModuleAddress; @@ -1081,18 +1076,21 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version cacheItem.targetShare = stakingModuleData.targetShare; cacheItem.status = StakingModuleStatus(stakingModuleData.status); - if (!_zeroValidatorsCountsIfInactive || cacheItem.status == StakingModuleStatus.Active) { - uint256 totalExitedValidators; - uint256 totalDepositedValidators; - (totalExitedValidators, totalDepositedValidators, cacheItem.availableValidatorsCount) - = IStakingModule(cacheItem.stakingModuleAddress).getStakingModuleSummary(); - - // the module might not receive all exited validators data yet => we need to replacing - // the exitedValidatorsCount with the one that the staking router is aware of - cacheItem.activeValidatorsCount = - totalDepositedValidators - - Math256.max(totalExitedValidators, stakingModuleData.exitedValidatorsCount); - } + ( + uint256 totalExitedValidators, + uint256 totalDepositedValidators, + uint256 depositableValidatorsCount + ) = IStakingModule(cacheItem.stakingModuleAddress).getStakingModuleSummary(); + + cacheItem.availableValidatorsCount = cacheItem.status == StakingModuleStatus.Active + ? depositableValidatorsCount + : 0; + + // the module might not receive all exited validators data yet => we need to replacing + // the exitedValidatorsCount with the one that the staking router is aware of + cacheItem.activeValidatorsCount = + totalDepositedValidators - + Math256.max(totalExitedValidators, stakingModuleData.exitedValidatorsCount); } function _getDepositsAllocation( @@ -1101,7 +1099,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version // calculate total used validators for operators uint256 totalActiveValidators; - (totalActiveValidators, stakingModulesCache) = _loadStakingModulesCache(true); + (totalActiveValidators, stakingModulesCache) = _loadStakingModulesCache(); uint256 stakingModulesCount = stakingModulesCache.length; allocations = new uint256[](stakingModulesCount); diff --git a/test/0.8.9/staking-router/staking-router-allocation-combinations.test.js b/test/0.8.9/staking-router/staking-router-allocation-combinations.test.js index 2c31f922a..e223a37f2 100644 --- a/test/0.8.9/staking-router/staking-router-allocation-combinations.test.js +++ b/test/0.8.9/staking-router/staking-router-allocation-combinations.test.js @@ -10,7 +10,7 @@ const BASIS_POINTS_BASE = 100_00 contract('StakingRouter', (accounts) => { let evmSnapshotId let depositContract, stakingRouter - let StakingModule1, StakingModule2 + let StakingModule1, StakingModule2, StakingModule3 const [deployer, lido, admin] = accounts before(async () => { @@ -19,10 +19,12 @@ contract('StakingRouter', (accounts) => { const mocks = await Promise.all([ StakingModuleMock.new({ from: deployer }), StakingModuleMock.new({ from: deployer }), + StakingModuleMock.new({ from: deployer }), ]) StakingModule1 = mocks[0] StakingModule2 = mocks[1] + StakingModule3 = mocks[2] const wc = '0x'.padEnd(66, '1234') await stakingRouter.initialize(admin, lido, wc, { from: deployer }) @@ -56,6 +58,85 @@ contract('StakingRouter', (accounts) => { const MODULE_AVAILABLE_KEYS_CASES = [0, 1, 10_000] const MODULE_ACTIVE_KEYS_CASES = [0, 1, 10_000] + describe('Deposits allocation with paused modules', () => { + it('allocates correctly if some staking modules are paused', async () => { + // add staking module 1 + await stakingRouter.addStakingModule( + 'Module 1', + StakingModule1.address, + 100_00, // target share BP + 10_00, // staking module fee BP + 50_00, // treasury fee BP + { from: admin } + ) + + const sm1AvailableKeysCount = 100 + await StakingModule1.setAvailableKeysCount(sm1AvailableKeysCount) + assert.equals(await StakingModule1.getAvailableValidatorsCount(), sm1AvailableKeysCount) + + const sm1ActiveKeysCount = 15000 + await StakingModule1.setActiveValidatorsCount(sm1ActiveKeysCount) + assert.equals(await StakingModule1.getActiveValidatorsCount(), sm1ActiveKeysCount) + + // add staking module 2 + await stakingRouter.addStakingModule( + 'Module 2', + StakingModule2.address, + 10_00, // target share BP + 10_00, // staking module fee BP + 50_00, // treasury fee BP + { from: admin } + ) + + const sm2AvailableKeysCount = 500 + await StakingModule2.setAvailableKeysCount(sm2AvailableKeysCount) + assert.equals(await StakingModule2.getAvailableValidatorsCount(), sm2AvailableKeysCount) + + const sm2ActiveKeysCount = 100 + await StakingModule2.setActiveValidatorsCount(sm2ActiveKeysCount) + assert.equals(await StakingModule2.getActiveValidatorsCount(), sm2ActiveKeysCount) + // add staking module 3 + await stakingRouter.addStakingModule( + 'Module 3', + StakingModule3.address, + 7_00, // target share BP + 5_00, // staking module fee BP + 0, // treasury fee BP + { from: admin } + ) + + const sm3AvailableKeysCount = 300 + await StakingModule3.setAvailableKeysCount(sm3AvailableKeysCount) + assert.equals(await StakingModule3.getAvailableValidatorsCount(), sm3AvailableKeysCount) + + const sm3ActiveKeysCount = 150 + await StakingModule3.setActiveValidatorsCount(sm3ActiveKeysCount) + assert.equals(await StakingModule3.getActiveValidatorsCount(), sm3ActiveKeysCount) + + const { allocated: allocated1, allocations: allocations1 } = await stakingRouter.getDepositsAllocation(100) + assert.equals(allocated1, 100) + assert.equals(allocations1[0], 15000) + assert.equals(allocations1[1], 175) + assert.equals(allocations1[2], 175) + + await stakingRouter.pauseStakingModule(1, { from: admin }) + const { allocated: allocated2, allocations: allocations2 } = await stakingRouter.getDepositsAllocation(100) + + assert.equals(allocated2, 100) + assert.equals(allocations2[0], 15000) + assert.equals(allocations2[1], 175) + assert.equals(allocations2[2], 175) + + await stakingRouter.pauseStakingModule(2, { from: admin }) + const { allocated: allocated3, allocations: allocations3 } = await stakingRouter.getDepositsAllocation(100) + + assert.equals(allocated3, 100) + assert.equals(allocations3[0], 15000) + assert.equals(allocations3[1], 100) + assert.equals(allocations3[2], 250) + }) + }) + describe('Single staking module', function () { this.timeout(30_000, 'Test suite took too long') beforeEach(async () => { From 8ac42571d298052ba2a7eca63ee545154b99e2d1 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 1 Mar 2023 20:23:02 +0400 Subject: [PATCH 086/236] Prevent reentrancy in StakingRouter.deposit --- contracts/0.8.9/StakingRouter.sol | 63 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index fdff95cdc..5dafbf804 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -951,12 +951,10 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version (allocated, allocations, ) = _getDepositsAllocation(_depositsCount); } - /** - * @dev Invokes a deposit call to the official Deposit contract - * @param _depositsCount number of deposits to make - * @param _stakingModuleId id of the staking module to be deposited - * @param _depositCalldata staking module calldata - */ + /// @dev Invokes a deposit call to the official Deposit contract + /// @param _depositsCount number of deposits to make + /// @param _stakingModuleId id of the staking module to be deposited + /// @param _depositCalldata staking module calldata function deposit( uint256 _depositsCount, uint256 _stakingModuleId, @@ -965,40 +963,39 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version if (msg.sender != LIDO_POSITION.getStorageAddress()) revert AppAuthLidoFailed(); StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); - uint256 depositsValue = msg.value; - if (depositsValue > 0) { - if (depositsValue != _depositsCount * DEPOSIT_SIZE) { - revert InvalidDepositsValue(depositsValue, _depositsCount); - } + uint256 depositsValue = msg.value; + /// @dev at first, modify the local state to prevent reentrancy + /// even though the staking modules are trusted contracts + stakingModule.lastDepositAt = uint64(block.timestamp); + stakingModule.lastDepositBlock = block.number; + emit StakingRouterETHDeposited(_stakingModuleId, depositsValue); - bytes32 withdrawalCredentials = getWithdrawalCredentials(); - if (withdrawalCredentials == 0) revert EmptyWithdrawalsCredentials(); + if (depositsValue == 0) return; + if (depositsValue != _depositsCount * DEPOSIT_SIZE) + revert InvalidDepositsValue(depositsValue, _depositsCount); - if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) { - revert StakingModuleNotActive(); - } + bytes32 withdrawalCredentials = getWithdrawalCredentials(); + if (withdrawalCredentials == 0) revert EmptyWithdrawalsCredentials(); - (bytes memory publicKeysBatch, bytes memory signaturesBatch) = - IStakingModule(stakingModule.stakingModuleAddress) - .obtainDepositData(_depositsCount, _depositCalldata); + if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) + revert StakingModuleNotActive(); - uint256 etherBalanceBeforeDeposits = address(this).balance; - _makeBeaconChainDeposits32ETH( - _depositsCount, - abi.encodePacked(withdrawalCredentials), - publicKeysBatch, - signaturesBatch - ); - uint256 etherBalanceAfterDeposits = address(this).balance; + (bytes memory publicKeysBatch, bytes memory signaturesBatch) = + IStakingModule(stakingModule.stakingModuleAddress) + .obtainDepositData(_depositsCount, _depositCalldata); - /// @dev all sent ETH must be deposited and self balance stay the same - assert(etherBalanceBeforeDeposits - etherBalanceAfterDeposits == depositsValue); - } + uint256 etherBalanceBeforeDeposits = address(this).balance; + _makeBeaconChainDeposits32ETH( + _depositsCount, + abi.encodePacked(withdrawalCredentials), + publicKeysBatch, + signaturesBatch + ); + uint256 etherBalanceAfterDeposits = address(this).balance; - stakingModule.lastDepositAt = uint64(block.timestamp); - stakingModule.lastDepositBlock = block.number; - emit StakingRouterETHDeposited(_stakingModuleId, depositsValue); + /// @dev all sent ETH must be deposited and self balance stay the same + assert(etherBalanceBeforeDeposits - etherBalanceAfterDeposits == depositsValue); } /** From b996bff5f13b62abf3a09681d277e9522dc546a9 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 00:52:48 +0300 Subject: [PATCH 087/236] test: implement utils for handleOracleReport tests --- test/helpers/utils.js | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/helpers/utils.js b/test/helpers/utils.js index aaaede6c9..1474a0ecd 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -1,6 +1,8 @@ const { web3 } = require('hardhat') const assert = require('node:assert') +const chai = require('chai') const { BN } = require('bn.js') +const { getEvents } = require('@aragon/contract-helpers-test') const ZERO_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000' @@ -117,6 +119,47 @@ const calcSharesMintedAsFees = (rewards, fee, feePoints, prevTotalShares, newTot ) } +const limitRebase = (limitE9, preTotalPooledEther, preTotalShares, clBalanceUpdate, elBalanceUpdate, sharesToBurn) => { + const bnE9 = toBN(e9(1)) + + let accumulatedRebase = toBN(0) + const clRebase = toBN(clBalanceUpdate).mul(bnE9).div(toBN(preTotalPooledEther)) + accumulatedRebase = accumulatedRebase.add(clRebase) + if (limitE9.lte(accumulatedRebase)) { + return { elBalanceUpdate: 0, sharesToBurn: 0 } + } + + let remainLimit = limitE9.sub(accumulatedRebase) + const remainEther = remainLimit.mul(toBN(preTotalPooledEther)).div(bnE9) + if (remainEther.lte(toBN(elBalanceUpdate))) { + return { elBalanceUpdate: remainEther, sharesToBurn: 0 } + } + + const elRebase = toBN(elBalanceUpdate).mul(bnE9).div(toBN(preTotalPooledEther)) + accumulatedRebase = accumulatedRebase.add(elRebase) + remainLimit = toBN(limitE9).sub(accumulatedRebase) + + const remainShares = remainLimit.mul(toBN(preTotalShares)).div(bnE9.add(remainLimit)) + + if (remainShares.lte(toBN(sharesToBurn))) { + return { elBalanceUpdate, sharesToBurn: remainShares } + } + + return { elBalanceUpdate, sharesToBurn } +} + +const calcShareRateDeltaE27 = (preTotalPooledEther, postTotalPooledEther, preTotalShares, postTotalShares) => { + const oldShareRateE27 = toBN(e27(1)).mul(toBN(preTotalPooledEther)).div(toBN(preTotalShares)) + const newShareRatesE27 = toBN(e27(1)).mul(toBN(postTotalPooledEther)).div(toBN(postTotalShares)) + return newShareRatesE27.sub(oldShareRateE27) +} + +function getFirstEventArgs(receipt, eventName, abi = undefined) { + const events = getEvents(receipt, eventName, { decodeForAbi: abi }) + chai.assert(events.length !== 0, () => `Expected event ${eventName} wasn't emitted`) + return events[0].args +} + module.exports = { ZERO_HASH, pad, @@ -143,4 +186,7 @@ module.exports = { toStr, prepIdsCountsPayload, calcSharesMintedAsFees, + getFirstEventArgs, + calcShareRateDeltaE27, + limitRebase, } From 62d859de830113c661c5dac9eefbcb00542de19b Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 23:39:54 +0300 Subject: [PATCH 088/236] fix: last test for EL rewards when Merge --- ...tion_layer_rewards_after_the_merge.test.js | 139 +++++++++--------- 1 file changed, 69 insertions(+), 70 deletions(-) diff --git a/test/scenario/execution_layer_rewards_after_the_merge.test.js b/test/scenario/execution_layer_rewards_after_the_merge.test.js index 2e9f2f4d2..ac9d9c5f9 100644 --- a/test/scenario/execution_layer_rewards_after_the_merge.test.js +++ b/test/scenario/execution_layer_rewards_after_the_merge.test.js @@ -1,22 +1,33 @@ -const { contract, artifacts, web3, ethers } = require('hardhat') +const { contract, artifacts, web3 } = require('hardhat') const { assert } = require('../helpers/assert') const { BN } = require('bn.js') const { getEventArgument } = require('@aragon/contract-helpers-test') -const { gwei, ZERO_HASH, ethToGwei, pad, toBN, ETH, tokens } = require('../helpers/utils') +const { gwei, ZERO_HASH, ethToGwei, pad, toBN, ETH, tokens, limitRebase } = require('../helpers/utils') const { DSMAttestMessage, DSMPauseMessage } = require('../helpers/signatures') -const { waitBlocks, setBalance } = require('../helpers/blockchain') +const { waitBlocks, setBalance, advanceChainTime } = require('../helpers/blockchain') const { deployProtocol } = require('../helpers/protocol') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') -const { SLOTS_PER_FRAME } = require('../helpers/constants') const { calcAccountingReportDataHash, getAccountingReportDataItems } = require('../helpers/reportData') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') const TOTAL_BASIS_POINTS = 10 ** 4 -const MAX_POSITIVE_REBASE_PRECISION_POINTS = 10 ** 9 const CURATED_MODULE_ID = 1 const LIDO_INIT_BALANCE_ETH = 1 +const ONE_DAY = 1 * 24 * 60 * 60 + +const ORACLE_REPORT_LIMITS_BOILERPLATE = { + churnValidatorsPerDayLimit: 255, + oneOffCLBalanceDecreaseBPLimit: 100, + annualBalanceIncreaseBPLimit: 10000, + simulatedShareRateDeviationBPLimit: 10000, + maxValidatorExitRequestsPerReport: 10000, + maxAccountingExtraDataListItemsCount: 10000, + maxNodeOperatorsPerExtraDataItemCount: 10000, + requestTimestampMargin: 0, + maxPositiveTokenRebase: 1000000000, +} const makeAccountingReport = ({ refSlot, numValidators, clBalanceGwei, elRewardsVaultBalance }) => ({ refSlot, @@ -48,7 +59,7 @@ contract('Lido: merge acceptance', (addresses) => { nobody, ] = addresses - let pool, nodeOperatorsRegistry, token + let pool, nodeOperatorsRegistry, token, oracleReportSanityChecker let oracleMock, depositContractMock let treasuryAddr, guardians, stakingRouter let depositSecurityModule, depositRoot @@ -108,6 +119,9 @@ contract('Lido: merge acceptance', (addresses) => { // contracts/Lido.sol pool = deployed.pool + // contracts/OracleReportSanityChecker.sol + oracleReportSanityChecker = deployed.oracleReportSanityChecker + // contracts/nos/NodeOperatorsRegistry.sol nodeOperatorsRegistry = deployed.stakingModules[0] @@ -510,11 +524,8 @@ contract('Lido: merge acceptance', (addresses) => { assert.equals(oldTotalPooledEther, ETH(107.35), 'total pooled ether') // Reporting the same balance as it was before (64.35ETH => 64.35ETH) + await advanceChainTime(ONE_DAY) - const oneDay = 1 * 24 * 60 * 60 - await ethers.provider.send('evm_increaseTime', [oneDay]) - - await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() const reportItems = getAccountingReportDataItems( @@ -609,11 +620,8 @@ contract('Lido: merge acceptance', (addresses) => { assert.equals(oldTotalPooledEther, ETH(114.35), 'total pooled ether') // Reporting balance decrease (64.35ETH => 62.35ETH) + await advanceChainTime(ONE_DAY) - const oneDay = 1 * 24 * 60 * 60 - await ethers.provider.send('evm_increaseTime', [oneDay]) - - await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() const reportItems = getAccountingReportDataItems( @@ -700,10 +708,8 @@ contract('Lido: merge acceptance', (addresses) => { assert.equals(oldTotalPooledEther, ETH(117.35), 'total pooled ether') // Reporting balance decrease (62.35ETH => 59.35ETH) - const oneDay = 1 * 24 * 60 * 60 - await ethers.provider.send('evm_increaseTime', [oneDay]) + await advanceChainTime(ONE_DAY) - await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() const reportItems = getAccountingReportDataItems( @@ -772,10 +778,8 @@ contract('Lido: merge acceptance', (addresses) => { assert.equals(oldTotalPooledEther, ETH(117.35), 'total pooled ether') // Reporting balance decrease (59.35ETH => 51.35ETH) - const oneDay = 1 * 24 * 60 * 60 - await ethers.provider.send('evm_increaseTime', [oneDay]) + await advanceChainTime(ONE_DAY) - await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() const reportItems = getAccountingReportDataItems( @@ -865,10 +869,8 @@ contract('Lido: merge acceptance', (addresses) => { assert.equals(oldTotalPooledEther, ETH(111.35), 'total pooled ether') // Reporting balance increase (51.35ETH => 51.49ETH) - const oneDay = 1 * 24 * 60 * 60 - await ethers.provider.send('evm_increaseTime', [oneDay]) + await advanceChainTime(ONE_DAY) - await consensus.setQuorum(2) const { refSlot } = await consensus.getCurrentFrame() const reportItems = getAccountingReportDataItems( @@ -947,92 +949,89 @@ contract('Lido: merge acceptance', (addresses) => { ) }) - // TODO: Revive - it.skip('collect 0.1 ETH execution layer rewards to elRewardsVault and withdraw it entirely by means of multiple oracle reports (+1 ETH)', async () => { - // Specify different withdrawal limits for a few epochs to test different values - const getMaxPositiveRebaseForFrame = (_frame) => { - let ret = 0 - - if (_frame === 7) { - ret = toBN(2) - } else if (_frame === 8) { - ret = toBN(1) - } else { - ret = toBN(3) - } + it('collect execution layer rewards to elRewardsVault and withdraw it entirely by means of multiple oracle reports', async () => { + const tokenRebaseLimit = toBN(10000000) - return ret.mul(toBN(MAX_POSITIVE_REBASE_PRECISION_POINTS / TOTAL_BASIS_POINTS)) - } + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: tokenRebaseLimit.toString(), // 1% + }, + { from: voting, gasPrice: 1 } + ) - const elRewards = ETH(0.1) + const elRewards = ETH(5) await setBalance(elRewardsVault.address, elRewards) assert.equals(await web3.eth.getBalance(elRewardsVault.address), elRewards, 'Execution layer rewards vault balance') let frame = 7 - let lastBeaconBalance = toBN(ETH(51.45)) - await pool.setMaxPositiveTokenRebase(getMaxPositiveRebaseForFrame(frame), { from: voting }) + let lastBeaconBalance = toBN(ETH(51.49)) - let maxPositiveRebase = await pool.getMaxPositiveTokenRebase() - let elRewardsVaultBalance = toBN(await web3.eth.getBalance(elRewardsVault.address)) + let elRewardsVaultBalance = toBN(elRewards) let totalPooledEther = await pool.getTotalPooledEther() + let totalShares = await pool.getTotalShares() let bufferedEther = await pool.getBufferedEther() - let totalSupply = await pool.totalSupply() - const beaconBalanceInc = toBN(ETH(0.001)) let elRewardsWithdrawn = toBN(0) + const beaconBalanceInc = toBN(ETH(0.001)) // Do multiple oracle reports to withdraw all ETH from execution layer rewards vault while (elRewardsVaultBalance > 0) { - const maxPositiveRebaseCalculated = getMaxPositiveRebaseForFrame(frame) - await pool.setMaxPositiveTokenRebase(maxPositiveRebaseCalculated, { from: voting }) - maxPositiveRebase = await pool.getMaxPositiveTokenRebase() - const clIncurredRebase = beaconBalanceInc.mul(toBN(MAX_POSITIVE_REBASE_PRECISION_POINTS)).div(totalPooledEther) - - const maxELRewardsAmountPerWithdrawal = totalPooledEther - .mul(maxPositiveRebase.sub(clIncurredRebase)) - .div(toBN(MAX_POSITIVE_REBASE_PRECISION_POINTS)) + await advanceChainTime(ONE_DAY) - const elRewardsToWithdraw = BN.min(maxELRewardsAmountPerWithdrawal, elRewardsVaultBalance) + const currentELBalance = await web3.eth.getBalance(elRewardsVault.address) - // Reporting balance increase - await oracleMock.submitReportData( + const { refSlot } = await consensus.getCurrentFrame() + const reportItems = getAccountingReportDataItems( makeAccountingReport({ - refSlot: frame * SLOTS_PER_FRAME - 1, + refSlot, numValidators: 2, clBalanceGwei: ethToGwei(lastBeaconBalance.add(beaconBalanceInc)), - elRewardsVaultBalance: await web3.eth.getBalance(elRewardsVault.address), - }), - 1 + elRewardsVaultBalance: currentELBalance, + }) + ) + const reportHash = calcAccountingReportDataHash(reportItems) + + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[2].address }) + await consensus.submitReport(refSlot, reportHash, 1, { from: signers[3].address }) + + await oracleMock.submitReportData(reportItems, 1, { from: signers[4].address }) + + const { elBalanceUpdate } = limitRebase( + toBN(tokenRebaseLimit), + totalPooledEther, + totalShares, + beaconBalanceInc, + toBN(currentELBalance), + toBN(0) ) assert.equals( await web3.eth.getBalance(elRewardsVault.address), - elRewardsVaultBalance.sub(elRewardsToWithdraw), + elRewardsVaultBalance.sub(toBN(elBalanceUpdate)), 'Execution layer rewards vault balance' ) assert.equals( await pool.getTotalPooledEther(), - totalPooledEther.add(beaconBalanceInc).add(elRewardsToWithdraw), + totalPooledEther.add(beaconBalanceInc).add(elBalanceUpdate), 'total pooled ether' ) - assert.equals( - await pool.totalSupply(), - totalSupply.add(beaconBalanceInc).add(elRewardsToWithdraw), - 'token total supply' - ) - assert.equals(await pool.getBufferedEther(), bufferedEther.add(elRewardsToWithdraw), 'buffered ether') + + assert.equals(await pool.getBufferedEther(), bufferedEther.add(elBalanceUpdate), 'buffered ether') elRewardsVaultBalance = toBN(await web3.eth.getBalance(elRewardsVault.address)) totalPooledEther = await pool.getTotalPooledEther() + totalShares = await pool.getTotalShares() bufferedEther = await pool.getBufferedEther() - totalSupply = await pool.totalSupply() lastBeaconBalance = lastBeaconBalance.add(beaconBalanceInc) - elRewardsWithdrawn = elRewardsWithdrawn.add(elRewardsToWithdraw) + elRewardsWithdrawn = elRewardsWithdrawn.add(elBalanceUpdate) frame += 1 } assert.equals(elRewardsWithdrawn, elRewards) + assert.equals(elRewardsVaultBalance, toBN(0)) + assert.isTrue(frame > 10) }) }) From 661fb62535e14434576cc2ac0e89c9ed47aa773a Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 2 Mar 2023 02:13:27 +0400 Subject: [PATCH 089/236] Catch error on withdrawal credentials set --- contracts/0.8.9/StakingRouter.sol | 41 ++++++++++++------- lib/abi/StakingRouter.json | 2 +- .../staking-router/staking-router.test.js | 35 ++++++++++++++++ test/helpers/stubs/generic.stub.js | 2 +- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 5dafbf804..13f9e4963 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -25,6 +25,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version event StakingModuleStatusSet(uint256 indexed stakingModuleId, StakingModuleStatus status, address setBy); event StakingModuleExitedValidatorsIncompleteReporting(uint256 indexed stakingModuleId, uint256 unreportedExitedValidatorsCount); event WithdrawalCredentialsSet(bytes32 withdrawalCredentials, address setBy); + event WithdrawalsCredentialsChangeFailed(uint256 indexed stakingModuleId, bytes lowLevelRevertData); /// Emitted when the StakingRouter received ETH event StakingRouterETHDeposited(uint256 indexed stakingModuleId, uint256 amount); @@ -710,10 +711,9 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version onlyRole(STAKING_MODULE_MANAGE_ROLE) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); - StakingModuleStatus _prevStatus = StakingModuleStatus(stakingModule.status); - if (_prevStatus == _status) revert StakingModuleStatusTheSame(); - stakingModule.status = uint8(_status); - emit StakingModuleStatusSet(_stakingModuleId, _status, msg.sender); + if (StakingModuleStatus(stakingModule.status) == _status) + revert StakingModuleStatusTheSame(); + _setStakingModuleStatus(stakingModule, _status); } /** @@ -725,10 +725,9 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version onlyRole(STAKING_MODULE_PAUSE_ROLE) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); - StakingModuleStatus _prevStatus = StakingModuleStatus(stakingModule.status); - if (_prevStatus != StakingModuleStatus.Active) revert StakingModuleNotActive(); - stakingModule.status = uint8(StakingModuleStatus.DepositsPaused); - emit StakingModuleStatusSet(_stakingModuleId, StakingModuleStatus.DepositsPaused, msg.sender); + if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) + revert StakingModuleNotActive(); + _setStakingModuleStatus(stakingModule, StakingModuleStatus.DepositsPaused); } /** @@ -740,10 +739,9 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version onlyRole(STAKING_MODULE_RESUME_ROLE) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); - StakingModuleStatus _prevStatus = StakingModuleStatus(stakingModule.status); - if (_prevStatus != StakingModuleStatus.DepositsPaused) revert StakingModuleNotPaused(); - stakingModule.status = uint8(StakingModuleStatus.Active); - emit StakingModuleStatusSet(_stakingModuleId, StakingModuleStatus.Active, msg.sender); + if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.DepositsPaused) + revert StakingModuleNotPaused(); + _setStakingModuleStatus(stakingModule, StakingModuleStatus.Active); } function getStakingModuleIsStopped(uint256 _stakingModuleId) external view @@ -1008,9 +1006,14 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 stakingModulesCount = getStakingModulesCount(); for (uint256 i; i < stakingModulesCount; ) { - IStakingModule(_getStakingModuleAddressByIndex(i)).onWithdrawalCredentialsChanged(); - unchecked { - ++i; + StakingModule storage stakingModule = _getStakingModuleByIndex(i); + unchecked { ++i; } + + try IStakingModule(stakingModule.stakingModuleAddress) + .onWithdrawalCredentialsChanged() {} + catch (bytes memory lowLevelRevertData) { + _setStakingModuleStatus(stakingModule, StakingModuleStatus.DepositsPaused); + emit WithdrawalsCredentialsChangeFailed(stakingModule.id, lowLevelRevertData); } } @@ -1090,6 +1093,14 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version Math256.max(totalExitedValidators, stakingModuleData.exitedValidatorsCount); } + function _setStakingModuleStatus(StakingModule storage _stakingModule, StakingModuleStatus _status) internal { + StakingModuleStatus prevStatus = StakingModuleStatus(_stakingModule.status); + if (prevStatus != _status) { + _stakingModule.status = uint8(_status); + emit StakingModuleStatusSet(_stakingModule.id, _status, msg.sender); + } + } + function _getDepositsAllocation( uint256 _depositsToAllocate ) internal view returns (uint256 allocated, uint256[] memory allocations, StakingModuleCache[] memory stakingModulesCache) { diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index 1f4227201..d9157abb8 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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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.8.9/staking-router/staking-router.test.js b/test/0.8.9/staking-router/staking-router.test.js index fae38b640..b51d82448 100644 --- a/test/0.8.9/staking-router/staking-router.test.js +++ b/test/0.8.9/staking-router/staking-router.test.js @@ -5,6 +5,7 @@ const { BN } = require('bn.js') const { assert } = require('../../helpers/assert') const { EvmSnapshot } = require('../../helpers/blockchain') const { ETH, toBN } = require('../../helpers/utils') +const { StakingModuleStub } = require('../../helpers/stubs/staking-module.stub') const OssifiableProxy = artifacts.require('OssifiableProxy.sol') const DepositContractMock = artifacts.require('DepositContractMock') @@ -322,6 +323,40 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { 2 ) }) + + it('set withdrawal credentials works when staking module reverts', async () => { + const stakingModuleWithBug = await StakingModuleStub.new() + // staking module will revert with panic exit code + await StakingModuleStub.stub(stakingModuleWithBug, 'onWithdrawalCredentialsChanged', { + revert: { error: 'Panic', args: { type: ['uint256'], value: [0x01] } }, + }) + await router.addStakingModule('Staking Module With Bug', stakingModuleWithBug.address, 100, 1000, 2000, { + from: appManager, + }) + const stakingModuleId = await router.getStakingModulesCount() + assert.isFalse(await router.getStakingModuleIsDepositsPaused(stakingModuleId)) + + const newWC = '0x'.padEnd(66, '5678') + const tx = await router.setWithdrawalCredentials(newWC, { from: appManager }) + + assert.emits(tx, 'WithdrawalsCredentialsChangeFailed', { + stakingModuleId, + lowLevelRevertData: '0x4e487b710000000000000000000000000000000000000000000000000000000000000001', + }) + + assert.emits( + tx, + 'StakingModuleStatusSet', + { + status: 1, + stakingModuleId, + setBy: appManager, + }, + { abi: StakingRouter._json.abi } + ) + + assert.isTrue(await router.getStakingModuleIsDepositsPaused(stakingModuleId)) + }) }) describe('staking modules limit', async () => { diff --git a/test/helpers/stubs/generic.stub.js b/test/helpers/stubs/generic.stub.js index 474a89673..c89294cba 100644 --- a/test/helpers/stubs/generic.stub.js +++ b/test/helpers/stubs/generic.stub.js @@ -98,7 +98,7 @@ class GenericStubConfigParser { } if (config.revert) { return config.revert.error - ? this._encodeError(config.revert.error) + ? this._encodeError(config.revert) : this._encodeError({ error: 'Error', args: { type: ['string'], value: [config.revert.reason || ''] } }) } return this._encode({ type: [], value: [] }) From 565542c1dd65311a7d72d662ceeb414e95cd7fc8 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Thu, 2 Mar 2023 05:27:35 +0700 Subject: [PATCH 090/236] test: Versioned 0.8.9 --- .../0.8.9/test_helpers/VersionedMock.sol | 25 ++++++ test/0.8.9/versioned.test.js | 89 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 contracts/0.8.9/test_helpers/VersionedMock.sol create mode 100644 test/0.8.9/versioned.test.js diff --git a/contracts/0.8.9/test_helpers/VersionedMock.sol b/contracts/0.8.9/test_helpers/VersionedMock.sol new file mode 100644 index 000000000..93521e7aa --- /dev/null +++ b/contracts/0.8.9/test_helpers/VersionedMock.sol @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.9; + +import { Versioned } from "../utils/Versioned.sol"; + +contract VersionedMock is Versioned { + constructor() Versioned() {} + + function getPetrifiedVersionMark() external pure returns (uint256) { + return PETRIFIED_VERSION_MARK; + } + + function initializeContractVersionTo(uint256 version) external { + _initializeContractVersionTo(version); + } + + function checkContractVersion(uint256 version) external view { + _checkContractVersion(version); + } + + function updateContractVersion(uint256 newVersion) external { + _updateContractVersion(newVersion); + } +} diff --git a/test/0.8.9/versioned.test.js b/test/0.8.9/versioned.test.js new file mode 100644 index 000000000..a0f59bbad --- /dev/null +++ b/test/0.8.9/versioned.test.js @@ -0,0 +1,89 @@ +const { contract, artifacts } = require('hardhat') +const { assert } = require('../helpers/assert') + +async function deployBehindOssifiableProxy(artifactName, proxyOwner, constructorArgs = []) { + const Contract = await artifacts.require(artifactName) + const implementation = await Contract.new(...constructorArgs, { from: proxyOwner }) + const OssifiableProxy = await artifacts.require('OssifiableProxy') + const proxy = await OssifiableProxy.new(implementation.address, proxyOwner, [], { from: proxyOwner }) + const proxied = await Contract.at(proxy.address) + return { implementation, proxy, proxied } +} + +contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { + let versionedImpl + let versionedProxied + const VERSION_INIT = 1 + const VERSION_ZERO = 0 + + before('Deploy', async () => { + const deployed = await deployBehindOssifiableProxy( + 'contracts/0.8.9/test_helpers/VersionedMock.sol:VersionedMock', + proxyOwner, + [] + ) + versionedImpl = deployed.implementation + versionedProxied = deployed.proxied + }) + + describe('raw implementation', async () => { + it('default version is petrified', async () => { + const versionPetrified = await versionedImpl.getPetrifiedVersionMark() + assert.equals(await versionedImpl.getContractVersion(), versionPetrified) + await assert.reverts( + versionedImpl.checkContractVersion(VERSION_ZERO), + `UnexpectedContractVersion(${String(versionPetrified)}, ${VERSION_ZERO})` + ) + }) + + it('reverts if trying to initialize', async () => { + await versionedImpl.getContractVersion() + await assert.reverts(versionedImpl.initializeContractVersionTo(1), 'NonZeroContractVersionOnInit()') + }) + }) + + describe('behind proxy', () => { + it('default version is zero', async () => { + const version = await versionedProxied.getContractVersion() + assert.equals(version, VERSION_ZERO) + await assert.reverts( + versionedProxied.checkContractVersion(VERSION_INIT), + `UnexpectedContractVersion(${VERSION_ZERO}, ${VERSION_INIT})` + ) + }) + + it('initialize sets version and emits event', async () => { + const tx = await versionedProxied.initializeContractVersionTo(VERSION_INIT) + assert.emits(tx, 'ContractVersionSet', { version: VERSION_INIT }) + assert.equals(await versionedProxied.getContractVersion(), VERSION_INIT) + await assert.reverts( + versionedProxied.checkContractVersion(VERSION_ZERO), + `UnexpectedContractVersion(${VERSION_INIT}, ${VERSION_ZERO})` + ) + }) + + it('reverts if trying to repeat initialize', async () => { + await assert.reverts(versionedProxied.initializeContractVersionTo(1), 'NonZeroContractVersionOnInit()') + }) + + it('version can be incremented by value 1 at time', async () => { + const prevVersion = +(await versionedProxied.getContractVersion()) + const nextVersion = prevVersion + 1 + const tx = await versionedProxied.updateContractVersion(nextVersion) + assert.emits(tx, 'ContractVersionSet', { version: nextVersion }) + await assert.reverts( + versionedProxied.checkContractVersion(prevVersion), + `UnexpectedContractVersion(${nextVersion}, ${prevVersion})` + ) + const newVersion = +(await versionedProxied.getContractVersion()) + assert.equals(newVersion, nextVersion) + }) + + it('reverts if trying to update version with incorrect value', async () => { + const prevVersion = +(await versionedProxied.getContractVersion()) + await assert.reverts(versionedProxied.updateContractVersion(prevVersion - 1), 'InvalidContractVersionIncrement()') + await assert.reverts(versionedProxied.updateContractVersion(prevVersion), 'InvalidContractVersionIncrement()') + await assert.reverts(versionedProxied.updateContractVersion(prevVersion + 2), 'InvalidContractVersionIncrement()') + }) + }) +}) From 31b99ff07bc21ae6f6e9ce6f62141a73d9858517 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 2 Mar 2023 02:41:52 +0400 Subject: [PATCH 091/236] Catch errors on exited and stuck validators reporting --- contracts/0.8.9/StakingRouter.sol | 9 ++++++- lib/abi/StakingRouter.json | 2 +- .../staking-router-keys-reporting.test.js | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 13f9e4963..db7362cd0 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -26,6 +26,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version event StakingModuleExitedValidatorsIncompleteReporting(uint256 indexed stakingModuleId, uint256 unreportedExitedValidatorsCount); event WithdrawalCredentialsSet(bytes32 withdrawalCredentials, address setBy); event WithdrawalsCredentialsChangeFailed(uint256 indexed stakingModuleId, bytes lowLevelRevertData); + event ExitedAndStuckValidatorsCountsUpdateFailed(uint256 indexed stakingModuleId, bytes lowLevelRevertData); /// Emitted when the StakingRouter received ETH event StakingRouterETHDeposited(uint256 indexed stakingModuleId, uint256 amount); @@ -430,7 +431,13 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version (uint256 exitedValidatorsCount, , ) = moduleContract.getStakingModuleSummary(); if (exitedValidatorsCount == stakingModule.exitedValidatorsCount) { // oracle finished updating exited validators for all node ops - moduleContract.onExitedAndStuckValidatorsCountsUpdated(); + try moduleContract.onExitedAndStuckValidatorsCountsUpdated() {} + catch (bytes memory lowLevelRevertData) { + emit ExitedAndStuckValidatorsCountsUpdateFailed( + stakingModule.id, + lowLevelRevertData + ); + } } unchecked { ++i; } diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index d9157abb8..cfff8c52d 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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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.8.9/staking-router/staking-router-keys-reporting.test.js b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js index aa71cb03e..99d6f97c0 100644 --- a/test/0.8.9/staking-router/staking-router-keys-reporting.test.js +++ b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js @@ -2,6 +2,7 @@ const { artifacts, contract, ethers } = require('hardhat') const { EvmSnapshot } = require('../../helpers/blockchain') const { assert } = require('../../helpers/assert') const { hex, hexConcat, toNum } = require('../../helpers/utils') +const { StakingModuleStub } = require('../../helpers/stubs/staking-module.stub') const StakingRouter = artifacts.require('StakingRouterMock.sol') const StakingModuleMock = artifacts.require('StakingModuleMock.sol') @@ -465,6 +466,30 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { assert.equal(callInfo.updateExitedValidatorsCount.callCount, 2) } ) + + it("doesn't revert when onExitedAndStuckValidatorsCountsUpdated reverted", async () => { + const stakingModuleWithBug = await StakingModuleStub.new() + // staking module will revert with panic exit code + await StakingModuleStub.stub(stakingModuleWithBug, 'onExitedAndStuckValidatorsCountsUpdated', { + revert: { error: 'Panic', args: { type: ['uint256'], value: [0x01] } }, + }) + await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleWithBug, { + totalExitedValidators: 0, + totalDepositedValidators: 0, + availableValidatorsCount: 0, + }) + await router.addStakingModule('Staking Module With Bug', stakingModuleWithBug.address, 100, 1000, 2000, { + from: admin, + }) + const stakingModuleId = await router.getStakingModulesCount() + + const tx = await router.onValidatorsCountsByNodeOperatorReportingFinished({ from: admin }) + + assert.emits(tx, 'ExitedAndStuckValidatorsCountsUpdateFailed', { + stakingModuleId, + lowLevelRevertData: '0x4e487b710000000000000000000000000000000000000000000000000000000000000001', + }) + }) }) describe('two staking modules', async () => { From ca4d8ae9a5eb0d41b6cf351d69a6c3a35f8fa623 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 2 Mar 2023 03:40:24 +0400 Subject: [PATCH 092/236] Remove validStakingModuleId modifier --- contracts/0.8.9/DepositSecurityModule.sol | 14 +-- contracts/0.8.9/StakingRouter.sol | 56 ++++-------- lib/abi/DepositSecurityModule.json | 2 +- lib/abi/StakingRouter.json | 2 +- test/0.8.9/deposit-security-module.test.js | 14 --- .../staking-router-deposits.test.js | 12 +-- .../staking-router/staking-router.test.js | 89 ------------------- 7 files changed, 25 insertions(+), 164 deletions(-) diff --git a/contracts/0.8.9/DepositSecurityModule.sol b/contracts/0.8.9/DepositSecurityModule.sol index 8f8cba651..4439ff348 100644 --- a/contracts/0.8.9/DepositSecurityModule.sol +++ b/contracts/0.8.9/DepositSecurityModule.sol @@ -49,7 +49,6 @@ contract DepositSecurityModule { event DepositsPaused(address indexed guardian, uint24 indexed stakingModuleId); event DepositsUnpaused(uint24 indexed stakingModuleId); - error StakingModuleIdTooLarge(); error ZeroAddress(string field); error DuplicateAddress(address addr); error NotAnOwner(address caller); @@ -134,11 +133,6 @@ contract DepositSecurityModule { _; } - modifier validStakingModuleId(uint256 _stakingModuleId) { - if (_stakingModuleId > type(uint24).max) revert StakingModuleIdTooLarge(); - _; - } - /** * Sets new owner. Only callable by the current owner. */ @@ -337,7 +331,7 @@ contract DepositSecurityModule { uint256 blockNumber, uint256 stakingModuleId, Signature memory sig - ) external validStakingModuleId(stakingModuleId) { + ) external { // In case of an emergency function `pauseDeposits` is supposed to be called // by all guardians. Thus only the first call will do the actual change. But // the other calls would be OK operations from the point of view of protocol’s logic. @@ -369,7 +363,7 @@ contract DepositSecurityModule { * * Only callable by the owner. */ - function unpauseDeposits(uint256 stakingModuleId) external validStakingModuleId(stakingModuleId) onlyOwner { + function unpauseDeposits(uint256 stakingModuleId) external onlyOwner { /// @dev unpause only paused modules (skip stopped) if (STAKING_ROUTER.getStakingModuleIsDepositsPaused(stakingModuleId)) { STAKING_ROUTER.resumeStakingModule(stakingModuleId); @@ -382,7 +376,7 @@ contract DepositSecurityModule { * guardian attestations of non-stale deposit root and `nonce`, and the number of * such attestations will be enough to reach quorum. */ - function canDeposit(uint256 stakingModuleId) external view validStakingModuleId(stakingModuleId) returns (bool) { + function canDeposit(uint256 stakingModuleId) external view returns (bool) { bool isModuleActive = STAKING_ROUTER.getStakingModuleIsActive(stakingModuleId); uint256 lastDepositBlock = STAKING_ROUTER.getStakingModuleLastDepositBlock(stakingModuleId); bool isLidoCanDeposit = LIDO.canDeposit(); @@ -418,7 +412,7 @@ contract DepositSecurityModule { uint256 nonce, bytes calldata depositCalldata, Signature[] calldata sortedGuardianSignatures - ) external validStakingModuleId(stakingModuleId) { + ) external { if (quorum == 0 || sortedGuardianSignatures.length < quorum) revert DepositNoQuorum(); bytes32 onchainDepositRoot = IDepositContract(DEPOSIT_CONTRACT).get_deposit_root(); diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index db7362cd0..1a9731d75 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -41,7 +41,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version error InvalidReportData(uint256 code); error ExitedValidatorsCountCannotDecrease(); error StakingModulesLimitExceeded(); - error StakingModuleIdTooLarge(); error StakingModuleUnregistered(); error AppAuthLidoFailed(); error StakingModuleStatusTheSame(); @@ -120,13 +119,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 public constant FEE_PRECISION_POINTS = 10 ** 20; // 100 * 10 ** 18 uint256 public constant TOTAL_BASIS_POINTS = 10000; - uint256 internal constant UINT24_MAX = type(uint24).max; - - modifier validStakingModuleId(uint256 _stakingModuleId) { - if (_stakingModuleId > UINT24_MAX) revert StakingModuleIdTooLarge(); - _; - } - constructor(address _depositContract) BeaconChainDepositor(_depositContract) {} /** @@ -226,10 +218,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 _targetShare, uint256 _stakingModuleFee, uint256 _treasuryFee - ) external - validStakingModuleId(_stakingModuleId) - onlyRole(STAKING_MODULE_MANAGE_ROLE) - { + ) external onlyRole(STAKING_MODULE_MANAGE_ROLE) { if (_targetShare > TOTAL_BASIS_POINTS) revert ValueOver100Percent("_targetShare"); if (_stakingModuleFee + _treasuryFee > TOTAL_BASIS_POINTS) revert ValueOver100Percent("_stakingModuleFee + _treasuryFee"); @@ -253,7 +242,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 _stakingModuleId, uint256 _nodeOperatorId, uint256 _refundedValidatorsCount - ) external validStakingModuleId(_stakingModuleId) onlyRole(STAKING_MODULE_MANAGE_ROLE) { + ) external onlyRole(STAKING_MODULE_MANAGE_ROLE) { address moduleAddr = _getStakingModuleById(_stakingModuleId).stakingModuleAddress; IStakingModule(moduleAddr) .updateRefundedValidatorsCount(_nodeOperatorId, _refundedValidatorsCount); @@ -488,7 +477,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version function getStakingModule(uint256 _stakingModuleId) public view - validStakingModuleId(_stakingModuleId) returns (StakingModule memory) { return _getStakingModuleById(_stakingModuleId); @@ -504,8 +492,9 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version /** * @dev Returns status of staking module */ - function getStakingModuleStatus(uint256 _stakingModuleId) public view - validStakingModuleId(_stakingModuleId) + function getStakingModuleStatus(uint256 _stakingModuleId) + public + view returns (StakingModuleStatus) { return StakingModuleStatus(_getStakingModuleById(_stakingModuleId).status); @@ -714,7 +703,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version * @notice set the staking module status flag for participation in further deposits and/or reward distribution */ function setStakingModuleStatus(uint256 _stakingModuleId, StakingModuleStatus _status) external - validStakingModuleId(_stakingModuleId) onlyRole(STAKING_MODULE_MANAGE_ROLE) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); @@ -728,7 +716,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version * @param _stakingModuleId id of the staking module to be paused */ function pauseStakingModule(uint256 _stakingModuleId) external - validStakingModuleId(_stakingModuleId) onlyRole(STAKING_MODULE_PAUSE_ROLE) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); @@ -742,7 +729,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version * @param _stakingModuleId id of the staking module to be unpaused */ function resumeStakingModule(uint256 _stakingModuleId) external - validStakingModuleId(_stakingModuleId) onlyRole(STAKING_MODULE_RESUME_ROLE) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); @@ -751,44 +737,39 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version _setStakingModuleStatus(stakingModule, StakingModuleStatus.Active); } - function getStakingModuleIsStopped(uint256 _stakingModuleId) external view - validStakingModuleId(_stakingModuleId) - returns (bool) + function getStakingModuleIsStopped(uint256 _stakingModuleId) external view returns (bool) { return getStakingModuleStatus(_stakingModuleId) == StakingModuleStatus.Stopped; } - function getStakingModuleIsDepositsPaused(uint256 _stakingModuleId) external view - validStakingModuleId(_stakingModuleId) + function getStakingModuleIsDepositsPaused(uint256 _stakingModuleId) + external + view returns (bool) { return getStakingModuleStatus(_stakingModuleId) == StakingModuleStatus.DepositsPaused; } - function getStakingModuleIsActive(uint256 _stakingModuleId) external view - validStakingModuleId(_stakingModuleId) - returns (bool) - { + function getStakingModuleIsActive(uint256 _stakingModuleId) external view returns (bool) { return getStakingModuleStatus(_stakingModuleId) == StakingModuleStatus.Active; } - function getStakingModuleNonce(uint256 _stakingModuleId) external view - validStakingModuleId(_stakingModuleId) - returns (uint256) - { + function getStakingModuleNonce(uint256 _stakingModuleId) external view returns (uint256) { return IStakingModule(_getStakingModuleAddressById(_stakingModuleId)).getNonce(); } - function getStakingModuleLastDepositBlock(uint256 _stakingModuleId) external view - validStakingModuleId(_stakingModuleId) + function getStakingModuleLastDepositBlock(uint256 _stakingModuleId) + external + view returns (uint256) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); return stakingModule.lastDepositBlock; } - function getStakingModuleActiveValidatorsCount(uint256 _stakingModuleId) external view - validStakingModuleId(_stakingModuleId) + function getStakingModuleActiveValidatorsCount(uint256 _stakingModuleId) + external + view returns (uint256 activeValidatorsCount) { ( @@ -808,7 +789,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version function getStakingModuleMaxDepositsCount(uint256 _stakingModuleId, uint256 _maxDepositsValue) public view - validStakingModuleId(_stakingModuleId) returns (uint256) { ( @@ -964,7 +944,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 _depositsCount, uint256 _stakingModuleId, bytes calldata _depositCalldata - ) external payable validStakingModuleId(_stakingModuleId) { + ) external payable { if (msg.sender != LIDO_POSITION.getStorageAddress()) revert AppAuthLidoFailed(); StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); diff --git a/lib/abi/DepositSecurityModule.json b/lib/abi/DepositSecurityModule.json index c4a2f7758..c443f1ea6 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":"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 +[{"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":[{"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/StakingRouter.json b/lib/abi/StakingRouter.json index cfff8c52d..acaa10963 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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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.8.9/deposit-security-module.test.js b/test/0.8.9/deposit-security-module.test.js index 023154b47..5ed520c05 100644 --- a/test/0.8.9/deposit-security-module.test.js +++ b/test/0.8.9/deposit-security-module.test.js @@ -1,6 +1,5 @@ const { artifacts, contract, ethers, network, web3 } = require('hardhat') const { assert } = require('../helpers/assert') -const { BN } = require('bn.js') const { DSMAttestMessage, DSMPauseMessage } = require('../helpers/signatures') const { ZERO_ADDRESS } = require('../helpers/constants') @@ -16,7 +15,6 @@ const MIN_DEPOSIT_BLOCK_DISTANCE = 14 const PAUSE_INTENT_VALIDITY_PERIOD_BLOCKS = 10 const STAKING_MODULE = 123 -const UINT24_MAX = new BN(2).pow(new BN(24)) const DEPOSIT_CALLDATA = '0x000000000000000000000000000000000000000000000000000000000000002a' const GUARDIAN1 = '0x5Fc0E75BF6502009943590492B02A1d08EAc9C43' @@ -626,18 +624,6 @@ contract('DepositSecurityModule', ([owner, stranger, guardian]) => { ) }) - it('reverts when staking module too large', async () => { - await assert.revertsWithCustomError( - depositSecurityModule.pauseDeposits( - stalePauseMessage.blockNumber, - UINT24_MAX, - stalePauseMessage.sign(GUARDIAN_PRIVATE_KEYS[GUARDIAN2]), - { from: stranger } - ), - 'StakingModuleIdTooLarge()' - ) - }) - it('reverts if called by a guardian with a future blockNumber', async () => { const futureBlockNumber = block.number + 100 await assert.reverts( diff --git a/test/0.8.9/staking-router/staking-router-deposits.test.js b/test/0.8.9/staking-router/staking-router-deposits.test.js index c4668398b..f9dbfe0a2 100644 --- a/test/0.8.9/staking-router/staking-router-deposits.test.js +++ b/test/0.8.9/staking-router/staking-router-deposits.test.js @@ -4,7 +4,7 @@ const { EvmSnapshot } = require('../../helpers/blockchain') const { setupNodeOperatorsRegistry } = require('../../helpers/staking-modules') const { deployProtocol } = require('../../helpers/protocol') -const { ETH, genKeys, toBN } = require('../../helpers/utils') +const { ETH, genKeys } = require('../../helpers/utils') const { assert } = require('../../helpers/assert') const { ZERO_BYTES32 } = require('../../helpers/constants') @@ -71,16 +71,6 @@ contract('StakingRouter', ([depositor, stranger]) => { ) }) - it('reverts if stakingModuleId more than uint24', async () => { - const depositsCount = 100 - const maxModuleId = toBN(2).pow(toBN(24)) - - await assert.reverts( - lido.methods[`deposit(uint256,uint256,bytes)`](depositsCount, maxModuleId, '0x', { from: depositor }), - 'StakingModuleIdTooLarge()' - ) - }) - it('add initial balance and keys', async () => { // balance are initial assert.equals(await web3.eth.getBalance(lido.address), ETH(1)) diff --git a/test/0.8.9/staking-router/staking-router.test.js b/test/0.8.9/staking-router/staking-router.test.js index b51d82448..b149a1b41 100644 --- a/test/0.8.9/staking-router/staking-router.test.js +++ b/test/0.8.9/staking-router/staking-router.test.js @@ -20,8 +20,6 @@ const STAKING_MODULE_PAUSE_ROLE = utils.soliditySha3('STAKING_MODULE_PAUSE_ROLE' const STAKING_MODULE_RESUME_ROLE = utils.soliditySha3('STAKING_MODULE_RESUME_ROLE') const STAKING_MODULE_MANAGE_ROLE = utils.soliditySha3('STAKING_MODULE_MANAGE_ROLE') -const UINT24_MAX = new BN(2).pow(new BN(24)) - const StakingModuleStatus = { Active: 0, // deposits and rewards allowed DepositsPaused: 1, // deposits NOT allowed, rewards allowed @@ -260,24 +258,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await router.getStakingModuleNonce(1), 100) }) - it('getStakingModuleNonce reverts when staking module id too large', async () => { - await assert.revertsWithCustomError(router.getStakingModuleNonce(UINT24_MAX), 'StakingModuleIdTooLarge()') - }) - - it('getStakingModuleLastDepositBlock reverts when staking module id too large', async () => { - await assert.revertsWithCustomError( - router.getStakingModuleLastDepositBlock(UINT24_MAX), - 'StakingModuleIdTooLarge()' - ) - }) - - it('getStakingModuleActiveValidatorsCount reverts when staking module id too large', async () => { - await assert.revertsWithCustomError( - router.getStakingModuleActiveValidatorsCount(UINT24_MAX), - 'StakingModuleIdTooLarge()' - ) - }) - it('getStakingModuleActiveValidatorsCount', async () => { await stakingModule.setActiveValidatorsCount(200, { from: deployer }) assert.equals(await router.getStakingModuleActiveValidatorsCount(1), 200) @@ -542,15 +522,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equals(await router.getStakingModuleIsDepositsPaused(stakingModulesParams[0].expectedModuleId), false) assert.equals(await router.getStakingModuleIsActive(stakingModulesParams[0].expectedModuleId), true) - await assert.revertsWithCustomError(router.getStakingModule(UINT24_MAX), 'StakingModuleIdTooLarge()') - await assert.revertsWithCustomError(router.getStakingModuleStatus(UINT24_MAX), 'StakingModuleIdTooLarge()') - await assert.revertsWithCustomError(router.getStakingModuleIsStopped(UINT24_MAX), 'StakingModuleIdTooLarge()') - await assert.revertsWithCustomError( - router.getStakingModuleIsDepositsPaused(UINT24_MAX), - 'StakingModuleIdTooLarge()' - ) - await assert.revertsWithCustomError(router.getStakingModuleIsActive(UINT24_MAX), 'StakingModuleIdTooLarge()') - const module = await router.getStakingModule(stakingModulesParams[0].expectedModuleId) assert.equals(module.name, stakingModulesParams[0].name) @@ -654,21 +625,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ) }) - it('update staking module reverts on large module id', async () => { - await assert.revertsWithCustomError( - router.updateStakingModule( - UINT24_MAX, - stakingModulesParams[0].targetShare + 1, - stakingModulesParams[0].stakingModuleFee + 1, - stakingModulesParams[0].treasuryFee + 1, - { - from: appManager, - } - ), - `StakingModuleIdTooLarge()` - ) - }) - it('update staking module fails on target share > 100%', async () => { await assert.revertsWithCustomError( router.updateStakingModule( @@ -741,15 +697,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ) }) - it('set staking module status reverts if staking module id too large', async () => { - await assert.revertsWithCustomError( - router.setStakingModuleStatus(UINT24_MAX, StakingModuleStatus.Stopped, { - from: appManager, - }), - `StakingModuleIdTooLarge()` - ) - }) - it('set staking module status reverts if status is the same', async () => { const module = await router.getStakingModule(stakingModulesParams[0].expectedModuleId) await assert.revertsWithCustomError( @@ -785,15 +732,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ) }) - it('pause staking module reverts when staking module too large', async () => { - await assert.revertsWithCustomError( - router.pauseStakingModule(UINT24_MAX, { - from: appManager, - }), - `StakingModuleIdTooLarge()` - ) - }) - it('pause staking module does not allowed at not active staking module', async () => { await router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Active, { from: appManager, @@ -838,13 +776,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) }) - it('deposit fails on too large module id', async () => { - await assert.revertsWithCustomError( - router.deposit(100, UINT24_MAX, '0x00', { value: 100, from: lido }), - 'StakingModuleIdTooLarge()' - ) - }) - it('deposit fails when module is not active', async () => { await assert.revertsWithCustomError( router.deposit(100, stakingModulesParams[0].expectedModuleId, '0x00', { value: ETH(32 * 100), from: lido }), @@ -868,15 +799,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ) }) - it('resume staking module reverts when staking module id too large', async () => { - await assert.revertsWithCustomError( - router.resumeStakingModule(UINT24_MAX, { - from: appManager, - }), - `StakingModuleIdTooLarge()` - ) - }) - it('resume staking module does not allowed at not paused staking module', async () => { await router.setStakingModuleStatus(stakingModulesParams[0].expectedModuleId, StakingModuleStatus.Stopped, { from: appManager, @@ -983,17 +905,6 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { before(snapshot) after(revert) - it('reverts if no stakingModuleId too large role', async () => { - const moduleId = new BN(2).pow(new BN(24)) - const nodeOperatorId = 1 - const refundedValidatorsCount = 3 - - await assert.reverts( - router.updateRefundedValidatorsCount(moduleId, nodeOperatorId, refundedValidatorsCount, { from: stranger }), - 'StakingModuleIdTooLarge()' - ) - }) - it('reverts if no STAKING_MODULE_MANAGE_ROLE role', async () => { const moduleId = 1 const nodeOperatorId = 1 From da4ac3420f8dc7cd4ada08560926d0b183405751 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 2 Mar 2023 04:06:22 +0400 Subject: [PATCH 093/236] Add arrays length checks --- contracts/0.8.9/StakingRouter.sol | 9 ++++++++ lib/abi/StakingRouter.json | 2 +- .../staking-router-keys-reporting.test.js | 22 +++++++++++++++---- .../staking-router/staking-router.test.js | 12 ++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 1a9731d75..8b047c8c5 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -52,6 +52,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version ); error InvalidDepositsValue(uint256 etherValue, uint256 depositsCount); error StakingModuleAddressExists(); + error ArraysLengthMismatch(uint256 firstArrayLength, uint256 secondArrayLength); enum StakingModuleStatus { Active, // deposits and rewards allowed @@ -252,6 +253,10 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version external onlyRole(REPORT_REWARDS_MINTED_ROLE) { + if (_stakingModuleIds.length != _totalShares.length) { + revert ArraysLengthMismatch(_stakingModuleIds.length, _totalShares.length); + } + for (uint256 i = 0; i < _stakingModuleIds.length; ) { address moduleAddr = _getStakingModuleById(_stakingModuleIds[i]).stakingModuleAddress; IStakingModule(moduleAddr).onRewardsMinted(_totalShares[i]); @@ -266,6 +271,10 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version external onlyRole(REPORT_EXITED_VALIDATORS_ROLE) { + if (_stakingModuleIds.length != _exitedValidatorsCounts.length) { + revert ArraysLengthMismatch(_stakingModuleIds.length, _exitedValidatorsCounts.length); + } + for (uint256 i = 0; i < _stakingModuleIds.length; ) { StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleIds[i]); diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index acaa10963..b8171d37f 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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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.8.9/staking-router/staking-router-keys-reporting.test.js b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js index 99d6f97c0..58b155471 100644 --- a/test/0.8.9/staking-router/staking-router-keys-reporting.test.js +++ b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js @@ -91,6 +91,16 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { ) }) + it('reverts when stakingModuleIds and exitedValidatorsCounts lengths mismatch', async () => { + const stakingModuleIds = [1, 2] + const exitedValidatorsCounts = [1, 2, 3] + await assert.reverts( + router.updateExitedValidatorsCountByStakingModule(stakingModuleIds, exitedValidatorsCounts, { from: admin }), + `ArraysLengthMismatch`, + [stakingModuleIds.length, exitedValidatorsCounts.length] + ) + }) + it('reporting total exited validators of a non-existent module reverts', async () => { await assert.reverts( router.updateExitedValidatorsCountByStakingModule([module1Id + 1], [1], { from: admin }), @@ -439,7 +449,8 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { }) // eslint-disable-next-line prettier/prettier - it(`now that exited validators totals in the router and in the module match, calling` + + it( + `now that exited validators totals in the router and in the module match, calling` + `onValidatorsCountsByNodeOperatorReportingFinished calls ` + `onExitedAndStuckValidatorsCountsUpdated on the module`, async () => { @@ -454,7 +465,8 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { ) // eslint-disable-next-line prettier/prettier - it(`calling onValidatorsCountsByNodeOperatorReportingFinished one more time calls ` + + it( + `calling onValidatorsCountsByNodeOperatorReportingFinished one more time calls ` + `onExitedAndStuckValidatorsCountsUpdated on the module again`, async () => { await router.onValidatorsCountsByNodeOperatorReportingFinished({ from: admin }) @@ -753,7 +765,8 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { }) // eslint-disable-next-line prettier/prettier - it(`now that router's view on exited validators total match the module 2's view,` + + it( + `now that router's view on exited validators total match the module 2's view,` + `calling onValidatorsCountsByNodeOperatorReportingFinished calls ` + `onExitedAndStuckValidatorsCountsUpdated on the module 2`, async () => { @@ -806,7 +819,8 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { }) // eslint-disable-next-line prettier/prettier - it(`now that router's view on exited validators total match the both modules' view,` + + it( + `now that router's view on exited validators total match the both modules' view,` + `calling onValidatorsCountsByNodeOperatorReportingFinished calls ` + `onExitedAndStuckValidatorsCountsUpdated on both modules`, async () => { diff --git a/test/0.8.9/staking-router/staking-router.test.js b/test/0.8.9/staking-router/staking-router.test.js index b149a1b41..7c3a99d1e 100644 --- a/test/0.8.9/staking-router/staking-router.test.js +++ b/test/0.8.9/staking-router/staking-router.test.js @@ -855,6 +855,18 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { ) }) + it('reverts if stakingModuleIds and totalShares lengths mismatch', async () => { + const stakingModuleIds = [1, 2, 3] + const totalShares = [300, 400] + + await router.grantRole(await router.REPORT_REWARDS_MINTED_ROLE(), admin, { from: admin }) + await assert.reverts( + router.reportRewardsMinted(stakingModuleIds, totalShares, { from: admin }), + `ArraysLengthMismatch`, + [stakingModuleIds.length, totalShares.length] + ) + }) + it('reverts if modules are not registered', async () => { const stakingModuleIds = [1, 2] const totalShares = [300, 400] From 27273b8664118b8a9b199608c689faf93b6e033f Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Thu, 2 Mar 2023 14:06:39 +0700 Subject: [PATCH 094/236] fix: time/deadline calculation --- .../oracle/base-oracle-submit-report.test.js | 112 +++++++++++------- 1 file changed, 71 insertions(+), 41 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 82ce4ba84..b429fa4c3 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,11 +1,23 @@ -const { contract } = require('hardhat') +const { contract, ethers } = require('hardhat') const { assert } = require('../../helpers/assert') +const { EvmSnapshot } = require('../../helpers/blockchain') const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') -const { SLOTS_PER_FRAME, ZERO_HASH, HASH_1, HASH_2, HASH_3, deployBaseOracle } = require('./base-oracle-deploy.test') +const { + SLOTS_PER_FRAME, + ZERO_HASH, + HASH_1, + HASH_2, + HASH_3, + deployBaseOracle, + computeTimestampAtSlot, + computeEpochFirstSlotAt, + SECONDS_PER_SLOT, +} = require('./base-oracle-deploy.test') contract('BaseOracle', ([admin]) => { + const evmSnapshot = new EvmSnapshot(ethers.provider) let consensus let baseOracle let initialRefSlot @@ -14,30 +26,43 @@ contract('BaseOracle', ([admin]) => { const deployed = await deployBaseOracle(admin, { initialEpoch: 1 }) consensus = deployed.consensusContract baseOracle = deployed.oracle - initialRefSlot = +(await baseOracle.getTime()) + const time = (await baseOracle.getTime()).toNumber() + initialRefSlot = computeEpochFirstSlotAt(time) + await evmSnapshot.make() } + const getDeadlineFromRefSlot = (slot) => computeTimestampAtSlot(+slot + SLOTS_PER_FRAME) + const getNextRefSlot = (slot) => +slot + SLOTS_PER_FRAME + + before(deployContract) + describe('submitConsensusReport is called and changes the contract state', () => { context('submitConsensusReport passes pre-conditions', () => { - before(deployContract) + before(async () => { + await evmSnapshot.rollback() + }) it('only setConsensus contract can call submitConsensusReport', async () => { await assert.revertsWithCustomError( - baseOracle.submitConsensusReport(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), + baseOracle.submitConsensusReport(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)), 'OnlyConsensusContractCanSubmitReport()' ) }) it('initial report is submitted and _handleConsensusReport is called', async () => { assert.equals((await baseOracle.getConsensusReportLastCall()).callCount, 0) - const tx = await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) + const tx = await consensus.submitReportAsConsensus( + HASH_1, + initialRefSlot, + getDeadlineFromRefSlot(initialRefSlot) + ) assert.emits( tx, 'ReportSubmitted', { refSlot: initialRefSlot, hash: HASH_1, - processingDeadlineTime: initialRefSlot + SLOTS_PER_FRAME, + processingDeadlineTime: getDeadlineFromRefSlot(initialRefSlot), }, { abi: baseOracleAbi } ) @@ -45,12 +70,12 @@ contract('BaseOracle', ([admin]) => { assert.equals(callCount, 1) assert.equal(report.hash, HASH_1) assert.equals(report.refSlot, initialRefSlot) - assert.equals(report.processingDeadlineTime, initialRefSlot + SLOTS_PER_FRAME) + assert.equals(report.processingDeadlineTime, getDeadlineFromRefSlot(initialRefSlot)) }) it('older report cannot be submitted', async () => { await assert.revertsWithCustomError( - consensus.submitReportAsConsensus(HASH_1, initialRefSlot - 1, initialRefSlot + SLOTS_PER_FRAME), + consensus.submitReportAsConsensus(HASH_1, initialRefSlot - 1, getDeadlineFromRefSlot(initialRefSlot)), `RefSlotCannotDecrease(${initialRefSlot - 1}, ${initialRefSlot})` ) }) @@ -61,29 +86,24 @@ contract('BaseOracle', ([admin]) => { it('consensus cannot resubmit already processing report', async () => { await assert.revertsWithCustomError( - consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME), + consensus.submitReportAsConsensus(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)), `RefSlotMustBeGreaterThanProcessingOne(${initialRefSlot}, ${initialRefSlot})` ) }) 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 - ) + const RefSlot2 = getNextRefSlot(initialRefSlot) + const RefSlot3 = getNextRefSlot(RefSlot2) + + const tx1 = await consensus.submitReportAsConsensus(HASH_1, RefSlot2, getDeadlineFromRefSlot(RefSlot2)) assert.equals((await baseOracle.getConsensusReportLastCall()).callCount, 2) assert.emits(tx1, 'ReportSubmitted', {}, { abi: baseOracleAbi }) - const tx2 = await consensus.submitReportAsConsensus( - HASH_1, - initialRefSlot + 20, - initialRefSlot + SLOTS_PER_FRAME - ) + const tx2 = await consensus.submitReportAsConsensus(HASH_1, RefSlot3, getDeadlineFromRefSlot(RefSlot3)) assert.emits( tx2, 'WarnProcessingMissed', - { refSlot: initialRefSlot + 10 }, + { refSlot: RefSlot2 }, { abi: baseOracleAbi, } @@ -94,7 +114,12 @@ contract('BaseOracle', ([admin]) => { }) context('submitConsensusReport updates getConsensusReport', () => { - before(deployContract) + let nextRefSlot, nextRefSlotDeadline + before(async () => { + nextRefSlot = getNextRefSlot(initialRefSlot) + nextRefSlotDeadline = getDeadlineFromRefSlot(nextRefSlot) + await evmSnapshot.rollback() + }) it('getConsensusReport at deploy returns empty state', async () => { const report = await baseOracle.getConsensusReport() @@ -105,17 +130,16 @@ contract('BaseOracle', ([admin]) => { }) it('initial report is submitted', async () => { - await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)) const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_1) assert.equals(report.refSlot, initialRefSlot) - assert.equals(report.processingDeadlineTime, initialRefSlot + SLOTS_PER_FRAME) + assert.equals(report.processingDeadlineTime, getDeadlineFromRefSlot(initialRefSlot)) 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) + const tx = await consensus.submitReportAsConsensus(HASH_2, nextRefSlot, nextRefSlotDeadline) assert.emits( tx, 'WarnProcessingMissed', @@ -127,44 +151,51 @@ contract('BaseOracle', ([admin]) => { const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_2) assert.equals(report.refSlot, nextRefSlot) - assert.equals(report.processingDeadlineTime, nextRefSlot + SLOTS_PER_FRAME) + assert.equals(report.processingDeadlineTime, nextRefSlotDeadline) 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) + const tx = await consensus.submitReportAsConsensus(HASH_3, nextRefSlot, nextRefSlotDeadline) assert.emitsNumberOfEvents(tx, 'WarnProcessingMissed', 0, { abi: baseOracleAbi, }) const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_3) assert.equals(report.refSlot, nextRefSlot) - assert.equals(report.processingDeadlineTime, nextRefSlot + SLOTS_PER_FRAME + 10) + assert.equals(report.processingDeadlineTime, nextRefSlotDeadline) 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) assert.equals(report.refSlot, nextRefSlot) - assert.equals(report.processingDeadlineTime, nextRefSlot + SLOTS_PER_FRAME + 10) + assert.equals(report.processingDeadlineTime, nextRefSlotDeadline) assert(report.processingStarted) }) }) }) describe('_startProcessing safely advances processing state', () => { - before(deployContract) + let refSlot1, refSlot2 + let refSlot1Deadline, refSlot2Deadline + before(async () => { + await evmSnapshot.rollback() + refSlot1 = getNextRefSlot(initialRefSlot) + refSlot1Deadline = getDeadlineFromRefSlot(refSlot1) + + refSlot2 = getNextRefSlot(refSlot1) + refSlot2Deadline = getDeadlineFromRefSlot(refSlot2) + }) it('initial contract state, no reports, cannot 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) + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)) const tx = await baseOracle.startProcessing() assert.emits(tx, 'ProcessingStarted', { refSlot: initialRefSlot, hash: HASH_1 }) assert.emits(tx, 'MockStartProcessingResult', { prevProcessingRefSlot: '0' }) @@ -175,19 +206,18 @@ contract('BaseOracle', ([admin]) => { }) it('next report comes in, start processing, state advances', async () => { - await consensus.submitReportAsConsensus(HASH_2, initialRefSlot + 10, initialRefSlot + 20) + await consensus.submitReportAsConsensus(HASH_2, refSlot1, refSlot1Deadline) const tx = await baseOracle.startProcessing() - assert.emits(tx, 'ProcessingStarted', { refSlot: initialRefSlot + 10, hash: HASH_2 }) + assert.emits(tx, 'ProcessingStarted', { refSlot: refSlot1, hash: HASH_2 }) assert.emits(tx, 'MockStartProcessingResult', { prevProcessingRefSlot: String(initialRefSlot) }) const processingSlot = await baseOracle.getLastProcessingRefSlot() - assert.equals(processingSlot, initialRefSlot + 10) + assert.equals(processingSlot, refSlot1) }) 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})`) + await consensus.submitReportAsConsensus(HASH_3, refSlot2, refSlot2Deadline) + await baseOracle.setTime(refSlot2Deadline + SECONDS_PER_SLOT * 10) + await assert.revertsWithCustomError(baseOracle.startProcessing(), `ProcessingDeadlineMissed(${refSlot2Deadline})`) }) }) }) From 15904651c82a764e1e317c88bb8a8816442bb106 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Thu, 2 Mar 2023 15:43:24 +0700 Subject: [PATCH 095/236] fix: deadline in setConsensus tests --- test/0.8.9/oracle/base-oracle-deploy.test.js | 4 ++ .../oracle/base-oracle-set-consensus.test.js | 42 +++++++++++------ .../oracle/base-oracle-submit-report.test.js | 45 +++++++++---------- 3 files changed, 53 insertions(+), 38 deletions(-) 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 067039e90..b0bab7c32 100644 --- a/test/0.8.9/oracle/base-oracle-deploy.test.js +++ b/test/0.8.9/oracle/base-oracle-deploy.test.js @@ -21,6 +21,8 @@ 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 computeDeadlineFromRefSlot = (slot) => computeTimestampAtSlot(+slot + SLOTS_PER_FRAME) +const computeNextRefSlotFromRefSlot = (slot) => +slot + SLOTS_PER_FRAME const ZERO_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000' @@ -85,6 +87,8 @@ module.exports = { computeEpochFirstSlotAt, computeTimestampAtSlot, computeTimestampAtEpoch, + computeNextRefSlotFromRefSlot, + computeDeadlineFromRefSlot, ZERO_HASH, HASH_1, HASH_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 28e857dee..9b5703a9b 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 @@ -1,6 +1,7 @@ -const { contract, artifacts, web3 } = require('hardhat') +const { contract, artifacts, web3, ethers } = require('hardhat') const { assert } = require('../../helpers/assert') const { ZERO_ADDRESS } = require('../../helpers/constants') +const { EvmSnapshot } = require('../../helpers/blockchain') const MockConsensusContract = artifacts.require('MockConsensusContract') @@ -9,14 +10,17 @@ const { SECONDS_PER_SLOT, GENESIS_TIME, EPOCHS_PER_FRAME, - SLOTS_PER_FRAME, HASH_1, HASH_2, CONSENSUS_VERSION, + computeEpochFirstSlotAt, + computeNextRefSlotFromRefSlot, + computeDeadlineFromRefSlot, deployBaseOracle, } = require('./base-oracle-deploy.test') contract('BaseOracle', ([admin, member, notMember]) => { + const evmSnapshot = new EvmSnapshot(ethers.provider) let consensus let baseOracle let initialRefSlot @@ -27,11 +31,16 @@ contract('BaseOracle', ([admin, member, notMember]) => { 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()) + const time = (await baseOracle.getTime()).toNumber() + initialRefSlot = computeEpochFirstSlotAt(time) + await evmSnapshot.make() } + const rollback = async () => evmSnapshot.rollback() + + before(deployContract) describe('setConsensusContract safely changes used consensus contract', () => { - before(deployContract) + before(rollback) it('reverts on zero address', async () => { await assert.revertsWithCustomError(baseOracle.setConsensusContract(ZERO_ADDRESS), 'AddressCannotBeZero()') @@ -75,7 +84,7 @@ contract('BaseOracle', ([admin, member, notMember]) => { { from: admin } ) await wrongConsensusContract.setCurrentFrame(10, 1, 2000) - await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + SLOTS_PER_FRAME) + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, computeDeadlineFromRefSlot(initialRefSlot)) await baseOracle.startProcessing() await assert.revertsWithCustomError( @@ -95,7 +104,9 @@ contract('BaseOracle', ([admin, member, notMember]) => { admin, { from: admin } ) - await newConsensusContract.setCurrentFrame(10, initialRefSlot + 1, initialRefSlot + SLOTS_PER_FRAME) + + const nextRefSlot = computeNextRefSlotFromRefSlot(initialRefSlot) + await newConsensusContract.setCurrentFrame(10, nextRefSlot, computeDeadlineFromRefSlot(nextRefSlot)) const tx = await baseOracle.setConsensusContract(newConsensusContract.address) assert.emits(tx, 'ConsensusHashContractSet', { addr: newConsensusContract.address, prevAddr: consensus.address }) const addressAtStorage = await baseOracle.getConsensusContract() @@ -104,7 +115,7 @@ contract('BaseOracle', ([admin, member, notMember]) => { }) describe('setConsensusVersion updates contract state', () => { - before(deployContract) + before(rollback) it('reverts on same version', async () => { await assert.revertsWithCustomError(baseOracle.setConsensusVersion(CONSENSUS_VERSION), 'VersionCannotBeSame()') @@ -119,19 +130,22 @@ contract('BaseOracle', ([admin, member, notMember]) => { }) describe('_checkConsensusData checks provided data against internal state', () => { - before(deployContract) + before(rollback) + let deadline it('report is submitted', async () => { - await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, initialRefSlot + 10) + deadline = computeDeadlineFromRefSlot(initialRefSlot) + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, deadline) }) it('deadline missed on current ref slot, reverts on any arguments', async () => { - await baseOracle.advanceTimeBy(11) + const oldTime = await baseOracle.getTime() + await baseOracle.setTime(deadline + 10) await assert.revertsWithCustomError( baseOracle.checkConsensusData(initialRefSlot, CONSENSUS_VERSION, HASH_1), - `ProcessingDeadlineMissed(${initialRefSlot + 10})` + `ProcessingDeadlineMissed(${deadline})` ) - await baseOracle.setTime(initialRefSlot) + await baseOracle.setTime(oldTime) }) it('reverts on mismatched slot', async () => { @@ -161,7 +175,7 @@ contract('BaseOracle', ([admin, member, notMember]) => { }) describe('_isConsensusMember correctly check address for consensus membership trough consensus contract', () => { - before(deployContract) + before(rollback) it('returns false on non member', async () => { const r = await baseOracle.isConsensusMember(notMember) @@ -175,7 +189,7 @@ contract('BaseOracle', ([admin, member, notMember]) => { }) describe('_getCurrentRefSlot correctly gets refSlot trough consensus contract', () => { - before(deployContract) + before(rollback) it('refSlot matches', async () => { const oracle_slot = await baseOracle.getCurrentRefSlot() 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 b429fa4c3..1ebd65b75 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,13 +5,13 @@ const { EvmSnapshot } = require('../../helpers/blockchain') const baseOracleAbi = require('../../../lib/abi/BaseOracle.json') const { - SLOTS_PER_FRAME, ZERO_HASH, HASH_1, HASH_2, HASH_3, deployBaseOracle, - computeTimestampAtSlot, + computeDeadlineFromRefSlot, + computeNextRefSlotFromRefSlot, computeEpochFirstSlotAt, SECONDS_PER_SLOT, } = require('./base-oracle-deploy.test') @@ -31,9 +31,6 @@ contract('BaseOracle', ([admin]) => { await evmSnapshot.make() } - const getDeadlineFromRefSlot = (slot) => computeTimestampAtSlot(+slot + SLOTS_PER_FRAME) - const getNextRefSlot = (slot) => +slot + SLOTS_PER_FRAME - before(deployContract) describe('submitConsensusReport is called and changes the contract state', () => { @@ -44,7 +41,7 @@ contract('BaseOracle', ([admin]) => { it('only setConsensus contract can call submitConsensusReport', async () => { await assert.revertsWithCustomError( - baseOracle.submitConsensusReport(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)), + baseOracle.submitConsensusReport(HASH_1, initialRefSlot, computeDeadlineFromRefSlot(initialRefSlot)), 'OnlyConsensusContractCanSubmitReport()' ) }) @@ -54,7 +51,7 @@ contract('BaseOracle', ([admin]) => { const tx = await consensus.submitReportAsConsensus( HASH_1, initialRefSlot, - getDeadlineFromRefSlot(initialRefSlot) + computeDeadlineFromRefSlot(initialRefSlot) ) assert.emits( tx, @@ -62,7 +59,7 @@ contract('BaseOracle', ([admin]) => { { refSlot: initialRefSlot, hash: HASH_1, - processingDeadlineTime: getDeadlineFromRefSlot(initialRefSlot), + processingDeadlineTime: computeDeadlineFromRefSlot(initialRefSlot), }, { abi: baseOracleAbi } ) @@ -70,12 +67,12 @@ contract('BaseOracle', ([admin]) => { assert.equals(callCount, 1) assert.equal(report.hash, HASH_1) assert.equals(report.refSlot, initialRefSlot) - assert.equals(report.processingDeadlineTime, getDeadlineFromRefSlot(initialRefSlot)) + assert.equals(report.processingDeadlineTime, computeDeadlineFromRefSlot(initialRefSlot)) }) it('older report cannot be submitted', async () => { await assert.revertsWithCustomError( - consensus.submitReportAsConsensus(HASH_1, initialRefSlot - 1, getDeadlineFromRefSlot(initialRefSlot)), + consensus.submitReportAsConsensus(HASH_1, initialRefSlot - 1, computeDeadlineFromRefSlot(initialRefSlot)), `RefSlotCannotDecrease(${initialRefSlot - 1}, ${initialRefSlot})` ) }) @@ -86,20 +83,20 @@ contract('BaseOracle', ([admin]) => { it('consensus cannot resubmit already processing report', async () => { await assert.revertsWithCustomError( - consensus.submitReportAsConsensus(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)), + consensus.submitReportAsConsensus(HASH_1, initialRefSlot, computeDeadlineFromRefSlot(initialRefSlot)), `RefSlotMustBeGreaterThanProcessingOne(${initialRefSlot}, ${initialRefSlot})` ) }) it('warning event is emitted when newer report is submitted and prev has not started processing yet', async () => { - const RefSlot2 = getNextRefSlot(initialRefSlot) - const RefSlot3 = getNextRefSlot(RefSlot2) + const RefSlot2 = computeNextRefSlotFromRefSlot(initialRefSlot) + const RefSlot3 = computeNextRefSlotFromRefSlot(RefSlot2) - const tx1 = await consensus.submitReportAsConsensus(HASH_1, RefSlot2, getDeadlineFromRefSlot(RefSlot2)) + const tx1 = await consensus.submitReportAsConsensus(HASH_1, RefSlot2, computeDeadlineFromRefSlot(RefSlot2)) assert.equals((await baseOracle.getConsensusReportLastCall()).callCount, 2) assert.emits(tx1, 'ReportSubmitted', {}, { abi: baseOracleAbi }) - const tx2 = await consensus.submitReportAsConsensus(HASH_1, RefSlot3, getDeadlineFromRefSlot(RefSlot3)) + const tx2 = await consensus.submitReportAsConsensus(HASH_1, RefSlot3, computeDeadlineFromRefSlot(RefSlot3)) assert.emits( tx2, 'WarnProcessingMissed', @@ -116,8 +113,8 @@ contract('BaseOracle', ([admin]) => { context('submitConsensusReport updates getConsensusReport', () => { let nextRefSlot, nextRefSlotDeadline before(async () => { - nextRefSlot = getNextRefSlot(initialRefSlot) - nextRefSlotDeadline = getDeadlineFromRefSlot(nextRefSlot) + nextRefSlot = computeNextRefSlotFromRefSlot(initialRefSlot) + nextRefSlotDeadline = computeDeadlineFromRefSlot(nextRefSlot) await evmSnapshot.rollback() }) @@ -130,11 +127,11 @@ contract('BaseOracle', ([admin]) => { }) it('initial report is submitted', async () => { - await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)) + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, computeDeadlineFromRefSlot(initialRefSlot)) const report = await baseOracle.getConsensusReport() assert.equal(report.hash, HASH_1) assert.equals(report.refSlot, initialRefSlot) - assert.equals(report.processingDeadlineTime, getDeadlineFromRefSlot(initialRefSlot)) + assert.equals(report.processingDeadlineTime, computeDeadlineFromRefSlot(initialRefSlot)) assert(!report.processingStarted) }) @@ -183,11 +180,11 @@ contract('BaseOracle', ([admin]) => { let refSlot1Deadline, refSlot2Deadline before(async () => { await evmSnapshot.rollback() - refSlot1 = getNextRefSlot(initialRefSlot) - refSlot1Deadline = getDeadlineFromRefSlot(refSlot1) + refSlot1 = computeNextRefSlotFromRefSlot(initialRefSlot) + refSlot1Deadline = computeDeadlineFromRefSlot(refSlot1) - refSlot2 = getNextRefSlot(refSlot1) - refSlot2Deadline = getDeadlineFromRefSlot(refSlot2) + refSlot2 = computeNextRefSlotFromRefSlot(refSlot1) + refSlot2Deadline = computeDeadlineFromRefSlot(refSlot2) }) it('initial contract state, no reports, cannot startProcessing', async () => { @@ -195,7 +192,7 @@ contract('BaseOracle', ([admin]) => { }) it('submit first report for initial slot', async () => { - await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, getDeadlineFromRefSlot(initialRefSlot)) + await consensus.submitReportAsConsensus(HASH_1, initialRefSlot, computeDeadlineFromRefSlot(initialRefSlot)) const tx = await baseOracle.startProcessing() assert.emits(tx, 'ProcessingStarted', { refSlot: initialRefSlot, hash: HASH_1 }) assert.emits(tx, 'MockStartProcessingResult', { prevProcessingRefSlot: '0' }) From d53b1bec44ab5491f28e0e57f06c23041c9deccb Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 12:13:18 +0200 Subject: [PATCH 096/236] feat: calculate extremas on each request --- contracts/0.8.9/WithdrawalQueueBase.sol | 146 ++++++++++-------- ...ithdrawal-queue-share-rate-changes.test.js | 12 +- 2 files changed, 85 insertions(+), 73 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 7ec32aaa3..a717222b2 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -188,6 +188,7 @@ abstract contract WithdrawalQueueBase { requestId = _state.batches[_state.batches[0]] + 1; prevRequestShareRate = _calcShareRate(_state.batches[_state.batches[0]], _maxShareRate); } + uint256 lastRequestId = getLastRequestId(); uint256 maxPossibleRequestId = requestId + MAX_REQUESTS_PER_CALL; @@ -198,9 +199,7 @@ abstract contract WithdrawalQueueBase { if (requestId > lastRequestId) break; // if end of the queue if (requestId == _getExtrema()[extemumStartIndex + extremaCounter]) { - unchecked{ - ++extremaCounter; - } + unchecked { ++extremaCounter; } if (extremaCounter > MAX_EXTREMA_PER_CALL) break; } @@ -253,59 +252,8 @@ abstract contract WithdrawalQueueBase { } function onPreRebase(uint256 reportTimestamp) external { + // TODO: auth and sanity checks _setLastReportTimestamp(reportTimestamp); - - // Populate shareRate extrema list - // TODO: move it to withdrawal request creation moment - uint256 lastRequestId = getLastRequestId(); - uint256[] storage extrema = _getExtrema(); - // first request is an extremum by default - if (extrema.length == 1 && lastRequestId > 0) { - extrema.push(lastRequestId); - return; - } - - uint256 lastExtremumId = extrema[extrema.length - 1]; - // no new requests => no new exrema - if (lastExtremumId == lastRequestId) return; - - WithdrawalRequest memory lastRequest = _getQueue()[lastRequestId]; - WithdrawalRequest memory lastExtremum = _getQueue()[lastExtremumId]; - - if (lastRequest.reportTimestamp == lastExtremum.reportTimestamp) return; - - uint256 lastRequestShareRate = _calcShareRate(lastRequestId, lastRequest); - uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId, lastExtremum); - - if (lastRequestShareRate == lastExtremumShareRate) return; - // first met request in a sequence with equal shareRate is an extremum - - if (extrema.length == 2) { - // first two different rates are always extrema - extrema.push(lastRequestId); - } else { - uint256 prevExtremumShareRate = _calcShareRate(lastExtremumId - 1, SHARE_RATE_UNLIMITED); - - bool wasGrowing = lastExtremumShareRate > prevExtremumShareRate; - // | • - // |• * - // +-------> - if (wasGrowing && lastRequestShareRate < lastExtremumShareRate) { - extrema.push(lastRequestId); - return; - } - // |• * - // | • - // +-------> - if (!wasGrowing && lastRequestShareRate > lastExtremumShareRate) { - extrema.push(lastRequestId); - return; - } - // |• | * - // | * OR |• - // +----> +----> - extrema[extrema.length - 1] = lastRequestId; - } } function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate) @@ -357,8 +305,9 @@ abstract contract WithdrawalQueueBase { uint256 batchPreStartId = getLastFinalizedRequestId(); uint256 batchEndId = _batches[batchIndex]; - uint256 extremumIndex = _getLastCheckedExtremum() + 1; - uint256 extremumId; + uint256 extremumIndex = _getLastCheckedExtremum(); + uint256 extremumLength = _getExtrema().length; + uint256 extremumId = _getExtrema()[extremumIndex]; uint256 batchShareRate= _calcShareRate( _getQueue()[batchPreStartId], @@ -367,13 +316,14 @@ abstract contract WithdrawalQueueBase { ); while (batchIndex < _batches.length - 1) { - if (extremumId < batchEndId) { - extremumId = _getExtrema()[extremumIndex]; - // check extremum - uint256 extremumShareRate = _calcShareRate(extremumId, SHARE_RATE_UNLIMITED); + if (extremumId <= batchEndId && extremumIndex < extremumLength - 1) { + if (extremumId > batchPreStartId) { + // check extremum + uint256 extremumShareRate = _calcShareRate(extremumId, SHARE_RATE_UNLIMITED); - if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); - if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); + if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); + if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); + } unchecked { ++extremumIndex; } } else { // check crossing point @@ -396,7 +346,7 @@ abstract contract WithdrawalQueueBase { } } - return extremumIndex - 1; + return extremumIndex; } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` @@ -457,14 +407,76 @@ abstract contract WithdrawalQueueBase { requestId = lastRequestId + 1; _setLastRequestId(requestId); - _getQueue()[requestId] = - WithdrawalRequest(cumulativeStETH, cumulativeShares, _owner, uint64(block.timestamp), false, - uint64(_getLastReportTimestamp())); + + WithdrawalRequest memory newRequest = WithdrawalRequest( + cumulativeStETH, + cumulativeShares, + _owner, + uint64(block.timestamp), + false, + uint64(_getLastReportTimestamp()) + ); + _getQueue()[requestId] = newRequest; assert(_getRequestsByOwner()[_owner].add(requestId)); + _populateExtrema(lastRequest, newRequest, requestId); + emit WithdrawalRequested(requestId, msg.sender, _owner, _amountOfStETH, _amountOfShares); } + /// @dev storing extrema of shareRate(requestId) function using three points: + /// newRequestId, prevRequestId and last known extremum id + /// - first request is always included as an extremum + /// - last request is not added by default to avoid storage write on each request + /// but speaking strictly last request is also an extremum + /// - if a lot of requests in a row have the same shareRate, the last one + /// will become an exremum as shareRate changes + function _populateExtrema( + WithdrawalRequest memory prevRequest, + WithdrawalRequest memory newRequest, + uint256 newRequestId + ) internal { + // shortcut for the same shareRate batches + // requests is guaranteed to be the same shareRate if they belong to + // the same oracle report period + if (prevRequest.reportTimestamp == newRequest.reportTimestamp) return; + + uint256[] storage extrema = _getExtrema(); + // bootstrap the algo adding thee first request as an extrema by default + if (extrema.length == 1 && newRequestId > 0) { + extrema.push(newRequestId); + return; + } + + uint256 lastExtremumId = extrema[extrema.length - 1]; + WithdrawalRequest memory lastExtremumRequest = _getQueue()[lastExtremumId]; + + uint256 newRequestShareRate = _calcShareRate(prevRequest, newRequest, SHARE_RATE_UNLIMITED); + uint256 prevRequestShareRate = _calcShareRate(newRequestId - 1, SHARE_RATE_UNLIMITED); + + // we can get a new extremum only when shareRate changes + // there can't be rounding jitter because we skipped on the same report requests in the beginning + if (newRequestShareRate == prevRequestShareRate) return; + + uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId, lastExtremumRequest); + + bool wasGrowing = lastExtremumShareRate < prevRequestShareRate; + // | * + // |• • + // +-------> + if (wasGrowing && prevRequestShareRate > newRequestShareRate) { + extrema.push(newRequestId - 1); + return; + } + // |• • + // | * + // +-------> + if (!wasGrowing && prevRequestShareRate < newRequestShareRate) { + extrema.push(newRequestId - 1); + return; + } + } + /// @notice Returns status of the withdrawal request with `_requestId` id function _getStatus(uint256 _requestId) internal view returns (WithdrawalRequestStatus memory status) { if (_requestId == 0 || _requestId > getLastRequestId()) revert InvalidRequestId(_requestId); diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index e48e8dc9a..2746c6c24 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -16,7 +16,9 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { let queue, steth + let rebaseCounter = 0 const setShareRate = async (rate) => { + await queue.onPreRebase(rebaseCounter++) await steth.setTotalPooledEther(TOTAL_SHARES.mul(toBN(rate))) } @@ -60,7 +62,6 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives rewards, changing share rate to 2.0`, async () => { - await queue.onPreRebase() await setShareRate(2) }) @@ -71,7 +72,6 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives slashing, changing share rate to 1.0`, async () => { - await queue.onPreRebase() await setShareRate(1) }) @@ -80,6 +80,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { it(`both requests can be finalized with 2 ETH`, async () => { const result = await queue.calculateFinalizationBatches(e27(1), MAX_UINT256, [e18(2), false, []]) assert.isTrue(result.finished) + assert.equals(result.batches, [1, 2]) const batch = await queue.prefinalize.call(result.batches, e27(1)) assert.equals(batch.ethToLock, e18(2)) @@ -126,7 +127,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives rewards, changing share rate to 2.0`, async () => { - await queue.onPreRebase() + await queue.onPreRebase(e27(2)) await setShareRate(2) }) @@ -137,7 +138,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives slashing, changing share rate to 1.0`, async () => { - await queue.onPreRebase() + await queue.onPreRebase(e27(1)) await setShareRate(1) }) @@ -147,8 +148,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { it(`both requests can be finalized with 2 ETH`, async () => { const result = await queue.calculateFinalizationBatches(maxShareRate, MAX_UINT256, [e18(2.5), false, []]) assert.isTrue(result.finished) - - console.log(result) + assert.equals(result.batches, [1, 2]) const batch = await queue.prefinalize.call(result.batches, maxShareRate) assert.equals(batch.ethToLock, e18(2.5)) From f30483ff9f8a178af923677b6268be71ee9d4396 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Thu, 2 Mar 2023 18:03:12 +0700 Subject: [PATCH 097/236] test: Versioned 0.4.24 --- .../0.4.24/test_helpers/VersionedMock.sol | 21 +++++++ test/0.4.24/versioned.test.js | 55 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 contracts/0.4.24/test_helpers/VersionedMock.sol create mode 100644 test/0.4.24/versioned.test.js diff --git a/contracts/0.4.24/test_helpers/VersionedMock.sol b/contracts/0.4.24/test_helpers/VersionedMock.sol new file mode 100644 index 000000000..c78513f95 --- /dev/null +++ b/contracts/0.4.24/test_helpers/VersionedMock.sol @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.4.24; + +import { Versioned } from "../utils/Versioned.sol"; + +contract VersionedMock is Versioned { + constructor() public {} + + function getPetrifiedVersionMark() external pure returns (uint256) { + return PETRIFIED_VERSION_MARK; + } + + function checkContractVersion(uint256 version) external view { + _checkContractVersion(version); + } + + function setContractVersion(uint256 version) external { + _setContractVersion(version); + } +} diff --git a/test/0.4.24/versioned.test.js b/test/0.4.24/versioned.test.js new file mode 100644 index 000000000..2927494c4 --- /dev/null +++ b/test/0.4.24/versioned.test.js @@ -0,0 +1,55 @@ +const { contract, artifacts } = require('hardhat') +const { assert } = require('../helpers/assert') + +async function deployBehindOssifiableProxy(artifactName, proxyOwner, constructorArgs = []) { + const Contract = await artifacts.require(artifactName) + const implementation = await Contract.new(...constructorArgs, { from: proxyOwner }) + const OssifiableProxy = await artifacts.require('OssifiableProxy') + const proxy = await OssifiableProxy.new(implementation.address, proxyOwner, [], { from: proxyOwner }) + const proxied = await Contract.at(proxy.address) + return { implementation, proxy, proxied } +} + +contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { + let versionedImpl + let versionedProxied + const VERSION_INIT = 1 + const VERSION_ZERO = 0 + + before('Deploy', async () => { + const deployed = await deployBehindOssifiableProxy( + 'contracts/0.4.24/test_helpers/VersionedMock.sol:VersionedMock', + proxyOwner, + [] + ) + versionedImpl = deployed.implementation + versionedProxied = deployed.proxied + }) + + describe('raw implementation', async () => { + it('default version is petrified', async () => { + const versionPetrified = await versionedImpl.getPetrifiedVersionMark() + assert.equals(await versionedImpl.getContractVersion(), versionPetrified) + await assert.reverts(versionedImpl.checkContractVersion(VERSION_ZERO), `UNEXPECTED_CONTRACT_VERSION`) + }) + }) + + describe('behind proxy', () => { + it('default version is zero', async () => { + const version = await versionedProxied.getContractVersion() + console.log(+version) + assert.equals(version, VERSION_ZERO) + await assert.reverts(versionedProxied.checkContractVersion(VERSION_INIT), `UNEXPECTED_CONTRACT_VERSION`) + }) + + it('version can be set and event should be emitted', async () => { + const prevVersion = +(await versionedProxied.getContractVersion()) + const nextVersion = prevVersion + 1 + const tx = await versionedProxied.setContractVersion(nextVersion) + assert.emits(tx, 'ContractVersionSet', { version: nextVersion }) + await assert.reverts(versionedProxied.checkContractVersion(prevVersion), `UNEXPECTED_CONTRACT_VERSION`) + const newVersion = +(await versionedProxied.getContractVersion()) + assert.equals(newVersion, nextVersion) + }) + }) +}) From 241f89a3a9032f2c85c39f22c0aa9eeda68714e7 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 13:10:01 +0200 Subject: [PATCH 098/236] fix: optimize withdrawal request storage --- contracts/0.8.9/WithdrawalQueueBase.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index a717222b2..fb6c37fe6 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -62,11 +62,11 @@ abstract contract WithdrawalQueueBase { /// @notice address that can claim or transfer the request address owner; /// @notice block.timestamp when the request was created - uint64 timestamp; + uint40 timestamp; /// @notice flag if the request was claimed bool claimed; - - uint64 reportTimestamp; + /// @notice timestamp of lastReport + uint40 reportTimestamp; } /// @notice structure to store discounts for requests that are affected by negative rebase @@ -412,9 +412,9 @@ abstract contract WithdrawalQueueBase { cumulativeStETH, cumulativeShares, _owner, - uint64(block.timestamp), + uint40(block.timestamp), false, - uint64(_getLastReportTimestamp()) + uint40(_getLastReportTimestamp()) ); _getQueue()[requestId] = newRequest; assert(_getRequestsByOwner()[_owner].add(requestId)); @@ -612,7 +612,7 @@ abstract contract WithdrawalQueueBase { // setting dummy zero structs in checkpoints and queue beginning // to avoid uint underflows and related if-branches // 0-index is reserved as 'not_found' response in the interface everywhere - _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint64(block.number), true, 0); + _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint40(block.timestamp), true, 0); _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, 0); _getExtrema().push(0); } From c9af4633ed4e4a826b2640686cf2591c97dd82e5 Mon Sep 17 00:00:00 2001 From: Dmitrii Podlesnyi Date: Thu, 2 Mar 2023 18:18:18 +0700 Subject: [PATCH 099/236] test: better coverage for Versioned --- test/0.4.24/versioned.test.js | 4 +++- test/0.8.9/versioned.test.js | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/0.4.24/versioned.test.js b/test/0.4.24/versioned.test.js index 2927494c4..4ce477e9f 100644 --- a/test/0.4.24/versioned.test.js +++ b/test/0.4.24/versioned.test.js @@ -30,6 +30,7 @@ contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { it('default version is petrified', async () => { const versionPetrified = await versionedImpl.getPetrifiedVersionMark() assert.equals(await versionedImpl.getContractVersion(), versionPetrified) + await versionedImpl.checkContractVersion(versionPetrified) await assert.reverts(versionedImpl.checkContractVersion(VERSION_ZERO), `UNEXPECTED_CONTRACT_VERSION`) }) }) @@ -37,8 +38,8 @@ contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { describe('behind proxy', () => { it('default version is zero', async () => { const version = await versionedProxied.getContractVersion() - console.log(+version) assert.equals(version, VERSION_ZERO) + await versionedProxied.checkContractVersion(VERSION_ZERO) await assert.reverts(versionedProxied.checkContractVersion(VERSION_INIT), `UNEXPECTED_CONTRACT_VERSION`) }) @@ -47,6 +48,7 @@ contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { const nextVersion = prevVersion + 1 const tx = await versionedProxied.setContractVersion(nextVersion) assert.emits(tx, 'ContractVersionSet', { version: nextVersion }) + await versionedProxied.checkContractVersion(nextVersion) await assert.reverts(versionedProxied.checkContractVersion(prevVersion), `UNEXPECTED_CONTRACT_VERSION`) const newVersion = +(await versionedProxied.getContractVersion()) assert.equals(newVersion, nextVersion) diff --git a/test/0.8.9/versioned.test.js b/test/0.8.9/versioned.test.js index a0f59bbad..314e891d9 100644 --- a/test/0.8.9/versioned.test.js +++ b/test/0.8.9/versioned.test.js @@ -46,6 +46,7 @@ contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { it('default version is zero', async () => { const version = await versionedProxied.getContractVersion() assert.equals(version, VERSION_ZERO) + await versionedProxied.checkContractVersion(VERSION_ZERO) await assert.reverts( versionedProxied.checkContractVersion(VERSION_INIT), `UnexpectedContractVersion(${VERSION_ZERO}, ${VERSION_INIT})` @@ -56,6 +57,7 @@ contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { const tx = await versionedProxied.initializeContractVersionTo(VERSION_INIT) assert.emits(tx, 'ContractVersionSet', { version: VERSION_INIT }) assert.equals(await versionedProxied.getContractVersion(), VERSION_INIT) + await versionedProxied.checkContractVersion(VERSION_INIT) await assert.reverts( versionedProxied.checkContractVersion(VERSION_ZERO), `UnexpectedContractVersion(${VERSION_INIT}, ${VERSION_ZERO})` @@ -71,6 +73,7 @@ contract('Versioned', ([admin, proxyOwner, account2, member1, member2]) => { const nextVersion = prevVersion + 1 const tx = await versionedProxied.updateContractVersion(nextVersion) assert.emits(tx, 'ContractVersionSet', { version: nextVersion }) + await versionedProxied.checkContractVersion(nextVersion) await assert.reverts( versionedProxied.checkContractVersion(prevVersion), `UnexpectedContractVersion(${nextVersion}, ${prevVersion})` From 58065276c98d4917e49e463914ec166037f2b17a Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 13:28:33 +0200 Subject: [PATCH 100/236] fix: properly report timestamp to withdrawal queue --- contracts/0.8.9/WithdrawalQueue.sol | 14 +++++++---- contracts/0.8.9/WithdrawalQueueBase.sol | 7 +----- contracts/0.8.9/oracle/AccountingOracle.sol | 10 ++++---- .../MockWithdrawalQueueForAccoutingOracle.sol | 23 +++++++------------ lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- .../oracle/accounting-oracle-deploy.test.js | 2 +- .../accounting-oracle-happy-path.test.js | 4 ++-- ...counting-oracle-submit-report-data.test.js | 4 +++- 10 files changed, 31 insertions(+), 39 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 0a23f8386..6a6ec8557 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -38,7 +38,7 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE"); bytes32 public constant RESUME_ROLE = keccak256("RESUME_ROLE"); bytes32 public constant FINALIZE_ROLE = keccak256("FINALIZE_ROLE"); - bytes32 public constant BUNKER_MODE_REPORT_ROLE = keccak256("BUNKER_MODE_REPORT_ROLE"); + bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE"); /// @notice minimal possible sum that is possible to withdraw uint256 public constant MIN_STETH_WITHDRAWAL_AMOUNT = 100; @@ -258,14 +258,18 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit _finalize(_batches, msg.value, _maxShareRate); } - /// @notice Update bunker mode state + /// @notice Update bunker mode state and last report timestamp /// @dev should be called by oracle /// - /// @param _isBunkerModeNow oracle report + /// @param _isBunkerModeNow is bunker mode reported by oracle /// @param _sinceTimestamp timestamp of start of the bunker mode - function updateBunkerMode(bool _isBunkerModeNow, uint256 _sinceTimestamp) external { - _checkRole(BUNKER_MODE_REPORT_ROLE, msg.sender); + /// @param _currentReportTimestamp timestamp of the current report ref slot + function onOracleReport(bool _isBunkerModeNow, uint256 _sinceTimestamp, uint256 _currentReportTimestamp) external { + _checkRole(ORACLE_ROLE, msg.sender); if (_sinceTimestamp >= block.timestamp) revert InvalidReportTimestamp(); + if (_currentReportTimestamp >= block.timestamp) revert InvalidReportTimestamp(); + + _setLastReportTimestamp(_currentReportTimestamp); bool isBunkerModeWasSetBefore = isBunkerModeActive(); diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index fb6c37fe6..502f3749c 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -251,13 +251,8 @@ abstract contract WithdrawalQueueBase { return _state; } - function onPreRebase(uint256 reportTimestamp) external { - // TODO: auth and sanity checks - _setLastReportTimestamp(reportTimestamp); - } - function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate) - public + external returns (uint256 ethToLock, uint256 sharesToBurn) { if (_maxShareRate == 0) revert ZeroShareRate(); diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index bc790d87c..53463f59d 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -81,8 +81,7 @@ interface IStakingRouter { interface IWithdrawalQueue { - function updateBunkerMode(bool isBunkerMode, uint256 prevReportTimestamp) external; - function onPreRebase() external; + function onOracleReport(bool isBunkerMode, uint256 prevReportTimestamp, uint256 currentReportTimestamp) external; } @@ -606,13 +605,12 @@ contract AccountingOracle is BaseOracle { slotsElapsed ); - withdrawalQueue.updateBunkerMode( + withdrawalQueue.onOracleReport( data.isBunkerMode, - GENESIS_TIME + prevRefSlot * SECONDS_PER_SLOT + GENESIS_TIME + prevRefSlot * SECONDS_PER_SLOT, + GENESIS_TIME + data.refSlot * SECONDS_PER_SLOT ); - withdrawalQueue.onPreRebase(); - ILido(LIDO).handleOracleReport( GENESIS_TIME + data.refSlot * SECONDS_PER_SLOT, slotsElapsed * SECONDS_PER_SLOT, diff --git a/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol b/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol index e305c6a50..4142d29b6 100644 --- a/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol +++ b/contracts/0.8.9/test_helpers/oracle/MockWithdrawalQueueForAccoutingOracle.sol @@ -5,26 +5,19 @@ pragma solidity 0.8.9; import { IWithdrawalQueue } from "../../oracle/AccountingOracle.sol"; contract MockWithdrawalQueueForAccountingOracle is IWithdrawalQueue { - struct OnPreRebaseCallData { - uint256 callCount; - } - - struct UpdateBunkerModeCallData { + struct OnOracleReportCallData { bool isBunkerMode; uint256 prevReportTimestamp; + uint256 currentReportTimestamp; uint256 callCount; } - UpdateBunkerModeCallData public lastCall__updateBunkerMode; - OnPreRebaseCallData public lastCall__onPreRebase; - - function updateBunkerMode(bool isBunkerMode, uint256 prevReportTimestamp) external { - lastCall__updateBunkerMode.isBunkerMode = isBunkerMode; - lastCall__updateBunkerMode.prevReportTimestamp = prevReportTimestamp; - ++lastCall__updateBunkerMode.callCount; - } + OnOracleReportCallData public lastCall__onOracleReport; - function onPreRebase() external { - ++lastCall__onPreRebase.callCount; + function onOracleReport(bool isBunkerMode, uint256 prevReportTimestamp, uint256 currentReportTimestamp) external { + lastCall__onOracleReport.isBunkerMode = isBunkerMode; + lastCall__onOracleReport.prevReportTimestamp = prevReportTimestamp; + lastCall__onOracleReport.currentReportTimestamp = currentReportTimestamp; + ++lastCall__onOracleReport.callCount; } } diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index fc1c97790..a55253658 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"reportTimestamp","type":"uint256"}],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index e4ad83217..cd9dbd396 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"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":"uint256","name":"reportTimestamp","type":"uint256"}],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index b6351d5cd..a9f9a9cb3 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"reportTimestamp","type":"uint256"}],"name":"onPreRebase","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index b9247a007..cbc90d0fb 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -358,7 +358,7 @@ contract('AccountingOracle', ([admin, member1]) => { assert.equals(await mockStakingRouter.totalCalls_reportExitedKeysByNodeOperator(), 0) assert.equals(await mockStakingRouter.totalCalls_reportStuckKeysByNodeOperator(), 0) - const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__updateBunkerMode() + const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() assert.equals(updateBunkerModeLastCall.callCount, 0) }) diff --git a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js index b3a0b3cf6..3c4f6af95 100644 --- a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js +++ b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js @@ -227,7 +227,7 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { }) it(`withdrawal queue got bunker mode report`, async () => { - const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__updateBunkerMode() + const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() assert.equals(updateBunkerModeLastCall.callCount, 1) assert.equals(updateBunkerModeLastCall.isBunkerMode, reportFields.isBunkerMode) assert.equal( @@ -409,7 +409,7 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { }) it(`withdrawal queue got bunker mode report`, async () => { - const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__updateBunkerMode() + const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() assert.equals(updateBunkerModeLastCall.callCount, 2) }) diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js index f5ce518de..d0d137a88 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js @@ -483,10 +483,12 @@ contract('AccountingOracle', ([admin, member1]) => { it('should call updateBunkerMode on WithdrawalQueue', async () => { const prevProcessingRefSlot = +(await oracle.getLastProcessingRefSlot()) await oracle.submitReportData(reportItems, oracleVersion, { from: member1 }) - const lastCall = await mockWithdrawalQueue.lastCall__updateBunkerMode() + const currentProcessingRefSlot = +(await oracle.getLastProcessingRefSlot()) + const lastCall = await mockWithdrawalQueue.lastCall__onOracleReport() assert.equals(lastCall.callCount, 1) assert.equals(lastCall.isBunkerMode, reportFields.isBunkerMode) assert.equals(lastCall.prevReportTimestamp, GENESIS_TIME + prevProcessingRefSlot * SECONDS_PER_SLOT) + assert.equals(lastCall.currentReportTimestamp, GENESIS_TIME + currentProcessingRefSlot * SECONDS_PER_SLOT) }) }) From 4a4ac2e1c01ad1b08483a732389d003985f68c7a Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 14:52:35 +0200 Subject: [PATCH 101/236] test: fix a renamed role in tests --- test/0.8.9/withdrawal-queue-deploy.test.js | 8 +++----- test/0.8.9/withdrawal-queue.test.js | 6 +++--- test/helpers/factories.js | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 85d4edc5f..c27a81d1a 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -32,11 +32,9 @@ async function deployWithdrawalQueue({ }) await withdrawalQueue.grantRole(await withdrawalQueue.PAUSE_ROLE(), queuePauser || queueAdmin, { from: queueAdmin }) await withdrawalQueue.grantRole(await withdrawalQueue.RESUME_ROLE(), queueResumer || queueAdmin, { from: queueAdmin }) - await withdrawalQueue.grantRole( - await withdrawalQueue.BUNKER_MODE_REPORT_ROLE(), - queueBunkerReporter || steth.address, - { from: queueAdmin } - ) + await withdrawalQueue.grantRole(await withdrawalQueue.ORACLE_ROLE(), queueBunkerReporter || steth.address, { + from: queueAdmin, + }) if (doResume) { await withdrawalQueue.resume({ from: queueResumer || queueAdmin }) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 602201fbf..1662498fa 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -95,12 +95,12 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('access control', async () => { assert(!(await withdrawalQueue.isBunkerModeActive())) - const BUNKER_MODE_REPORT_ROLE = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() - await withdrawalQueue.grantRole(BUNKER_MODE_REPORT_ROLE, bunkerReporter, { from: daoAgent }) + const ORACLE_ROLE = await withdrawalQueue.ORACLE_ROLE() + await withdrawalQueue.grantRole(ORACLE_ROLE, bunkerReporter, { from: daoAgent }) await assert.revertsOZAccessControl( withdrawalQueue.updateBunkerMode(true, 0, { from: stranger }), stranger, - 'BUNKER_MODE_REPORT_ROLE' + 'ORACLE_ROLE' ) await withdrawalQueue.updateBunkerMode(true, 0, { from: bunkerReporter }) }) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 4a277e0d3..8af9e8676 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -262,14 +262,14 @@ async function withdrawalQueueFactory({ appManager, oracle, pool }) { await withdrawalQueue.initialize(appManager.address) - const BUNKER_MODE_REPORT_ROLE = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() - await withdrawalQueue.grantRole(BUNKER_MODE_REPORT_ROLE, oracle.address, { from: appManager.address }) + const ORACLE_ROLE = await withdrawalQueue.ORACLE_ROLE() + await withdrawalQueue.grantRole(ORACLE_ROLE, oracle.address, { from: appManager.address }) await grantRoles({ by: appManager.address, on: withdrawalQueue, to: appManager.address, - roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'BUNKER_MODE_REPORT_ROLE'], + roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'ORACLE_ROLE'], }) return withdrawalQueue From b52ca3a3d747444724cc6939dc87ccb7097e10ae Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 15:18:17 +0200 Subject: [PATCH 102/236] test: other realated fixes --- .../oracle/accounting-oracle-deploy.test.js | 4 ++-- .../oracle/accounting-oracle-happy-path.test.js | 17 +++++++---------- ...accounting-oracle-submit-report-data.test.js | 2 +- test/0.8.9/withdrawal-queue.test.js | 14 +++++++------- test/helpers/factories.js | 1 - test/scenario/deposit.test.js | 1 - 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index cbc90d0fb..a00d66fcb 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -358,8 +358,8 @@ contract('AccountingOracle', ([admin, member1]) => { assert.equals(await mockStakingRouter.totalCalls_reportExitedKeysByNodeOperator(), 0) assert.equals(await mockStakingRouter.totalCalls_reportStuckKeysByNodeOperator(), 0) - const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() - assert.equals(updateBunkerModeLastCall.callCount, 0) + const onOracleReportLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() + assert.equals(onOracleReportLastCall.callCount, 0) }) it('the initial reference slot is greater than the last one of the legacy oracle', async () => { diff --git a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js index 3c4f6af95..a6633f917 100644 --- a/test/0.8.9/oracle/accounting-oracle-happy-path.test.js +++ b/test/0.8.9/oracle/accounting-oracle-happy-path.test.js @@ -227,13 +227,10 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { }) it(`withdrawal queue got bunker mode report`, async () => { - const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() - assert.equals(updateBunkerModeLastCall.callCount, 1) - assert.equals(updateBunkerModeLastCall.isBunkerMode, reportFields.isBunkerMode) - assert.equal( - +updateBunkerModeLastCall.prevReportTimestamp, - GENESIS_TIME + prevProcessingRefSlot * SECONDS_PER_SLOT - ) + const onOracleReportLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() + assert.equals(onOracleReportLastCall.callCount, 1) + assert.equals(onOracleReportLastCall.isBunkerMode, reportFields.isBunkerMode) + assert.equal(+onOracleReportLastCall.prevReportTimestamp, GENESIS_TIME + prevProcessingRefSlot * SECONDS_PER_SLOT) }) it(`Staking router got the exited keys report`, async () => { @@ -408,9 +405,9 @@ contract('AccountingOracle', ([admin, member1, member2, member3, stranger]) => { assert.equal(lastOracleReportCall.callCount, 2) }) - it(`withdrawal queue got bunker mode report`, async () => { - const updateBunkerModeLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() - assert.equals(updateBunkerModeLastCall.callCount, 2) + it(`withdrawal queue got their part of report`, async () => { + const onOracleReportLastCall = await mockWithdrawalQueue.lastCall__onOracleReport() + assert.equals(onOracleReportLastCall.callCount, 2) }) it(`Staking router got the exited keys report`, async () => { diff --git a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js index d0d137a88..a17e1022a 100644 --- a/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js +++ b/test/0.8.9/oracle/accounting-oracle-submit-report-data.test.js @@ -480,7 +480,7 @@ contract('AccountingOracle', ([admin, member1]) => { assert.equals(lastCall.clValidators, reportFields.numValidators) }) - it('should call updateBunkerMode on WithdrawalQueue', async () => { + it('should call onOracleReport on WithdrawalQueue', async () => { const prevProcessingRefSlot = +(await oracle.getLastProcessingRefSlot()) await oracle.submitReportData(reportItems, oracleVersion, { from: member1 }) const currentProcessingRefSlot = +(await oracle.getLastProcessingRefSlot()) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 1662498fa..bfd534107 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -9,7 +9,7 @@ const { impersonate, EvmSnapshot, getCurrentBlockTimestamp, setBalance } = requi const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') -contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, bunkerReporter]) => { +contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, oracle]) => { let withdrawalQueue, steth const snapshot = new EvmSnapshot(ethers.provider) @@ -96,13 +96,13 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('access control', async () => { assert(!(await withdrawalQueue.isBunkerModeActive())) const ORACLE_ROLE = await withdrawalQueue.ORACLE_ROLE() - await withdrawalQueue.grantRole(ORACLE_ROLE, bunkerReporter, { from: daoAgent }) + await withdrawalQueue.grantRole(ORACLE_ROLE, oracle, { from: daoAgent }) await assert.revertsOZAccessControl( - withdrawalQueue.updateBunkerMode(true, 0, { from: stranger }), + withdrawalQueue.onOracleReport(true, 0, 0, { from: stranger }), stranger, 'ORACLE_ROLE' ) - await withdrawalQueue.updateBunkerMode(true, 0, { from: bunkerReporter }) + await withdrawalQueue.onOracleReport(true, 0, 0, { from: oracle }) }) it('state and events', async () => { @@ -110,18 +110,18 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.equals(ethers.constants.MaxUint256, await withdrawalQueue.bunkerModeSinceTimestamp()) let timestamp = await getCurrentBlockTimestamp() await assert.reverts( - withdrawalQueue.updateBunkerMode(true, +timestamp + 1000000, { from: steth.address }), + withdrawalQueue.onOracleReport(true, +timestamp + 1000000, +timestamp + 1100000, { from: steth.address }), 'InvalidReportTimestamp()' ) // enable timestamp = await getCurrentBlockTimestamp() - const tx1 = await withdrawalQueue.updateBunkerMode(true, timestamp, { from: steth.address }) + const tx1 = await withdrawalQueue.onOracleReport(true, timestamp, timestamp, { from: steth.address }) assert.emits(tx1, 'BunkerModeEnabled', { _sinceTimestamp: timestamp }) assert(await withdrawalQueue.isBunkerModeActive()) assert.equals(timestamp, await withdrawalQueue.bunkerModeSinceTimestamp()) // disable timestamp = await getCurrentBlockTimestamp() - const tx2 = await withdrawalQueue.updateBunkerMode(false, timestamp, { from: steth.address }) + const tx2 = await withdrawalQueue.onOracleReport(false, timestamp, timestamp, { from: steth.address }) assert.emits(tx2, 'BunkerModeDisabled') assert(!(await withdrawalQueue.isBunkerModeActive())) assert.equals(ethers.constants.MaxUint256, await withdrawalQueue.bunkerModeSinceTimestamp()) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 8af9e8676..4abaa0fa8 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -359,7 +359,6 @@ async function postSetup({ await depositContract.reset() await depositContract.set_deposit_root(deployParams.depositRoot) - await withdrawalQueue.updateBunkerMode(false, 0, { from: appManager.address }) await pool.resumeProtocolAndStaking({ from: voting.address }) } diff --git a/test/scenario/deposit.test.js b/test/scenario/deposit.test.js index eb4e6e702..56f4ae7f3 100644 --- a/test/scenario/deposit.test.js +++ b/test/scenario/deposit.test.js @@ -52,7 +52,6 @@ contract('Lido with official deposit contract', ([user1, user2, user3, nobody, d depositContractFactory, postSetup: async ({ pool, lidoLocator, eip712StETH, withdrawalQueue, appManager, voting }) => { await pool.initialize(lidoLocator.address, eip712StETH.address, { value: ETH(1) }) - await withdrawalQueue.updateBunkerMode(false, 0, { from: appManager.address }) await pool.resumeProtocolAndStaking({ from: voting.address }) }, }) From 4d089ed1dfe848c475a67d5eeae21f95b9df7f14 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 15:32:03 +0200 Subject: [PATCH 103/236] test: fix more tests --- test/0.8.9/withdrawal-queue-deploy.test.js | 4 ++-- test/0.8.9/withdrawal-queue-share-rate-changes.test.js | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index c27a81d1a..473555570 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -14,7 +14,7 @@ async function deployWithdrawalQueue({ queuePauser, queueResumer, queueFinalizer, - queueBunkerReporter, + queueOracle, queueName = 'Unsteth nft', symbol = 'UNSTETH', doResume = true, @@ -32,7 +32,7 @@ async function deployWithdrawalQueue({ }) await withdrawalQueue.grantRole(await withdrawalQueue.PAUSE_ROLE(), queuePauser || queueAdmin, { from: queueAdmin }) await withdrawalQueue.grantRole(await withdrawalQueue.RESUME_ROLE(), queueResumer || queueAdmin, { from: queueAdmin }) - await withdrawalQueue.grantRole(await withdrawalQueue.ORACLE_ROLE(), queueBunkerReporter || steth.address, { + await withdrawalQueue.grantRole(await withdrawalQueue.ORACLE_ROLE(), queueOracle || steth.address, { from: queueAdmin, }) diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index 2746c6c24..c49716ff7 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -7,7 +7,7 @@ const { EvmSnapshot } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') -contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { +contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user, oracle]) => { const evmSnapshot = new EvmSnapshot(ethers.provider) const snapshot = () => evmSnapshot.make() const rollback = () => evmSnapshot.rollback() @@ -18,7 +18,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { let rebaseCounter = 0 const setShareRate = async (rate) => { - await queue.onPreRebase(rebaseCounter++) + await queue.onOracleReport(false, rebaseCounter, ++rebaseCounter, { from: oracle }) await steth.setTotalPooledEther(TOTAL_SHARES.mul(toBN(rate))) } @@ -27,6 +27,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { stethOwner: owner, queueAdmin: daoAgent, queueFinalizer: finalizer, + queueOracle: oracle, }) steth = deployed.steth @@ -127,7 +128,6 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives rewards, changing share rate to 2.0`, async () => { - await queue.onPreRebase(e27(2)) await setShareRate(2) }) @@ -138,7 +138,6 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives slashing, changing share rate to 1.0`, async () => { - await queue.onPreRebase(e27(1)) await setShareRate(1) }) From 8eadc4d4932a56edc4a46d0403c0f35154827d42 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 15:41:05 +0200 Subject: [PATCH 104/236] test: fix withdrawal nft tests --- test/0.8.9/withdrawal-request-nft.test.js | 62 ++++++++++------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index e84a2ad8e..a9a9b87ec 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -10,9 +10,9 @@ const StETH = artifacts.require('StETHMock') const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock') contract('WithdrawalNFT', (addresses) => { - const [deployer, stEthHolder, wstEthHolder, nftHolderStETH, nftHolderWstETH, recipient, stranger] = addresses - let withdrawalQueueERC721, stETH, wstETH, erc721ReceiverMock - let nftHolderStETHTokenIds, nftHolderWstETHTokenIds, nonExistedTokenId + const [deployer, stEthHolder, nftHolderStETH, recipient, stranger] = addresses + let withdrawalQueueERC721, stETH, erc721ReceiverMock + let nftHolderStETHTokenIds, nonExistedTokenId const snapshot = new EvmSnapshot(ethers.provider) before(async () => { @@ -21,26 +21,18 @@ contract('WithdrawalNFT', (addresses) => { erc721ReceiverMock = await ERC721ReceiverMock.new({ from: deployer }) withdrawalQueueERC721 = (await withdrawals.deploy(deployer, stETH.address, 'Lido TEST Request', 'unstEsT')).queue - await withdrawalQueueERC721.initialize( - deployer, // owner - deployer, // pauser - deployer, // resumer - deployer, // finalizer - deployer - ) + await withdrawalQueueERC721.initialize(deployer) + await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.RESUME_ROLE(), deployer) + await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.FINALIZE_ROLE(), deployer) await withdrawalQueueERC721.resume({ from: deployer }) await stETH.setTotalPooledEther(ETH(101)) - await stETH.mintShares(stEthHolder, shares(50)) - await stETH.mintShares(wstETH.address, shares(50)) - await wstETH.mint(wstEthHolder, ETH(25)) + await stETH.mintShares(stEthHolder, shares(100)) await stETH.approve(withdrawalQueueERC721.address, ETH(50), { from: stEthHolder }) - await wstETH.approve(withdrawalQueueERC721.address, ETH(25), { from: wstEthHolder }) + await withdrawalQueueERC721.requestWithdrawals([ETH(25), ETH(25)], nftHolderStETH, { from: stEthHolder }) nftHolderStETHTokenIds = [1, 2] - await withdrawalQueueERC721.requestWithdrawalsWstETH([ETH(25)], nftHolderWstETH, { from: wstEthHolder }) - nftHolderWstETHTokenIds = [3] nonExistedTokenId = 4 await snapshot.make() }) @@ -84,7 +76,6 @@ contract('WithdrawalNFT', (addresses) => { it('return correct withdrawal requests count', async () => { assert.equals(await withdrawalQueueERC721.balanceOf(nftHolderStETH), 2) - assert.equals(await withdrawalQueueERC721.balanceOf(nftHolderWstETH), 1) }) it('reverts for zero address', async () => { @@ -104,7 +95,6 @@ contract('WithdrawalNFT', (addresses) => { it('reverts correct owner', async () => { assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), nftHolderStETH) assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[1]), nftHolderStETH) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), nftHolderWstETH) }) }) @@ -190,8 +180,8 @@ contract('WithdrawalNFT', (addresses) => { it('reverts with message "TransferToNonIERC721Receiver()" when transfer to contract that not implements IERC721Receiver interface', async () => { await assert.reverts( - withdrawalQueueERC721.safeTransferFrom(nftHolderWstETH, stETH.address, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, stETH.address, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }), `TransferToNonIERC721Receiver("${stETH.address}")` ) @@ -232,16 +222,16 @@ contract('WithdrawalNFT', (addresses) => { it('reverts when transfer to the same address', async () => { await assert.reverts( - withdrawalQueueERC721.transferFrom(nftHolderWstETH, nftHolderWstETH, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + withdrawalQueueERC721.transferFrom(nftHolderStETH, nftHolderStETH, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }), 'TransferToThemselves()' ) }) it('reverts with error "RequestAlreadyClaimed()" when called on claimed request', async () => { - const batch = await withdrawalQueueERC721.finalizationValue([3], shareRate(1)) - await withdrawalQueueERC721.finalize(3, shareRate(1), { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.prefinalize.call([2], shareRate(1)) + await withdrawalQueueERC721.finalize([2], shareRate(1), { from: deployer, value: batch.ethToLock }) const ownerETHBefore = await ethers.provider.getBalance(nftHolderStETH) const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { from: nftHolderStETH, @@ -259,11 +249,11 @@ contract('WithdrawalNFT', (addresses) => { }) it('transfers if called by owner', async () => { - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), recipient) - await withdrawalQueueERC721.transferFrom(nftHolderWstETH, recipient, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) + await withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), recipient) + assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) }) it('transfers if token approval set', async () => { @@ -295,8 +285,8 @@ contract('WithdrawalNFT', (addresses) => { }) assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - const batch = await withdrawalQueueERC721.finalizationValue([3], shareRate(1)) - await withdrawalQueueERC721.finalize(3, shareRate(1), { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.prefinalize.call([2], shareRate(1)) + await withdrawalQueueERC721.finalize([2], shareRate(1), { from: deployer, value: batch.ethToLock }) const recipientETHBefore = await ethers.provider.getBalance(recipient) const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { @@ -308,11 +298,11 @@ contract('WithdrawalNFT', (addresses) => { }) it("doesn't reverts when transfer to contract that not implements IERC721Receiver interface", async () => { - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), nftHolderWstETH) - await withdrawalQueueERC721.transferFrom(nftHolderWstETH, stETH.address, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), nftHolderStETH) + await withdrawalQueueERC721.transferFrom(nftHolderStETH, stETH.address, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), stETH.address) + assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), stETH.address) }) }) @@ -320,8 +310,8 @@ contract('WithdrawalNFT', (addresses) => { it('balanceOf decreases after claim', async () => { const balanceBefore = await withdrawalQueueERC721.balanceOf(nftHolderStETH) - const batch = await withdrawalQueueERC721.finalizationValue([3], shareRate(1)) - await withdrawalQueueERC721.finalize(3, shareRate(1), { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.prefinalize.call([2], shareRate(1)) + await withdrawalQueueERC721.finalize([2], shareRate(1), { from: deployer, value: batch.ethToLock }) await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { from: nftHolderStETH, From 056843e841b70f02d6c098dd6393a45dc39506bd Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 16:20:57 +0200 Subject: [PATCH 105/236] feat: use MemUtils for memory array trimming --- contracts/0.8.9/WithdrawalQueueBase.sol | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 502f3749c..d712a3fbd 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -8,6 +8,7 @@ import "@openzeppelin/contracts-v4.4/utils/structs/EnumerableSet.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; import {Math} from "./lib/Math.sol"; +import {MemUtils} from "../common/lib/MemUtils.sol"; /// @title Queue to store and manage WithdrawalRequests. /// @dev Use an optimizations to store discounts heavily inspired @@ -239,13 +240,7 @@ abstract contract WithdrawalQueueBase { _state.finished = requestId < maxPossibleRequestId || requestId == lastRequestId + 1; if (_state.finished) { - assert(_state.batches[MAX_EXTREMA_PER_CALL] <= MAX_EXTREMA_PER_CALL); - uint256[] memory batches = _state.batches; - uint256 length = _state.batches[MAX_EXTREMA_PER_CALL]; - // todo: use MemUtils - assembly { - mstore(batches, length) - } + MemUtils.trimUint256Array(_state.batches, _state.batches.length - _state.batches[MAX_EXTREMA_PER_CALL]); } return _state; From 99ec8c01f9cb2e67dccbbff52ec845a380540a72 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Thu, 2 Mar 2023 16:00:38 +0100 Subject: [PATCH 106/236] fix: penalty delay restart --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 0a7b9d08c..124c9817c 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -609,7 +609,8 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { */ function _updateStuckValidatorsCount(uint256 _nodeOperatorId, uint64 _stuckValidatorsCount) internal { Packed64x4.Packed memory stuckPenaltyStats = _loadOperatorStuckPenaltyStats(_nodeOperatorId); - if (_stuckValidatorsCount == stuckPenaltyStats.get(STUCK_VALIDATORS_COUNT_OFFSET)) return; + uint64 curStuckValidatorsCount = stuckPenaltyStats.get(REFUNDED_VALIDATORS_COUNT_OFFSET); + if (_stuckValidatorsCount == curStuckValidatorsCount) return; Packed64x4.Packed memory signingKeysStats = _loadOperatorSigningKeysStats(_nodeOperatorId); _requireValidRange( @@ -617,15 +618,17 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { <= signingKeysStats.get(DEPOSITED_KEYS_COUNT_OFFSET) - signingKeysStats.get(EXITED_KEYS_COUNT_OFFSET) ); - stuckPenaltyStats.set(STUCK_VALIDATORS_COUNT_OFFSET, _stuckValidatorsCount); - if (_stuckValidatorsCount <= stuckPenaltyStats.get(REFUNDED_VALIDATORS_COUNT_OFFSET)) { + uint64 curRefundedValidatorsCount = stuckPenaltyStats.get(STUCK_VALIDATORS_COUNT_OFFSET); + if (_stuckValidatorsCount<= curRefundedValidatorsCount && curStuckValidatorsCount > curRefundedValidatorsCount) { stuckPenaltyStats.set(STUCK_PENALTY_END_TIMESTAMP_OFFSET, uint64(block.timestamp + getStuckPenaltyDelay())); } + + stuckPenaltyStats.set(STUCK_VALIDATORS_COUNT_OFFSET, _stuckValidatorsCount); _saveOperatorStuckPenaltyStats(_nodeOperatorId, stuckPenaltyStats); emit StuckPenaltyStateChanged( _nodeOperatorId, _stuckValidatorsCount, - stuckPenaltyStats.get(REFUNDED_VALIDATORS_COUNT_OFFSET), + curRefundedValidatorsCount, stuckPenaltyStats.get(STUCK_PENALTY_END_TIMESTAMP_OFFSET) ); @@ -634,19 +637,22 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { function _updateRefundValidatorsKeysCount(uint256 _nodeOperatorId, uint64 _refundedValidatorsCount) internal { Packed64x4.Packed memory stuckPenaltyStats = _loadOperatorStuckPenaltyStats(_nodeOperatorId); - if (_refundedValidatorsCount == stuckPenaltyStats.get(REFUNDED_VALIDATORS_COUNT_OFFSET)) return; + uint64 curRefundedValidatorsCount = stuckPenaltyStats.get(REFUNDED_VALIDATORS_COUNT_OFFSET); + if (_refundedValidatorsCount == curRefundedValidatorsCount) return; Packed64x4.Packed memory signingKeysStats = _loadOperatorSigningKeysStats(_nodeOperatorId); _requireValidRange(_refundedValidatorsCount <= signingKeysStats.get(DEPOSITED_KEYS_COUNT_OFFSET)); - stuckPenaltyStats.set(REFUNDED_VALIDATORS_COUNT_OFFSET, _refundedValidatorsCount); - if (stuckPenaltyStats.get(STUCK_VALIDATORS_COUNT_OFFSET) <= _refundedValidatorsCount) { + uint64 curStuckValidatorsCount = stuckPenaltyStats.get(STUCK_VALIDATORS_COUNT_OFFSET); + if (_refundedValidatorsCount >= curStuckValidatorsCount && curRefundedValidatorsCount < curStuckValidatorsCount) { stuckPenaltyStats.set(STUCK_PENALTY_END_TIMESTAMP_OFFSET, uint64(block.timestamp + getStuckPenaltyDelay())); } + + stuckPenaltyStats.set(REFUNDED_VALIDATORS_COUNT_OFFSET, _refundedValidatorsCount); _saveOperatorStuckPenaltyStats(_nodeOperatorId, stuckPenaltyStats); emit StuckPenaltyStateChanged( _nodeOperatorId, - stuckPenaltyStats.get(STUCK_VALIDATORS_COUNT_OFFSET), + curStuckValidatorsCount, _refundedValidatorsCount, stuckPenaltyStats.get(STUCK_PENALTY_END_TIMESTAMP_OFFSET) ); From 213a62f10e307e0999323da3d5187937b0c3dc3d Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 2 Mar 2023 18:52:47 +0300 Subject: [PATCH 107/236] fix: wq request status iface for sanity checker --- .../OracleReportSanityChecker.sol | 37 ++++++++++------ .../OracleReportSanityCheckerMocks.sol | 43 ++++++++++++------- lib/abi/IWithdrawalQueue.json | 2 +- .../oracle-report-sanity-checker.test.js | 4 +- 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 297fa8402..0f3e37c55 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -13,17 +13,25 @@ import {ILidoLocator} from "../../common/interfaces/ILidoLocator.sol"; import {IBurner} from "../../common/interfaces/IBurner.sol"; interface IWithdrawalQueue { - function getWithdrawalRequestStatus(uint256 _requestId) + struct WithdrawalRequestStatus { + /// @notice stETH token amount that was locked on withdrawal queue for this request + uint256 amountOfStETH; + /// @notice amount of stETH shares locked on withdrawal queue for this request + uint256 amountOfShares; + /// @notice address that can claim or transfer this request + address owner; + /// @notice timestamp of when the request was created, in seconds + uint256 timestamp; + /// @notice true, if request is finalized + bool isFinalized; + /// @notice true, if request is claimed. Request is claimable if (isFinalized && !isClaimed) + bool isClaimed; + } + + function getWithdrawalStatus(uint256[] calldata _requestIds) external view - returns ( - uint256 amountOfStETH, - uint256 amountOfShares, - address recipient, - uint256 timestamp, - bool isFinalized, - bool isClaimed - ); + returns (WithdrawalRequestStatus[] memory statuses); } /// @notice The set of restrictions used in the sanity checks of the oracle report @@ -598,10 +606,13 @@ contract OracleReportSanityChecker is AccessControlEnumerable { uint256 _lastFinalizableId, uint256 _reportTimestamp ) internal view { - (, , , uint256 requestTimestampToFinalizeUpTo, , ) = IWithdrawalQueue(_withdrawalQueue) - .getWithdrawalRequestStatus(_lastFinalizableId); - if (_reportTimestamp < requestTimestampToFinalizeUpTo + _limitsList.requestTimestampMargin) - revert IncorrectRequestFinalization(requestTimestampToFinalizeUpTo); + uint256[] memory requestIds = new uint256[](1); + requestIds[0] = _lastFinalizableId; + + IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = IWithdrawalQueue(_withdrawalQueue) + .getWithdrawalStatus(requestIds); + if (_reportTimestamp < statuses[0].timestamp + _limitsList.requestTimestampMargin) + revert IncorrectRequestFinalization(statuses[0].timestamp); } function _checkSimulatedShareRate( diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index bf1def18d..e03cbd5ca 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -19,25 +19,36 @@ contract LidoStub { } contract WithdrawalQueueStub { - mapping(uint256 => uint256) private _blockNumbers; + struct WithdrawalRequestStatus { + /// @notice stETH token amount that was locked on withdrawal queue for this request + uint256 amountOfStETH; + /// @notice amount of stETH shares locked on withdrawal queue for this request + uint256 amountOfShares; + /// @notice address that can claim or transfer this request + address owner; + /// @notice timestamp of when the request was created, in seconds + uint256 timestamp; + /// @notice true, if request is finalized + bool isFinalized; + /// @notice true, if request is claimed. Request is claimable if (isFinalized && !isClaimed) + bool isClaimed; + } + + mapping(uint256 => uint256) private _timestamps; - function setRequestBlockNumber(uint256 _requestId, uint256 _blockNumber) external { - _blockNumbers[_requestId] = _blockNumber; + function setRequestTimestamp(uint256 _requestId, uint256 _timestamp) external { + _timestamps[_requestId] = _timestamp; } - function getWithdrawalRequestStatus(uint256 _requestId) - external - view - returns ( - uint256, - uint256, - address, - uint256 blockNumber, - bool, - bool - ) - { - blockNumber = _blockNumbers[_requestId]; + function getWithdrawalStatus( + uint256[] calldata _requestIds + ) external view returns ( + WithdrawalRequestStatus[] memory statuses + ) { + statuses = new WithdrawalRequestStatus[](_requestIds.length); + for (uint256 i; i < _requestIds.length; ++i) { + statuses[i].timestamp = _timestamps[_requestIds[i]]; + } } } diff --git a/lib/abi/IWithdrawalQueue.json b/lib/abi/IWithdrawalQueue.json index b70a929f2..4c65f3257 100644 --- a/lib/abi/IWithdrawalQueue.json +++ b/lib/abi/IWithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getWithdrawalRequestStatus","outputs":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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 IWithdrawalQueue.WithdrawalRequestStatus[]","name":"statuses","type":"tuple[]"}],"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 78436fa45..0d724094d 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -252,9 +252,9 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa correctWithdrawalQueueOracleReport.refReportTimestamp = currentBlockTimestamp oldRequestCreationTimestamp = currentBlockTimestamp - defaultLimitsList.requestTimestampMargin correctWithdrawalQueueOracleReport.lastFinalizableRequestId = oldRequestCreationTimestamp - await withdrawalQueueMock.setRequestBlockNumber(oldRequestId, oldRequestCreationTimestamp) + await withdrawalQueueMock.setRequestTimestamp(oldRequestId, oldRequestCreationTimestamp) newRequestCreationTimestamp = currentBlockTimestamp - Math.floor(defaultLimitsList.requestTimestampMargin / 2) - await withdrawalQueueMock.setRequestBlockNumber(newRequestId, newRequestCreationTimestamp) + await withdrawalQueueMock.setRequestTimestamp(newRequestId, newRequestCreationTimestamp) }) it('reverts with the error IncorrectRequestFinalization() when the creation timestamp of requestIdToFinalizeUpTo is too close to report timestamp', async () => { From 908cba534d9bb11015900def9cba81e1e30c8793 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 2 Mar 2023 19:20:03 +0300 Subject: [PATCH 108/236] fix: adopt new WQ for Lido --- contracts/0.4.24/Lido.sol | 13 +++++++------ contracts/0.8.9/WithdrawalQueueBase.sol | 6 +++--- .../OracleReportSanityCheckerMocks.sol | 17 +---------------- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 4b6b76dfe..916bf9c0d 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -104,7 +104,9 @@ interface IStakingRouter { function getTotalFeeE4Precision() external view returns (uint16 totalFee); - function getStakingFeeAggregateDistributionE4Precision() external view returns (uint16 modulesFee, uint16 treasuryFee); + function getStakingFeeAggregateDistributionE4Precision() external view returns ( + uint16 modulesFee, uint16 treasuryFee + ); function getStakingModuleMaxDepositsCount(uint256 _stakingModuleId, uint256 _depositableEther) external @@ -113,10 +115,9 @@ interface IStakingRouter { } interface IWithdrawalQueue { - function finalizationValue(uint256[] _batches, uint256 _maxShareRate) + function prefinalize(uint256[] _batches, uint256 _maxShareRate) external - view - returns (uint128 eth, uint128 shares); + returns (uint256 ethToLock, uint256 sharesToBurn); function finalize(uint256[] _batches, uint256 _maxShareRate) external payable; @@ -862,7 +863,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { function _calculateWithdrawals( OracleReportContracts memory _contracts, OracleReportedData memory _reportedData - ) internal view returns ( + ) internal returns ( uint256 etherToLock, uint256 sharesToBurn ) { IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(_contracts.withdrawalQueue); @@ -873,7 +874,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { _reportedData.reportTimestamp ); - (etherToLock, sharesToBurn) = withdrawalQueue.finalizationValue( + (etherToLock, sharesToBurn) = withdrawalQueue.prefinalize( _reportedData.withdrawalFinalizationBatches, _reportedData.simulatedShareRate ); diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index d712a3fbd..3f2f91d86 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -160,10 +160,10 @@ abstract contract WithdrawalQueueBase { // Right now finalization consists of several steps: // 1. Oracle daemon precalculates finalization batches' boundaries that is valid on oracle report refSlot // and post it with the report - `calculateFinalizationBatches()` - // 2. Lido contract invokes `onPreRebase()` handler to update ShareRate extremum list + // 2. AccountingOracle contract invokes `onOracleReport()` handler to update ShareRate extremum list // 3. Lido contract, during the report handling, calculates the value of finalization batchs in eth and shares - // and checks its correctness - `finalizationValue()` - // 4. Lido contract finalize the requests pasing the required ether along with `finalize()` method + // and checks its correctness - `prefinalize()` + // 4. Lido contract finalize the requests passing the required ether along with `finalize()` method struct CalcState { uint256 ethBudget; diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index e03cbd5ca..5556f3339 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -18,22 +18,7 @@ contract LidoStub { } } -contract WithdrawalQueueStub { - struct WithdrawalRequestStatus { - /// @notice stETH token amount that was locked on withdrawal queue for this request - uint256 amountOfStETH; - /// @notice amount of stETH shares locked on withdrawal queue for this request - uint256 amountOfShares; - /// @notice address that can claim or transfer this request - address owner; - /// @notice timestamp of when the request was created, in seconds - uint256 timestamp; - /// @notice true, if request is finalized - bool isFinalized; - /// @notice true, if request is claimed. Request is claimable if (isFinalized && !isClaimed) - bool isClaimed; - } - +contract WithdrawalQueueStub is IWithdrawalQueue { mapping(uint256 => uint256) private _timestamps; function setRequestTimestamp(uint256 _requestId, uint256 _timestamp) external { From 1a776e120cf1fd5d6f61e3694098eb9bdb98ba05 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 2 Mar 2023 19:30:57 +0300 Subject: [PATCH 109/236] chore: remove 'hre' prefix --- test/0.8.9/oracle-report-sanity-checker.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 e899e6c70..e78914ec8 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -1,14 +1,14 @@ -const { hre, contract, ethers } = require('hardhat') +const { artifacts, contract, ethers } = require('hardhat') const { ETH } = require('../helpers/utils') const { assert } = require('../helpers/assert') const { getCurrentBlockTimestamp } = require('../helpers/blockchain') const mocksFilePath = 'contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol' -const LidoStub = hre.artifacts.require(`${mocksFilePath}:LidoStub`) -const OracleReportSanityChecker = hre.artifacts.require('OracleReportSanityChecker') -const LidoLocatorStub = hre.artifacts.require(`${mocksFilePath}:LidoLocatorStub`) -const WithdrawalQueueStub = hre.artifacts.require(`${mocksFilePath}:WithdrawalQueueStub`) -const BurnerStub = hre.artifacts.require(`${mocksFilePath}:BurnerStub`) +const LidoStub = artifacts.require(`${mocksFilePath}:LidoStub`) +const OracleReportSanityChecker = artifacts.require('OracleReportSanityChecker') +const LidoLocatorStub = artifacts.require(`${mocksFilePath}:LidoLocatorStub`) +const WithdrawalQueueStub = artifacts.require(`${mocksFilePath}:WithdrawalQueueStub`) +const BurnerStub = artifacts.require(`${mocksFilePath}:BurnerStub`) function wei(number, units = 'wei') { switch (units.toLowerCase()) { From c80515683f9541f541b551b5db394bbe749e8fec Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Thu, 2 Mar 2023 19:24:14 +0200 Subject: [PATCH 110/236] wq: add an (unfinished) failing gas test --- .../0.8.9/test_helpers/StakingModuleMock.sol | 5 +- package.json | 1 + test/0.4.24/lido-handle-oracle-report.test.js | 757 ++---------------- test/helpers/factories.js | 31 +- test/helpers/oracle.js | 62 +- test/helpers/utils.js | 2 + ...ido-wq-acct-oracle-integration-gas.test.js | 166 ++++ test/scenario/lido_happy_path.test.js | 12 +- 8 files changed, 299 insertions(+), 737 deletions(-) create mode 100644 test/scenario/lido-wq-acct-oracle-integration-gas.test.js diff --git a/contracts/0.8.9/test_helpers/StakingModuleMock.sol b/contracts/0.8.9/test_helpers/StakingModuleMock.sol index 00d1227ad..205b6a4a1 100644 --- a/contracts/0.8.9/test_helpers/StakingModuleMock.sol +++ b/contracts/0.8.9/test_helpers/StakingModuleMock.sol @@ -115,7 +115,10 @@ contract StakingModuleMock is IStakingModule { bytes memory publicKeys, bytes memory signatures ) - {} + { + publicKeys = new bytes(48 * _depositsCount); + signatures = new bytes(96 * _depositsCount); + } function setTotalExitedValidatorsCount(uint256 newExitedValidatorsCount) external { _exitedValidatorsCount = newExitedValidatorsCount; diff --git a/package.json b/package.json index 976ea1485..b70bc98b8 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "test:e2e": "npm run compile && ava -T 1000000 -v", "estimate-deposit-loop-gas": "yarn run test:unit ./estimate_deposit_loop_gas.js", "compile": "hardhat compile && yarn extract-abi", + "clean": "hardhat clean", "extract-abi": "node ./scripts/extract-abi.js", "size-contracts": "yarn run hardhat size-contracts", "deploy": "yarn run deploy:all", 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 df5679741..ca89fbc6e 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1,17 +1,7 @@ const { artifacts, contract, ethers } = require('hardhat') const { assert } = require('../helpers/assert') -const { - e9, - shareRate, - ETH, - toBN, - genKeys, - StETH, - calcSharesMintedAsFees, - calcShareRateDeltaE27, - limitRebase, -} = require('../helpers/utils') +const { ETH, toBN, genKeys, StETH, calcSharesMintedAsFees } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') const { EvmSnapshot, setBalance } = require('../helpers/blockchain') const { ZERO_ADDRESS, INITIAL_HOLDER } = require('../helpers/constants') @@ -33,18 +23,6 @@ const ORACLE_REPORT_LIMITS_BOILERPLATE = { maxPositiveTokenRebase: 1000000000, } -const DEFAULT_LIDO_ORACLE_REPORT = { - reportTimestamp: 0, // uint256, seconds - timeElapsed: 0, // uint256, seconds - clValidators: 0, // uint256, counter - postCLBalance: ETH(0), // uint256, wei - withdrawalVaultBalance: ETH(0), // uint256, wei - elRewardsVaultBalance: ETH(0), // uint256, wei - sharesRequestedToBurn: StETH(0), // uint256, wad - withdrawalFinalizationBatches: [], // uint256[], indexes - simulatedShareRate: shareRate(0), // uint256, 10e27 -} - const checkEvents = async ({ tx, reportTimestamp = 0, @@ -107,8 +85,8 @@ const checkEvents = async ({ ) } -contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anotherStranger, depositor, operator]) => { - let deployed, snapshot, lido, treasury, voting, oracle, burner +contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, anotherStranger, depositor, operator]) => { + let deployed, snapshot, lido, treasury, voting, oracle let curatedModule, oracleReportSanityChecker, elRewardsVault let withdrawalVault let strangerBalanceBefore, @@ -147,7 +125,6 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot await curatedModule.setNodeOperatorStakingLimit(0, keysAmount, { from: deployed.voting.address }) lido = deployed.pool - burner = deployed.burner treasury = deployed.treasury.address voting = deployed.voting.address oracle = deployed.oracle.address @@ -235,22 +212,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot } it('handleOracleReport access control', async () => { - await assert.reverts( - lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: stranger }), - 'APP_AUTH_FAILED' - ) + await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'APP_AUTH_FAILED') }) - it('handleOracleReport reverts when protocol is stopped', async () => { + it('handleOracleReport reverts whe protocol stopped', async () => { await lido.stop({ from: deployed.voting.address }) - await assert.reverts( - lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: stranger }), - 'CONTRACT_IS_STOPPED' - ) + 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 () => { - const tx = await lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: oracle }) + const tx = await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -279,9 +250,9 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }) }) - describe('clBalance', async () => { + describe('clBalance', () => { beforeEach(async () => { - await lido.deposit(3, 1, '0x', { from: depositor }) + await await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -294,10 +265,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }) it('first report after deposit without rewards', async () => { - const tx = await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 1, postCLBalance: ETH(32) }), - { from: oracle } - ) + const tx = await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -327,15 +295,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }) it('first report after deposit with rewards', async () => { - const tx = await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 1, - postCLBalance: ETH(33), - }), - { from: oracle } - ) + const tx = await lido.handleOracleReport(0, ONE_YEAR, 1, ETH(33), 0, 0, 0, 0, { from: oracle }) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) await checkEvents({ tx, @@ -351,7 +311,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot preTotalEther: ETH(100), postTotalShares: toBN(ETH(100)).add(sharesMintedAsFees).toString(), postTotalEther: ETH(101), - sharesMintedAsFees: sharesMintedAsFees.toString(), + sharesMintedAsFees, }) await checkStat({ depositedValidators: 3, beaconValidators: 1, beaconBalance: ETH(33) }) @@ -369,60 +329,38 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot describe('sanity checks', async () => { beforeEach(async () => { - await lido.deposit(3, 1, '0x', { from: depositor }) + await await lido.deposit(3, 1, '0x', { from: depositor }) }) it('reverts on reported more than deposited', async () => { - await assert.reverts( - lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 4 }), { from: oracle }), - '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.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), - { from: oracle } - ) + 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.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 2 }), { from: oracle }), + 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.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, withdrawalVaultBalance: 1 }), { - from: oracle, - }), + lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, { from: oracle }), 'IncorrectWithdrawalsVaultBalance(0)' ) }) - it('execution layer rewards vault balance check', async () => { - await assert.reverts( - lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, elRewardsVaultBalance: 1 }), { - from: oracle, - }), - 'IncorrectELRewardsVaultBalance(0)' - ) - }) - - it('burner shares to burn check', async () => { + it('withdrawal vault balance check 2', async () => { await assert.reverts( - lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, sharesRequestedToBurn: 1 }), { - from: oracle, - }), - 'IncorrectSharesRequestedToBurn(0)' + 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 () => { - let tx = await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), - { from: oracle } - ) + let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -448,10 +386,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), - { from: oracle } - ) + tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 3, @@ -483,10 +418,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - let tx = await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), - { from: oracle } - ) + let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -512,10 +444,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(95.04) }), - { from: oracle } - ) + tx = await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, 0, { from: oracle }) await checkEvents({ tx, preCLValidators: 3, @@ -548,10 +477,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), - { from: oracle } - ) + 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, @@ -562,10 +488,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(95.03) }), - { from: oracle } - ), + lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, 0, { from: oracle }), 'IncorrectCLBalanceDecrease(101)' ) }) @@ -580,10 +503,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot { from: voting } ) - await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), - { from: oracle } - ) + 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, @@ -593,15 +513,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - const tx = await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96.96), - }), - { from: oracle } - ) + const tx = await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0, { from: oracle }) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.96), 10, 100, ETH(100), ETH(100.96)) await checkEvents({ tx, @@ -641,10 +553,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot { from: voting } ) - await lido.handleOracleReport( - ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), - { from: oracle } - ) + 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, @@ -655,15 +564,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96.97), - }), - { from: oracle } - ), + lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0, { from: oracle }), 'IncorrectCLBalanceIncrease(101)' ) }) @@ -680,15 +581,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 100, - postCLBalance: ETH(3200), - }), - { from: oracle, 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) }) }) @@ -704,15 +597,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot { from: voting, gasPrice: 1 } ) await assert.reverts( - lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 101, - postCLBalance: ETH(3200), - }), - { from: oracle, gasPrice: 1 } - ), + lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }), 'IncorrectAppearedValidators(101)' ) }) @@ -720,7 +605,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot describe('smooth report', async () => { beforeEach(async () => { - await lido.deposit(3, 1, '0x', { from: depositor }) + await await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -740,15 +625,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(97), - }), - { from: oracle, 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) }) }) @@ -760,15 +637,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(100), - }), - { from: oracle, 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) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(4), @@ -791,16 +660,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96), - withdrawalVaultBalance: ETH(1), - }), - { from: oracle, 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), @@ -824,16 +684,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96), - withdrawalVaultBalance: ETH(1.1), - }), - { from: oracle, 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), @@ -858,16 +709,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96), - elRewardsVaultBalance: ETH(1), - }), - { from: oracle, 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({ @@ -893,16 +735,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(95.5), - elRewardsVaultBalance: ETH(1.5), - }), - { from: oracle, 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), @@ -927,16 +760,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96), - elRewardsVaultBalance: ETH(1.1), - }), - { from: oracle, 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), @@ -960,16 +784,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96.1), - elRewardsVaultBalance: ETH(0.9), - }), - { from: oracle, 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({ @@ -995,16 +810,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96.1), - elRewardsVaultBalance: ETH(1.1), - }), - { from: oracle, 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), @@ -1017,308 +823,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.2)) }) - - it('does not smooth shares to burn if report in limit with shares', async () => { - await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) - - const sharesToBurn = await lido.sharesOf(bob) - await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) - await burner.requestBurnShares(bob, sharesToBurn, { from: voting }) - let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() - assert.equals(coverShares.add(nonCoverShares), sharesToBurn) - - await oracleReportSanityChecker.setOracleReportLimits( - { - ...ORACLE_REPORT_LIMITS_BOILERPLATE, - maxPositiveTokenRebase: 10000000, // 1% - }, - { from: voting, gasPrice: 1 } - ) - const tx = await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96), - sharesRequestedToBurn: sharesToBurn, - }), - { from: oracle, gasPrice: 1 } - ) - await checkEvents({ - tx, - preCLValidators: 0, - postCLValidators: 3, - preCLBalance: ETH(96), - postCLBalance: ETH(96), - withdrawalsWithdrawn: 0, - executionLayerRewardsWithdrawn: ETH(0), - postBufferedEther: ETH(5), - timeElapsed: ONE_YEAR, - preTotalShares: ETH(101), - preTotalEther: ETH(101), - postTotalShares: toBN(ETH(101)).sub(sharesToBurn).toString(), - postTotalEther: ETH(101), - sharesMintedAsFees: 0, - }) - - await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) - await checkBalanceDeltas({ - totalPooledEtherDiff: ETH(1), // bob's deposit - treasuryBalanceDiff: ETH(0), // no rewards reported - strangerBalanceDiff: ETH(0.3), // though, bob has sacrificed stETH shares for all users - anotherStrangerBalanceDiff: ETH(0.69), - curatedModuleBalanceDiff: ETH(0), // no rewards reported - initialHolderBalanceDiff: ETH(0.01), - }) - ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) - assert.equals(coverShares.add(nonCoverShares), StETH(0)) - assert.equals(await lido.balanceOf(burner.address), StETH(0)) - }) - - it('smooth shares to burn if report in limit without shares and no fees', async () => { - await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) - await setBalance(elRewardsVault, ETH(0.5)) - - const sharesRequestedToBurn = await lido.sharesOf(bob) - await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) - await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) - let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() - assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) - - await oracleReportSanityChecker.setOracleReportLimits( - { - ...ORACLE_REPORT_LIMITS_BOILERPLATE, - maxPositiveTokenRebase: 10000000, // 1% - }, - { from: voting, gasPrice: 1 } - ) - - const tx = await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96), - elRewardsVaultBalance: ETH(0.5), - sharesRequestedToBurn: sharesRequestedToBurn.toString(), - }), - { from: oracle, gasPrice: 1 } - ) - - const { elBalanceUpdate, sharesToBurn } = limitRebase( - toBN(10000000), - ETH(101), - ETH(101), - ETH(0), - ETH(0.5), - sharesRequestedToBurn - ) - - const postTotalShares = toBN(ETH(101)).sub(toBN(sharesToBurn)) - const postTotalEther = toBN(ETH(101)).add(toBN(elBalanceUpdate)) - - await checkEvents({ - tx, - preCLValidators: 0, - postCLValidators: 3, - preCLBalance: ETH(96), - postCLBalance: ETH(96), - withdrawalsWithdrawn: 0, - executionLayerRewardsWithdrawn: ETH(0.5), - postBufferedEther: ETH(5.5), - timeElapsed: ONE_YEAR, - preTotalShares: ETH(101), - preTotalEther: ETH(101), - postTotalShares: postTotalShares.toString(), - postTotalEther: postTotalEther.toString(), - sharesMintedAsFees: 0, // no rewards on CL side => no minted fee - }) - await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) - const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) - - await checkBalanceDeltas({ - totalPooledEtherDiff: ETH(1.5), - treasuryBalanceDiff: ETH(0), // no fee minted - strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), // though, bob has sacrificed stETH shares for all users - anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), - curatedModuleBalanceDiff: ETH(0), // no fee minted - initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), - }) - assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) - ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) - assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) - assert.equals( - await lido.balanceOf(burner.address), - await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) - ) - }) - - it('smooth shares to burn if report in limit without shares and fees', async () => { - await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) - await setBalance(elRewardsVault, ETH(0.4)) - - const sharesRequestedToBurn = await lido.sharesOf(bob) - await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) - await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) - let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() - assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) - - await oracleReportSanityChecker.setOracleReportLimits( - { - ...ORACLE_REPORT_LIMITS_BOILERPLATE, - maxPositiveTokenRebase: 10000000, // 1% - }, - { from: voting, gasPrice: 1 } - ) - - const tx = await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96.1), - elRewardsVaultBalance: ETH(0.4), - sharesRequestedToBurn: sharesRequestedToBurn.toString(), - }), - { from: oracle, gasPrice: 1 } - ) - - const { elBalanceUpdate, sharesToBurn } = limitRebase( - toBN(10000000), - ETH(101), - ETH(101), - ETH(0.1), - ETH(0.4), - sharesRequestedToBurn - ) - - const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) - const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.5), 10, 100, ETH(101), postTotalEther) - const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) - - await checkEvents({ - tx, - preCLValidators: 0, - postCLValidators: 3, - preCLBalance: ETH(96), - postCLBalance: ETH(96.1), - withdrawalsWithdrawn: 0, - executionLayerRewardsWithdrawn: ETH(0.4), - postBufferedEther: ETH(5.4), - timeElapsed: ONE_YEAR, - preTotalShares: ETH(101), - preTotalEther: ETH(101), - postTotalShares: postTotalShares.toString(), - postTotalEther: postTotalEther.toString(), - sharesMintedAsFees: sharesMintedAsFees.toString(), // no rewards on CL side => no minted fee - }) - await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) - const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) - - await checkBalanceDeltas({ - totalPooledEtherDiff: ETH(1.5), - treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), - strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), - anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), - curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), - initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), - }) - assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) - ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) - assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) - assert.equals( - await lido.balanceOf(burner.address), - await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) - ) - }) - - it('postpone all shares to burn if report out of limit even without shares', async () => { - await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) - await setBalance(elRewardsVault, ETH(4.9)) - - const sharesRequestedToBurn = await lido.sharesOf(bob) - await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) - await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) - let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() - assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) - - await oracleReportSanityChecker.setOracleReportLimits( - { - ...ORACLE_REPORT_LIMITS_BOILERPLATE, - maxPositiveTokenRebase: 10000000, // 1% - }, - { from: voting, gasPrice: 1 } - ) - - const tx = await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_YEAR, - clValidators: 3, - postCLBalance: ETH(96.1), - elRewardsVaultBalance: ETH(4.9), - sharesRequestedToBurn: sharesRequestedToBurn.toString(), - }), - { from: oracle, gasPrice: 1 } - ) - - const { elBalanceUpdate, sharesToBurn } = limitRebase( - toBN(10000000), - ETH(101), - ETH(101), - ETH(0.1), - ETH(4.9), - sharesRequestedToBurn - ) - - const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) - const sharesMintedAsFees = calcSharesMintedAsFees( - toBN(ETH(0.1)).add(elBalanceUpdate), - 10, - 100, - ETH(101), - postTotalEther - ) - const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) - - await checkEvents({ - tx, - preCLValidators: 0, - postCLValidators: 3, - preCLBalance: ETH(96), - postCLBalance: ETH(96.1), - withdrawalsWithdrawn: 0, - executionLayerRewardsWithdrawn: elBalanceUpdate.toString(), - postBufferedEther: toBN(ETH(5)).add(elBalanceUpdate).toString(), - timeElapsed: ONE_YEAR, - preTotalShares: ETH(101), - preTotalEther: ETH(101), - postTotalShares: postTotalShares.toString(), - postTotalEther: postTotalEther.toString(), - sharesMintedAsFees: sharesMintedAsFees.toString(), - }) - await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) - const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) - - await checkBalanceDeltas({ - totalPooledEtherDiff: toBN(ETH(1.1)).add(elBalanceUpdate), - treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), - strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), - anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), - curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), - initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), - }) - assert.equals(await ethers.provider.getBalance(elRewardsVault), toBN(ETH(4.9)).sub(elBalanceUpdate)) - ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) - assert.equals(sharesToBurn, 0) - assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) - assert.equals(await lido.balanceOf(burner.address), await lido.getPooledEthByShares(sharesRequestedToBurn)) - }) }) - - describe('daily reports', async () => { + describe('daily reports', () => { beforeEach(async () => { - await lido.deposit(3, 1, '0x', { from: depositor }) + await await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -1340,16 +848,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96.1), - elRewardsVaultBalance: ETH(1.1), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -1370,15 +869,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96.0027), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.0027), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.0027) }) }) @@ -1391,15 +882,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96.0028), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96 + 0.0028), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96 + clIncrease) }) assert( 0.00014 + 0.0028 * 0.9 * 0.3 + 0.0028 * 0.9 * 0.69 + 0.0028 * 0.01 * 0.9 + 0.00014 === clIncrease, @@ -1426,16 +909,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96), - withdrawalVaultBalance: ETH(1), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -1459,16 +933,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96), - withdrawalVaultBalance: ETH(1.1), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -1493,16 +958,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96), - elRewardsVaultBalance: ETH(1), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1), 0, 0, { from: oracle, gasPrice: 1 }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -1528,16 +984,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(95.5), - elRewardsVaultBalance: ETH(1.5), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -1562,16 +1009,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96), - elRewardsVaultBalance: ETH(1.1), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 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), @@ -1595,16 +1033,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96.1), - elRewardsVaultBalance: ETH(0.9), - }), - { from: oracle, gasPrice: 1 } - ) + await lido.handleOracleReport(0, ONE_DAY, 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({ @@ -1618,85 +1047,5 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.1)) }) - - it.skip('does not smooth shares to burn if report in limit with shares', async () => { - // TODO - }) - - it.skip('smooth shares to burn if report in limit without shares', async () => { - // TODO - }) - - it.skip('postpone all shares to burn if report out of limit without shares', async () => { - // TODO - }) - }) - - describe('reports with withdrawals finalization', () => { - beforeEach(async () => { - 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, - initialHolderBalanceDiff: 0, - }) - }) - - it('dry-run eth_call works and returns proper values', async () => { - await setBalance(elRewardsVault, ETH(0.5)) - await setBalance(withdrawalVault, ETH(0.5)) - - await oracleReportSanityChecker.setOracleReportLimits( - { - ...ORACLE_REPORT_LIMITS_BOILERPLATE, - churnValidatorsPerDayLimit: 100, - maxPositiveTokenRebase: 10000000, - }, - { from: voting, gasPrice: 1 } - ) - - const [postTotalPooledEther, postTotalShares, withdrawals, elRewards] = await lido.handleOracleReport.call( - ...Object.values({ - ...DEFAULT_LIDO_ORACLE_REPORT, - timeElapsed: ONE_DAY, - clValidators: 3, - postCLBalance: ETH(96.1), - elRewardsVaultBalance: ETH(0.5), - withdrawalVaultBalance: ETH(0.5), - }), - { from: oracle, gasPrice: 1 } - ) - - await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: ETH(0) }) - await checkBalanceDeltas({ - totalPooledEtherDiff: ETH(0), - treasuryBalanceDiff: ETH(0), - strangerBalanceDiff: ETH(0), - anotherStrangerBalanceDiff: ETH(0), - curatedModuleBalanceDiff: ETH(0), - initialHolderBalanceDiff: ETH(0), - }) - assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.5)) - assert.equals(await ethers.provider.getBalance(withdrawalVault), ETH(0.5)) - - const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) - - assert.equals(postTotalPooledEther, ETH(101)) - assert.equals(postTotalShares, toBN(ETH(100)).add(sharesMintedAsFees)) - assert.equals(withdrawals, ETH(0.5)) - assert.equals(elRewards, ETH(0.4)) - }) - - it.skip('withdrawal finalization works after dry-run call', async () => { - // TODO - }) - - it.skip('check simulated share rate correctness when limit is higher due to withdrawals', async () => { - // TODO - }) }) }) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 4abaa0fa8..59379b869 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -132,12 +132,6 @@ async function hashConsensusFactory({ voting, oracle, signers, legacyOracle, dep await consensus.addMember(signers[3].address, 2, { from: voting.address }) await consensus.addMember(signers[4].address, 2, { from: voting.address }) - await oracle.initialize(voting.address, consensus.address, CONSENSUS_VERSION) - - await oracle.grantRole(await oracle.MANAGE_CONSENSUS_CONTRACT_ROLE(), voting.address, { from: voting.address }) - await oracle.grantRole(await oracle.MANAGE_CONSENSUS_VERSION_ROLE(), voting.address, { from: voting.address }) - await oracle.grantRole(await oracle.SUBMIT_DATA_ROLE(), voting.address, { from: voting.address }) - return consensus } @@ -169,6 +163,7 @@ async function hashConsensusTimeTravellableFactory({ await consensus.addMember(signers[2].address, 1, { from: voting.address }) await consensus.addMember(signers[3].address, 2, { from: voting.address }) await consensus.addMember(signers[4].address, 2, { from: voting.address }) + await consensus.setTime(deployParams.genesisTime + initialEpoch * SLOTS_PER_EPOCH * SECONDS_PER_SLOT) return consensus @@ -322,7 +317,23 @@ async function oracleReportSanityCheckerFactory({ lidoLocator, voting, appManage deployParams.oracleReportSanityChecker.managersRoster ) - await checker.grantRole(await checker.ALL_LIMITS_MANAGER_ROLE(), voting.address, { from: appManager.address }) + await grantRoles({ + by: appManager.address, + on: checker, + to: voting.address, + roles: [ + 'ALL_LIMITS_MANAGER_ROLE', + 'CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE', + 'ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE', + 'ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE', + 'SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE', + 'MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE', + 'MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE', + 'MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_COUNT_ROLE', + 'REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE', + 'MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE', + ] + }) return checker } @@ -350,11 +361,17 @@ async function postSetup({ appManager, voting, deployParams, + oracle, legacyOracle, consensusContract, }) { await pool.initialize(lidoLocator.address, eip712StETH.address, { value: ETH(1) }) + await oracle.initialize(voting.address, consensusContract.address, CONSENSUS_VERSION) + await oracle.grantRole(await oracle.MANAGE_CONSENSUS_CONTRACT_ROLE(), voting.address, { from: voting.address }) + await oracle.grantRole(await oracle.MANAGE_CONSENSUS_VERSION_ROLE(), voting.address, { from: voting.address }) + await oracle.grantRole(await oracle.SUBMIT_DATA_ROLE(), voting.address, { from: voting.address }) + await legacyOracle.initialize(lidoLocator.address, consensusContract.address) await depositContract.reset() diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index dbf434c87..2ca5a5dd0 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -2,24 +2,25 @@ const { web3 } = require('hardhat') const { CONSENSUS_VERSION, ZERO_BYTES32 } = require('./constants') const { assert } = require('./assert') +const { toBN } = require('./utils') function getReportDataItems(r) { return [ - r.consensusVersion, - +r.refSlot, - r.numValidators, - r.clBalanceGwei, - r.stakingModuleIdsWithNewlyExitedValidators, - r.numExitedValidatorsByStakingModule, - r.withdrawalVaultBalance, - r.elRewardsVaultBalance, - r.requestedToBurnShares, - r.withdrawalFinalizationBatches, - r.simulatedShareRate, + String(r.consensusVersion), + String(r.refSlot), + String(r.numValidators), + String(r.clBalanceGwei), + r.stakingModuleIdsWithNewlyExitedValidators.map(String), + r.numExitedValidatorsByStakingModule.map(String), + String(r.withdrawalVaultBalance), + String(r.elRewardsVaultBalance), + String(r.sharesRequestedToBurn), + r.withdrawalFinalizationBatches.map(String), + String(r.simulatedShareRate), r.isBunkerMode, - r.extraDataFormat, + String(r.extraDataFormat), r.extraDataHash, - r.extraDataItemsCount, + String(r.extraDataItemsCount), ] } @@ -30,7 +31,6 @@ function calcReportDataHash(reportItems) { ], [reportItems] ) - return web3.utils.keccak256(data) } @@ -42,18 +42,22 @@ async function triggerConsensusOnHash(hash, consensus) { assert.equal((await consensus.getConsensusState()).consensusReport, hash) } -async function pushOracleReport(consensus, oracle, numValidators, clBalance, elRewards) { +async function reportOracle(consensus, oracle, { + numValidators, + clBalance, + elRewards = 0 +}) { const { refSlot } = await consensus.getCurrentFrame() const reportFields = { consensusVersion: 1, refSlot, numValidators, - clBalanceGwei: clBalance / 1e9, + clBalanceGwei: toBN(clBalance).div(toBN(10).pow(toBN(9))), stakingModuleIdsWithNewlyExitedValidators: [], numExitedValidatorsByStakingModule: [], withdrawalVaultBalance: 0, - elRewardsVaultBalance: elRewards || 0, - requestedToBurnShares: 0, + elRewardsVaultBalance: elRewards, + sharesRequestedToBurn: 0, withdrawalFinalizationBatches: [], simulatedShareRate: 0, isBunkerMode: false, @@ -61,6 +65,7 @@ async function pushOracleReport(consensus, oracle, numValidators, clBalance, elR extraDataHash: ZERO_BYTES32, extraDataItemsCount: 0, } + const reportItems = getReportDataItems(reportFields) const reportHash = calcReportDataHash(reportItems) @@ -76,4 +81,23 @@ async function pushOracleReport(consensus, oracle, numValidators, clBalance, elR return { submitDataTx, submitExtraDataTx } } -module.exports = { getReportDataItems, calcReportDataHash, pushOracleReport } +function pushOracleReport(consensus, oracle, numValidators, clBalance, elRewards) { + return reportOracle(consensus, oracle, { numValidators, clBalance, elRewards }) +} + +// const computeSlotAt = (time, c) => Math.floor((time - (+c.genesisTime)) / (+c.secondsPerSlot)) +// const computeEpochAt = (time, c) => Math.floor(computeSlotAt(time, c) / (+c.slotsPerEpoch)) +// const computeEpochFirstSlot = (epoch, c) => epoch * (+c.slotsPerEpoch) +// const computeEpochFirstSlotAt = (time, c) => computeEpochFirstSlot(computeEpochAt(time, c), c) +// const computeTimestampAtEpoch = (epoch, c) => +c.genesisTime + epoch * ((+c.secondsPerSlot) * (+c.slotsPerEpoch)) +// const computeTimestampAtSlot = (slot, c) => +c.genesisTime + slot * +c.secondsPerSlot + +async function getSecondsPerFrame(consensus) { + const [chainConfig, frameConfig] = await Promise.all([ + consensus.getChainConfig(), + consensus.getFrameConfig() + ]) + return (+chainConfig.secondsPerSlot) * (+chainConfig.slotsPerEpoch) * (+frameConfig.epochsPerFrame) +} + +module.exports = { getReportDataItems, calcReportDataHash, reportOracle, pushOracleReport, getSecondsPerFrame } diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 1474a0ecd..5a903f1df 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -4,6 +4,7 @@ const chai = require('chai') const { BN } = require('bn.js') const { getEvents } = require('@aragon/contract-helpers-test') +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const ZERO_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000' const pad = (hex, bytesLength, fill = '0') => { @@ -161,6 +162,7 @@ function getFirstEventArgs(receipt, eventName, abi = undefined) { } module.exports = { + ZERO_ADDRESS, ZERO_HASH, pad, hexConcat, diff --git a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js new file mode 100644 index 000000000..2ddbe868a --- /dev/null +++ b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js @@ -0,0 +1,166 @@ +const { assert } = require('../helpers/assert') +const { MAX_UINT256 } = require('../helpers/constants') +const { ZERO_ADDRESS, toBN, e18, e27 } = require('../helpers/utils') +const { deployProtocol } = require('../helpers/protocol') +const { reportOracle, getSecondsPerFrame } = require('../helpers/oracle') +const { advanceChainTime } = require('../helpers/blockchain') + +const StakingModuleMock = artifacts.require('StakingModuleMock') + + +function piecewiseModN({values, pointsPerValue, x}) { + const iValue = Math.floor(x / pointsPerValue) + const leftValue = values[iValue % values.length] + const rightValue = values[(iValue + 1) % values.length] + return leftValue + (rightValue - leftValue) * (x % pointsPerValue) / pointsPerValue +} + + +contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, user, stranger]) => { + + const test = (numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema) => { + let lido, router, wQueue, oracle, consensus, voting, stakingModule, stakingModuleId + let secondsPerFrame + + before('deploy contracts', async () => { + const deployed = await deployProtocol({ + stakingModulesFactory: async (protocol) => { + stakingModule = await StakingModuleMock.new() + return [ + { + module: stakingModule, + name: 'module1', + targetShares: 10000, + moduleFee: 500, + treasuryFee: 500, + }, + ] + }, + depositSecurityModuleFactory: async () => { + return { address: depositor } + }, + }) + + lido = deployed.pool + router = deployed.stakingRouter + wQueue = deployed.withdrawalQueue + oracle = deployed.oracle + consensus = deployed.consensusContract + voting = deployed.voting.address + + secondsPerFrame = await getSecondsPerFrame(consensus) + stakingModuleId = +(await router.getStakingModuleIds())[0] + + const withdrawalCredentials = '0x'.padEnd(66, '1234') + await router.setWithdrawalCredentials(withdrawalCredentials, { from: voting }) + + await deployed.oracleReportSanityChecker.setAnnualBalanceIncreaseBPLimit(10000, { from: voting }) + + await wQueue.resume({ from: deployed.appManager.address }) + }) + + const advanceTimeToNextFrame = async () => { + await advanceChainTime(secondsPerFrame) + } + + const rebaseToShareRateBP = async (shareRateBP) => { + const stat = await lido.getBeaconStat() + const totalShares = await lido.getTotalShares() + const newTotalEth = toBN(shareRateBP).mul(toBN(totalShares)).divn(10000) + const ethDiff = newTotalEth.sub(toBN(await lido.getTotalPooledEther())) + const newCLBalance = toBN(stat.beaconBalance).add(ethDiff) + + await advanceTimeToNextFrame() + + const { submitDataTx } = await reportOracle(consensus, oracle, { + numValidators: stat.beaconValidators, + clBalance: newCLBalance, + }) + + return submitDataTx + } + + let userBalance + + it(`a user submits ETH to the protocol`, async () => { + const ethToSubmit = toBN(e18(320)).sub(await lido.getTotalPooledEther()) + await lido.submit(ZERO_ADDRESS, { from: user, value: ethToSubmit }) + + userBalance = await lido.balanceOf(user) + await lido.approve(wQueue.address, userBalance, { from: user }) + }) + + it(`ether gets deposited to the CL`, async () => { + await stakingModule.setAvailableKeysCount(10) + await lido.deposit(10, stakingModuleId, '0x0', { from: depositor }) + assert.equals(await lido.getBufferedEther(), 0) + + let stat = await lido.getBeaconStat() + assert.equals(stat.depositedValidators, 10) + + const clBalance = toBN(stat.depositedValidators).mul(toBN(e18(32))) + + await advanceTimeToNextFrame() + + await reportOracle(consensus, oracle, { + numValidators: stat.depositedValidators, + clBalance, + }) + + stat = await lido.getBeaconStat() + assert.equals(stat.beaconValidators, 10) + assert.equals(stat.beaconBalance, clBalance) + }) + + const totalRequests = numRebases * withdrawalRequestsPerRebase + const shareRatesBP = [10010, 10020] + + for (let i = 0; i < numRebases; ++i) { + const shareRateBP = Math.floor(piecewiseModN({ + values: shareRatesBP, + pointsPerValue: rebasesPerShareRateExtrema, + x: i + })) + + context(`rebase ${i}, share rate: ${shareRateBP / 10000}`, () => { + before(async () => { + await rebaseToShareRateBP(shareRateBP) + assert.equals(await lido.getPooledEthByShares(10000), shareRateBP) + }) + + it(`adding ${withdrawalRequestsPerRebase} requests`, async () => { + const requestSize = toBN(userBalance).divn(totalRequests) + const amounts = new Array(withdrawalRequestsPerRebase).fill(requestSize) + await wQueue.requestWithdrawals(amounts, user, { from: user }) + }) + }) + } + + const finalizationShareRateBP = Math.floor((shareRatesBP[0] + shareRatesBP[1]) / 2) + + context(`share rate: ${finalizationShareRateBP / 10000}`, () => { + it(`calculating batches`, async () => { + await rebaseToShareRateBP(finalizationShareRateBP) + const shareRate27 = e27(finalizationShareRateBP / 10000) + + let calcState = { ethBudget: MAX_UINT256, finished: false, batches: [] } + let i = 0 + + while (!calcState.finished) { + calcState = await wQueue.calculateFinalizationBatches(shareRate27, MAX_UINT256, calcState) + console.log(`calcState ${i}:`, calcState) + ++i + } + }) + }) + } + + context('handleOracleReport gas consumption', () => { + const testWithParams = (numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema) => { + const desc = `rebases: ${numRebases}, requests per rebase: ${withdrawalRequestsPerRebase}, ` + + `rebases per extrema: ${rebasesPerShareRateExtrema}` + context(desc, () => test(numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema)) + } + testWithParams(40, 1, 1) + }) +}) diff --git a/test/scenario/lido_happy_path.test.js b/test/scenario/lido_happy_path.test.js index 54a764802..11b28b9f0 100644 --- a/test/scenario/lido_happy_path.test.js +++ b/test/scenario/lido_happy_path.test.js @@ -89,13 +89,13 @@ contract('Lido: happy path', (addresses) => { // Total fee is 10% const totalFeePoints = 0.1 * 10000 - it('voting sets fee and its distribution', async () => { + it.skip('voting sets fee and its distribution', async () => { // Fee and distribution were set - // assert.equals(await pool.getFee({ from: nobody }), totalFeePoints, 'total fee') - // const distribution = await pool.getFeeDistribution({ from: nobody }) - // console.log('distribution', distribution) - // assert.equals(distribution.treasuryFeeBasisPoints, treasuryFeePoints, 'treasury fee') - // assert.equals(distribution.operatorsFeeBasisPoints, nodeOperatorsFeePoints, 'node operators fee') + assert.equals(await pool.getFee({ from: nobody }), totalFeePoints, 'total fee') + const distribution = await pool.getFeeDistribution({ from: nobody }) + console.log('distribution', distribution) + assert.equals(distribution.treasuryFeeBasisPoints, treasuryFeePoints, 'treasury fee') + assert.equals(distribution.operatorsFeeBasisPoints, nodeOperatorsFeePoints, 'node operators fee') }) it('voting sets withdrawal credentials', async () => { From b5fd971013012b5f9a2bd013cdfe1698f17e01cc Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Fri, 3 Mar 2023 04:27:48 +0400 Subject: [PATCH 111/236] Replace "magic variables" with constants --- contracts/0.8.9/StakingRouter.sol | 27 ++++++++++++++++++--------- lib/abi/StakingRouter.json | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 8b047c8c5..8a9767f6f 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -119,6 +119,8 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 public constant FEE_PRECISION_POINTS = 10 ** 20; // 100 * 10 ** 18 uint256 public constant TOTAL_BASIS_POINTS = 10000; + uint256 public constant MAX_STAKING_MODULES_COUNT = 32; + uint256 public constant MAX_STAKING_MODULE_NAME_LENGTH = 32; constructor(address _depositContract) BeaconChainDepositor(_depositContract) {} @@ -168,17 +170,23 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 _stakingModuleFee, uint256 _treasuryFee ) external onlyRole(STAKING_MODULE_MANAGE_ROLE) { - 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(); + 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 > MAX_STAKING_MODULE_NAME_LENGTH) + revert StakingModuleWrongName(); uint256 newStakingModuleIndex = getStakingModulesCount(); - if (newStakingModuleIndex >= 32) revert StakingModulesLimitExceeded(); + if (newStakingModuleIndex >= MAX_STAKING_MODULES_COUNT) + revert StakingModulesLimitExceeded(); for (uint256 i; i < newStakingModuleIndex; ) { - if (_stakingModuleAddress == _getStakingModuleByIndex(i).stakingModuleAddress) revert StakingModuleAddressExists(); + if (_stakingModuleAddress == _getStakingModuleByIndex(i).stakingModuleAddress) + revert StakingModuleAddressExists(); unchecked { ++i; } @@ -193,9 +201,10 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version newStakingModule.targetShare = uint16(_targetShare); newStakingModule.stakingModuleFee = uint16(_stakingModuleFee); newStakingModule.treasuryFee = uint16(_treasuryFee); - /// @dev since `enum` is `uint8` by nature, so the `status` is stored as `uint8` to avoid possible problems when upgrading. - /// But for human readability, we use `enum` as function parameter type. - /// More about conversion in the docs https://docs.soliditylang.org/en/v0.8.17/types.html#enums + /// @dev since `enum` is `uint8` by nature, so the `status` is stored as `uint8` to avoid + /// possible problems when upgrading. But for human readability, we use `enum` as + /// function parameter type. More about conversion in the docs + /// https://docs.soliditylang.org/en/v0.8.17/types.html#enums newStakingModule.status = uint8(StakingModuleStatus.Active); _setStakingModuleIndexById(newStakingModuleId, newStakingModuleIndex); diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index b8171d37f..4157002c5 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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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 9c3c3d7964e42496083d4f152ea0f90ef34bdc8d Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Fri, 3 Mar 2023 11:42:07 +0300 Subject: [PATCH 112/236] test: handleOracleReport daily shares burn cases --- test/0.4.24/lido-handle-oracle-report.test.js | 285 +++++++++++++++++- 1 file changed, 277 insertions(+), 8 deletions(-) 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 df5679741..338424d75 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1153,7 +1153,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot ) }) - it('smooth shares to burn if report in limit without shares and fees', async () => { + it('smooth shares to burn if report in limit without shares and some fees', async () => { await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) await setBalance(elRewardsVault, ETH(0.4)) @@ -1210,7 +1210,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot preTotalEther: ETH(101), postTotalShares: postTotalShares.toString(), postTotalEther: postTotalEther.toString(), - sharesMintedAsFees: sharesMintedAsFees.toString(), // no rewards on CL side => no minted fee + sharesMintedAsFees: sharesMintedAsFees.toString(), }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) @@ -1619,16 +1619,285 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.1)) }) - it.skip('does not smooth shares to burn if report in limit with shares', async () => { - // TODO + it('does not smooth shares to burn if report in limit with shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + + const sharesToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + sharesRequestedToBurn: sharesToBurn, + }), + { 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.69), + curatedModuleBalanceDiff: 0, + initialHolderBalanceDiff: ETH(0.01), + }) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(coverShares.add(nonCoverShares), StETH(0)) + assert.equals(await lido.balanceOf(burner.address), StETH(0)) }) - it.skip('smooth shares to burn if report in limit without shares', async () => { - // TODO + it('smooth shares to burn if report in limit without shares and no fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.5)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(0.5), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0), + ETH(0.5), + sharesRequestedToBurn + ) + + const postTotalShares = toBN(ETH(101)).sub(toBN(sharesToBurn)) + const postTotalEther = toBN(ETH(101)).add(toBN(elBalanceUpdate)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.5), + postBufferedEther: ETH(5.5), + timeElapsed: ONE_DAY, // NB: day-long + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: 0, // no rewards on CL side => no minted fee + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: ETH(0), // no fee minted + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), // though, bob has sacrificed stETH shares for all users + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: ETH(0), // no fee minted + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) }) - it.skip('postpone all shares to burn if report out of limit without shares', async () => { - // TODO + it('smooth shares to burn if report in limit without shares and some fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.4)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.4), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(0.4), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.5), 10, 100, ETH(101), postTotalEther) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.4), + postBufferedEther: ETH(5.4), + timeElapsed: ONE_DAY, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) + }) + + it('postpone all shares to burn if report out of limit without shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(4.9)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(4.9), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(4.9), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees( + toBN(ETH(0.1)).add(elBalanceUpdate), + 10, + 100, + ETH(101), + postTotalEther + ) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: elBalanceUpdate.toString(), + postBufferedEther: toBN(ETH(5)).add(elBalanceUpdate).toString(), + timeElapsed: ONE_DAY, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: toBN(ETH(1.1)).add(elBalanceUpdate), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), toBN(ETH(4.9)).sub(elBalanceUpdate)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesToBurn, 0) + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + assert.equals(await lido.balanceOf(burner.address), await lido.getPooledEthByShares(sharesRequestedToBurn)) }) }) From 1880868c5eba99e2631b328cba769e67779e7266 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 3 Mar 2023 18:18:41 +0700 Subject: [PATCH 113/236] feat: legacy oracle deploy test --- test/0.4.24/legacy-oracle-deploy.test.js | 102 +++++++++++++++++ .../oracle/accounting-oracle-deploy.test.js | 107 ++++++++++-------- 2 files changed, 162 insertions(+), 47 deletions(-) create mode 100644 test/0.4.24/legacy-oracle-deploy.test.js diff --git a/test/0.4.24/legacy-oracle-deploy.test.js b/test/0.4.24/legacy-oracle-deploy.test.js new file mode 100644 index 000000000..feb9fd664 --- /dev/null +++ b/test/0.4.24/legacy-oracle-deploy.test.js @@ -0,0 +1,102 @@ +const { contract, ethers } = require('hardhat') +const { assert } = require('../helpers/assert') +const { impersonate } = require('../helpers/blockchain') + +const { legacyOracleFactory } = require('../helpers/factories') + +const { + deployAccountingOracleSetup, + initAccountingOracle, + EPOCHS_PER_FRAME, + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, +} = require('../0.8.9/oracle/accounting-oracle-deploy.test') + +async function deployLegacyOracle({ admin, initialEpoch = 1, lastProcessingRefSlot = 31 }) { + const legacyOracle = await legacyOracleFactory({ appManager: { address: admin } }) + const { locatorAddr, consensus, oracle, lido } = await deployAccountingOracleSetup(admin, { + initialEpoch, + legacyOracleAddrArg: legacyOracle.address, + getLegacyOracle: () => { + return legacyOracle + }, + }) + await legacyOracle.initialize(locatorAddr, consensus.address) + await initAccountingOracle({ admin, oracle, consensus, shouldMigrateLegacyOracle: false, lastProcessingRefSlot }) + return { legacyOracle, consensus, accountingOracle: oracle, lido } +} + +module.exports = { + deployLegacyOracle, +} + +contract('LegacyOracle', ([admin, stranger]) => { + let legacyOracle, accountingOracle, lido, consensus + + context('Fresh deploy and puppet methods checks', () => { + before('deploy', async () => { + const deployed = await deployLegacyOracle({ admin }) + legacyOracle = deployed.legacyOracle + accountingOracle = deployed.accountingOracle + lido = deployed.lido + consensus = deployed.consensus + }) + + it('initial state is correct', async () => { + assert.equals(await legacyOracle.getVersion(), 4) + assert.equals(await legacyOracle.getAccountingOracle(), accountingOracle.address) + assert.equals(await legacyOracle.getLido(), lido.address) + const spec = await legacyOracle.getBeaconSpec() + assert.equals(spec.epochsPerFrame, EPOCHS_PER_FRAME) + assert.equals(spec.slotsPerEpoch, SLOTS_PER_EPOCH) + assert.equals(spec.secondsPerSlot, SECONDS_PER_SLOT) + assert.equals(spec.genesisTime, GENESIS_TIME) + const frame = await consensus.getCurrentFrame() + const epochId = frame.refSlot.addn(1).divn(SLOTS_PER_EPOCH) + assert.equals(await legacyOracle.getCurrentEpochId(), epochId) + assert.equals(await legacyOracle.getLastCompletedEpochId(), 0) + }) + + it('handlePostTokenRebase performs AC, emits event and changes state', async () => { + await impersonate(ethers.provider, lido.address) + await assert.reverts( + legacyOracle.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7, { from: stranger }), + 'SENDER_NOT_ALLOWED' + ) + const tx = await legacyOracle.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7, { from: lido.address }) + assert.emits(tx, 'PostTotalShares', { + postTotalPooledEther: 6, + preTotalPooledEther: 4, + timeElapsed: 2, + totalShares: 5, + }) + const delta = await legacyOracle.getLastCompletedReportDelta() + assert.equals(delta.postTotalPooledEther, 6) + assert.equals(delta.preTotalPooledEther, 4) + assert.equals(delta.timeElapsed, 2) + }) + + it('handleConsensusLayerReport performs AC, emits event and changes state', async () => { + const refSlot = 3000 + await impersonate(ethers.provider, accountingOracle.address) + await assert.reverts( + legacyOracle.handleConsensusLayerReport(refSlot, 2, 3, { from: stranger }), + 'SENDER_NOT_ALLOWED' + ) + const tx = await legacyOracle.handleConsensusLayerReport(refSlot, 2, 3, { from: accountingOracle.address }) + const epochId = Math.floor((refSlot + 1) / SLOTS_PER_EPOCH) + assert.emits(tx, 'Completed', { + epochId, + beaconBalance: 2, + beaconValidators: 3, + }) + const completedEpoch = await legacyOracle.getLastCompletedEpochId() + assert.equals(completedEpoch, epochId) + }) + }) + + context('Migration from old contract', () => { + it.skip('deploy') + }) +}) diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index e3f976788..36590830e 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -119,45 +119,6 @@ async function deployOracleReportSanityCheckerForAccounting(lidoLocator, admin) return oracleReportSanityChecker } -module.exports = { - SLOTS_PER_EPOCH, - SECONDS_PER_SLOT, - GENESIS_TIME, - SECONDS_PER_EPOCH, - EPOCHS_PER_FRAME, - SLOTS_PER_FRAME, - SECONDS_PER_FRAME, - ZERO_HASH, - HASH_1, - HASH_2, - HASH_3, - HASH_4, - HASH_5, - computeSlotAt, - computeEpochAt, - computeEpochFirstSlotAt, - computeEpochFirstSlot, - computeTimestampAtSlot, - computeTimestampAtEpoch, - CONSENSUS_VERSION, - V1_ORACLE_LAST_COMPLETED_EPOCH, - V1_ORACLE_LAST_REPORT_SLOT, - EXTRA_DATA_FORMAT_EMPTY, - EXTRA_DATA_FORMAT_LIST, - EXTRA_DATA_TYPE_STUCK_VALIDATORS, - EXTRA_DATA_TYPE_EXITED_VALIDATORS, - deployAndConfigureAccountingOracle, - deployAccountingOracleSetup, - initAccountingOracle, - deployMockLegacyOracle, - deployMockLidoAndStakingRouter, - getReportDataItems, - calcReportDataHash, - encodeExtraDataItem, - encodeExtraDataItems, - packExtraDataList, - calcExtraDataListHash, -} async function deployMockLegacyOracle({ epochsPerFrame = EPOCHS_PER_FRAME, slotsPerEpoch = SLOTS_PER_EPOCH, @@ -195,13 +156,6 @@ async function deployAccountingOracleSetup( const { lido, stakingRouter, withdrawalQueue } = await getLidoAndStakingRouter() const oracleReportSanityChecker = await deployOracleReportSanityCheckerForAccounting(locatorAddr, admin) - await updateLocatorImplementation(locatorAddr, admin, { - lido: lido.address, - stakingRouter: stakingRouter.address, - withdrawalQueue: withdrawalQueue.address, - oracleReportSanityChecker: oracleReportSanityChecker.address, - }) - const legacyOracle = await getLegacyOracle() if (initialEpoch == null) { @@ -225,6 +179,13 @@ async function deployAccountingOracleSetup( genesisTime, initialEpoch, }) + await updateLocatorImplementation(locatorAddr, admin, { + lido: lido.address, + stakingRouter: stakingRouter.address, + withdrawalQueue: withdrawalQueue.address, + oracleReportSanityChecker: oracleReportSanityChecker.address, + accountingOracle: oracle.address, + }) // pretend we're at the first slot of the initial frame's epoch await consensus.setTime(genesisTime + initialEpoch * slotsPerEpoch * secondsPerSlot) @@ -247,8 +208,20 @@ async function initAccountingOracle({ consensus, dataSubmitter = null, consensusVersion = CONSENSUS_VERSION, + shouldMigrateLegacyOracle = true, + lastProcessingRefSlot, }) { - const initTx = await oracle.initialize(admin, consensus.address, consensusVersion, { from: admin }) + let initTx + if (shouldMigrateLegacyOracle) + initTx = await oracle.initialize(admin, consensus.address, consensusVersion, { from: admin }) + else + initTx = await oracle.initializeWithoutMigration( + admin, + consensus.address, + consensusVersion, + lastProcessingRefSlot, + { from: admin } + ) await oracle.grantRole(await oracle.MANAGE_CONSENSUS_CONTRACT_ROLE(), admin, { from: admin }) await oracle.grantRole(await oracle.MANAGE_CONSENSUS_VERSION_ROLE(), admin, { from: admin }) @@ -271,6 +244,46 @@ async function deployAndConfigureAccountingOracle(admin) { return { ...deployed, initTx } } +module.exports = { + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + SECONDS_PER_EPOCH, + EPOCHS_PER_FRAME, + SLOTS_PER_FRAME, + SECONDS_PER_FRAME, + ZERO_HASH, + HASH_1, + HASH_2, + HASH_3, + HASH_4, + HASH_5, + computeSlotAt, + computeEpochAt, + computeEpochFirstSlotAt, + computeEpochFirstSlot, + computeTimestampAtSlot, + computeTimestampAtEpoch, + CONSENSUS_VERSION, + V1_ORACLE_LAST_COMPLETED_EPOCH, + V1_ORACLE_LAST_REPORT_SLOT, + EXTRA_DATA_FORMAT_EMPTY, + EXTRA_DATA_FORMAT_LIST, + EXTRA_DATA_TYPE_STUCK_VALIDATORS, + EXTRA_DATA_TYPE_EXITED_VALIDATORS, + deployAndConfigureAccountingOracle, + deployAccountingOracleSetup, + initAccountingOracle, + deployMockLegacyOracle, + deployMockLidoAndStakingRouter, + getReportDataItems, + calcReportDataHash, + encodeExtraDataItem, + encodeExtraDataItems, + packExtraDataList, + calcExtraDataListHash, +} + contract('AccountingOracle', ([admin, member1]) => { let consensus let oracle From e304ede29e19bd9f170329cb871314f32e07e1ea Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 3 Mar 2023 18:19:38 +0700 Subject: [PATCH 114/236] feat: fix mock legacy oracle to fit as old impl --- .../0.4.24/test_helpers/MockLegacyOracle.sol | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/contracts/0.4.24/test_helpers/MockLegacyOracle.sol b/contracts/0.4.24/test_helpers/MockLegacyOracle.sol index bb59b1b84..2077f11d6 100644 --- a/contracts/0.4.24/test_helpers/MockLegacyOracle.sol +++ b/contracts/0.4.24/test_helpers/MockLegacyOracle.sol @@ -27,12 +27,6 @@ contract MockLegacyOracle is ILegacyOracle, LegacyOracle { HandleConsensusLayerReportCallData public lastCall__handleConsensusLayerReport; - uint64 internal _epochsPerFrame; - uint64 internal _slotsPerEpoch; - uint64 internal _secondsPerSlot; - uint64 internal _genesisTime; - uint256 internal _lastCompletedEpochId; - function getBeaconSpec() external view returns ( uint64 epochsPerFrame, @@ -40,14 +34,22 @@ contract MockLegacyOracle is ILegacyOracle, LegacyOracle { uint64 secondsPerSlot, uint64 genesisTime ) { - return ( - _epochsPerFrame, - _slotsPerEpoch, - _secondsPerSlot, - _genesisTime - ); + + ChainSpec memory spec = _getChainSpec(); + epochsPerFrame = spec.epochsPerFrame; + slotsPerEpoch = spec.slotsPerEpoch; + secondsPerSlot = spec.secondsPerSlot; + genesisTime = spec.genesisTime; + } + + function setBeaconSpec( uint64 epochsPerFrame, + uint64 slotsPerEpoch, + uint64 secondsPerSlot, + uint64 genesisTime) external { + _setChainSpec(ChainSpec(epochsPerFrame,slotsPerEpoch,secondsPerSlot,genesisTime)); } + function handleConsensusLayerReport(uint256 refSlot, uint256 clBalance, uint256 clValidators) external { @@ -65,18 +67,13 @@ contract MockLegacyOracle is ILegacyOracle, LegacyOracle { uint64 genesisTime, uint256 lastCompletedEpochId ) external { - _epochsPerFrame = epochsPerFrame; - _slotsPerEpoch = slotsPerEpoch; - _secondsPerSlot = secondsPerSlot; - _genesisTime = genesisTime; - _lastCompletedEpochId = lastCompletedEpochId; - - } - function getLastCompletedEpochId() external view returns (uint256) { - return _lastCompletedEpochId; + _setChainSpec(ChainSpec(epochsPerFrame,slotsPerEpoch,secondsPerSlot,genesisTime)); + LAST_COMPLETED_EPOCH_ID_POSITION.setStorageUint256(lastCompletedEpochId); } - + function setLastCompletedEpochId(uint256 lastCompletedEpochId) external { - _lastCompletedEpochId = lastCompletedEpochId; + LAST_COMPLETED_EPOCH_ID_POSITION.setStorageUint256(lastCompletedEpochId); } + + } From ff356887f1d44d72937ef4fb94a239982d8e37c2 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 3 Mar 2023 19:49:29 +0700 Subject: [PATCH 115/236] feat: legacy oracle migration test --- .../0.4.24/test_helpers/MockLegacyOracle.sol | 3 + ...e-deploy.test.js => legacy-oracle.test.js} | 63 +++++++++++++++++-- test/0.4.24/legacyoracle.test.js | 5 -- 3 files changed, 61 insertions(+), 10 deletions(-) rename test/0.4.24/{legacy-oracle-deploy.test.js => legacy-oracle.test.js} (61%) delete mode 100644 test/0.4.24/legacyoracle.test.js diff --git a/contracts/0.4.24/test_helpers/MockLegacyOracle.sol b/contracts/0.4.24/test_helpers/MockLegacyOracle.sol index 2077f11d6..01049a671 100644 --- a/contracts/0.4.24/test_helpers/MockLegacyOracle.sol +++ b/contracts/0.4.24/test_helpers/MockLegacyOracle.sol @@ -75,5 +75,8 @@ contract MockLegacyOracle is ILegacyOracle, LegacyOracle { LAST_COMPLETED_EPOCH_ID_POSITION.setStorageUint256(lastCompletedEpochId); } + function initializeAsV3() external { + CONTRACT_VERSION_POSITION_DEPRECATED.setStorageUint256(3); + } } diff --git a/test/0.4.24/legacy-oracle-deploy.test.js b/test/0.4.24/legacy-oracle.test.js similarity index 61% rename from test/0.4.24/legacy-oracle-deploy.test.js rename to test/0.4.24/legacy-oracle.test.js index feb9fd664..92341bf61 100644 --- a/test/0.4.24/legacy-oracle-deploy.test.js +++ b/test/0.4.24/legacy-oracle.test.js @@ -1,9 +1,14 @@ -const { contract, ethers } = require('hardhat') +const { contract, ethers, artifacts } = require('hardhat') const { assert } = require('../helpers/assert') const { impersonate } = require('../helpers/blockchain') const { legacyOracleFactory } = require('../helpers/factories') +const OssifiableProxy = artifacts.require('OssifiableProxy') + +const LegacyOracle = artifacts.require('LegacyOracle') +const MockLegacyOracle = artifacts.require('MockLegacyOracle') + const { deployAccountingOracleSetup, initAccountingOracle, @@ -13,7 +18,7 @@ const { GENESIS_TIME, } = require('../0.8.9/oracle/accounting-oracle-deploy.test') -async function deployLegacyOracle({ admin, initialEpoch = 1, lastProcessingRefSlot = 31 }) { +async function deployLegacyOracleWithAccountingOracle({ admin, initialEpoch = 1, lastProcessingRefSlot = 31 }) { const legacyOracle = await legacyOracleFactory({ appManager: { address: admin } }) const { locatorAddr, consensus, oracle, lido } = await deployAccountingOracleSetup(admin, { initialEpoch, @@ -28,7 +33,7 @@ async function deployLegacyOracle({ admin, initialEpoch = 1, lastProcessingRefSl } module.exports = { - deployLegacyOracle, + deployLegacyOracleWithAccountingOracle, } contract('LegacyOracle', ([admin, stranger]) => { @@ -36,7 +41,7 @@ contract('LegacyOracle', ([admin, stranger]) => { context('Fresh deploy and puppet methods checks', () => { before('deploy', async () => { - const deployed = await deployLegacyOracle({ admin }) + const deployed = await deployLegacyOracleWithAccountingOracle({ admin }) legacyOracle = deployed.legacyOracle accountingOracle = deployed.accountingOracle lido = deployed.lido @@ -97,6 +102,54 @@ contract('LegacyOracle', ([admin, stranger]) => { }) context('Migration from old contract', () => { - it.skip('deploy') + const lastCompletedEpoch = 10 + let oldImplementation + let newImplementation + let proxy + let proxyAsOldImplementation + let proxyAsNewImplementation + let deployedInfra + + before('deploy old implementation and set as proxy', async () => { + oldImplementation = await MockLegacyOracle.new({ from: admin }) + newImplementation = await LegacyOracle.new({ from: admin }) + proxy = await OssifiableProxy.new(oldImplementation.address, admin, '0x') + proxyAsOldImplementation = await MockLegacyOracle.at(proxy.address) + }) + + it('implementations are petrified', async () => { + await assert.reverts(oldImplementation.initialize(stranger, stranger), 'INIT_ALREADY_INITIALIZED') + await assert.reverts(newImplementation.initialize(stranger, stranger), 'INIT_ALREADY_INITIALIZED') + }) + + it('set state to mimic legacy oracle', async () => { + await proxyAsOldImplementation.initializeAsV3() + await proxyAsOldImplementation.setParams( + EPOCHS_PER_FRAME, + SLOTS_PER_EPOCH, + SECONDS_PER_SLOT, + GENESIS_TIME, + lastCompletedEpoch + ) + }) + + it('deploy&initialize all contracts', async () => { + deployedInfra = await deployAccountingOracleSetup(admin, { + legacyOracleAddrArg: proxy.address, + getLegacyOracle: () => { + return proxyAsOldImplementation + }, + }) + const { consensus, oracle } = deployedInfra + await initAccountingOracle({ admin, oracle, consensus, shouldMigrateLegacyOracle: true }) + }) + + it('upgrade implementation', async () => { + await proxy.proxy__upgradeTo(newImplementation.address) + proxyAsNewImplementation = await LegacyOracle.at(proxy.address) + await proxyAsNewImplementation.finalizeUpgrade_v4(deployedInfra.oracle.address) + }) + + it.skip('lifecycle tests') }) }) diff --git a/test/0.4.24/legacyoracle.test.js b/test/0.4.24/legacyoracle.test.js deleted file mode 100644 index 4db9b947c..000000000 --- a/test/0.4.24/legacyoracle.test.js +++ /dev/null @@ -1,5 +0,0 @@ -const { contract } = require('hardhat') - -contract('LegacyOracle', () => { - it.skip('TODO: legacy compat tests', async () => {}) -}) From 9d508efa687e0f486bb64da8276870978980ba60 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Fri, 3 Mar 2023 15:44:32 +0200 Subject: [PATCH 116/236] wq: iterate on the integration/gas test --- test/helpers/debug.js | 21 ++++ test/helpers/oracle.js | 92 ++++++++++------ ...ido-wq-acct-oracle-integration-gas.test.js | 103 +++++++++++++++--- 3 files changed, 167 insertions(+), 49 deletions(-) create mode 100644 test/helpers/debug.js diff --git a/test/helpers/debug.js b/test/helpers/debug.js new file mode 100644 index 000000000..b351e1e2a --- /dev/null +++ b/test/helpers/debug.js @@ -0,0 +1,21 @@ +const { BN } = require('bn.js') + +// transforms all object entries +const transformEntries = (obj, tr) => + Object.fromEntries( + Object.entries(obj) + .map(tr) + .filter((x) => x !== undefined) + ) + +// converts all object BN keys to strings, drops numeric keys and the __length__ key +const processNamedTuple = (obj) => + transformEntries(obj, ([k, v]) => { + return /^(\d+|__length__)$/.test(k) ? undefined : [k, BN.isBN(v) ? v.toString() : v] + }) + +const printEvents = (tx) => { + console.log(tx.receipt.logs.map(({ event, args }) => ({ event, args: processNamedTuple(args) }))) +} + +module.exports = { transformEntries, processNamedTuple, printEvents } diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index 889bb0a58..1a9d3a8ae 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -34,6 +34,39 @@ function calcReportDataHash(reportItems) { return web3.utils.keccak256(data) } +const DEFAULT_REPORT_FIELDS = { + consensusVersion: 1, + refSlot: 0, + numValidators: 0, + clBalanceGwei: 0, + stakingModuleIdsWithNewlyExitedValidators: [], + numExitedValidatorsByStakingModule: [], + withdrawalVaultBalance: 0, + elRewardsVaultBalance: 0, + sharesRequestedToBurn: 0, + withdrawalFinalizationBatches: [], + simulatedShareRate: 0, + isBunkerMode: false, + extraDataFormat: 0, + extraDataHash: ZERO_BYTES32, + extraDataItemsCount: 0, +} + +const E9 = toBN(10).pow(toBN(9)) + +async function prepareOracleReport({ clBalance, ...restFields }) { + const fields = { + ...DEFAULT_REPORT_FIELDS, + ...restFields, + clBalanceGwei: toBN(clBalance).div(E9), + } + + const items = getReportDataItems(fields) + const hash = calcReportDataHash(items) + + return { fields, items, hash } +} + async function triggerConsensusOnHash(hash, consensus) { const members = await consensus.getMembers() const { refSlot } = await consensus.getCurrentFrame() @@ -42,55 +75,48 @@ async function triggerConsensusOnHash(hash, consensus) { assert.equal((await consensus.getConsensusState()).consensusReport, hash) } -async function reportOracle(consensus, oracle, { numValidators, clBalance, elRewards = 0 }) { +async function reportOracle(consensus, oracle, reportFields) { const { refSlot } = await consensus.getCurrentFrame() - const reportFields = { - consensusVersion: 1, - refSlot, - numValidators, - clBalanceGwei: toBN(clBalance).div(toBN(10).pow(toBN(9))), - stakingModuleIdsWithNewlyExitedValidators: [], - numExitedValidatorsByStakingModule: [], - withdrawalVaultBalance: 0, - elRewardsVaultBalance: elRewards, - sharesRequestedToBurn: 0, - withdrawalFinalizationBatches: [], - simulatedShareRate: 0, - isBunkerMode: false, - extraDataFormat: 0, - extraDataHash: ZERO_BYTES32, - extraDataItemsCount: 0, - } + const report = await prepareOracleReport({ ...reportFields, refSlot }) - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + // non-empty extra data is not supported here yet + assert.equals(report.fields.extraDataFormat, 0) + assert.equals(report.fields.extraDataHash, ZERO_BYTES32) + assert.equals(report.fields.extraDataItemsCount, 0) const members = await consensus.getMembers() - - await triggerConsensusOnHash(reportHash, consensus) + await triggerConsensusOnHash(report.hash, consensus) const oracleVersion = await oracle.getContractVersion() - - const submitDataTx = await oracle.submitReportData(reportItems, oracleVersion, { from: members.addresses[0] }) + const submitDataTx = await oracle.submitReportData(report.items, oracleVersion, { from: members.addresses[0] }) const submitExtraDataTx = await oracle.submitReportExtraDataEmpty({ from: members.addresses[0] }) - return { submitDataTx, submitExtraDataTx } + return { report, submitDataTx, submitExtraDataTx } } +// FIXME: kept for compat, remove after refactoring tests function pushOracleReport(consensus, oracle, numValidators, clBalance, elRewards) { return reportOracle(consensus, oracle, { numValidators, clBalance, elRewards }) } -// const computeSlotAt = (time, c) => Math.floor((time - (+c.genesisTime)) / (+c.secondsPerSlot)) -// const computeEpochAt = (time, c) => Math.floor(computeSlotAt(time, c) / (+c.slotsPerEpoch)) -// const computeEpochFirstSlot = (epoch, c) => epoch * (+c.slotsPerEpoch) -// const computeEpochFirstSlotAt = (time, c) => computeEpochFirstSlot(computeEpochAt(time, c), c) -// const computeTimestampAtEpoch = (epoch, c) => +c.genesisTime + epoch * ((+c.secondsPerSlot) * (+c.slotsPerEpoch)) -// const computeTimestampAtSlot = (slot, c) => +c.genesisTime + slot * +c.secondsPerSlot - async function getSecondsPerFrame(consensus) { const [chainConfig, frameConfig] = await Promise.all([consensus.getChainConfig(), consensus.getFrameConfig()]) return +chainConfig.secondsPerSlot * +chainConfig.slotsPerEpoch * +frameConfig.epochsPerFrame } -module.exports = { getReportDataItems, calcReportDataHash, reportOracle, pushOracleReport, getSecondsPerFrame } +async function getSlotTimestamp(slot, consensus) { + const chainConfig = await consensus.getChainConfig() + return +chainConfig.genesisTime + +chainConfig.secondsPerSlot * slot +} + +module.exports = { + DEFAULT_REPORT_FIELDS, + getReportDataItems, + calcReportDataHash, + prepareOracleReport, + triggerConsensusOnHash, + reportOracle, + pushOracleReport, + getSecondsPerFrame, + getSlotTimestamp, +} diff --git a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js index 2ddbe868a..c4c3b88f5 100644 --- a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js +++ b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js @@ -1,9 +1,11 @@ +const { BN } = require('bn.js') const { assert } = require('../helpers/assert') const { MAX_UINT256 } = require('../helpers/constants') -const { ZERO_ADDRESS, toBN, e18, e27 } = require('../helpers/utils') +const { ZERO_ADDRESS, toBN, e9, e18, e27, toStr } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') -const { reportOracle, getSecondsPerFrame } = require('../helpers/oracle') +const { prepareOracleReport, reportOracle, getSecondsPerFrame, getSlotTimestamp } = require('../helpers/oracle') const { advanceChainTime } = require('../helpers/blockchain') +const { processNamedTuple } = require('../helpers/debug') const StakingModuleMock = artifacts.require('StakingModuleMock') @@ -16,7 +18,7 @@ function piecewiseModN({values, pointsPerValue, x}) { } -contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, user, stranger]) => { +contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, user, user2, stranger]) => { const test = (numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema) => { let lido, router, wQueue, oracle, consensus, voting, stakingModule, stakingModuleId @@ -63,11 +65,15 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use await advanceChainTime(secondsPerFrame) } - const rebaseToShareRateBP = async (shareRateBP) => { - const stat = await lido.getBeaconStat() + const calcCLBalanceIncreaseForShareRateBP = async (shareRateBP) => { const totalShares = await lido.getTotalShares() const newTotalEth = toBN(shareRateBP).mul(toBN(totalShares)).divn(10000) - const ethDiff = newTotalEth.sub(toBN(await lido.getTotalPooledEther())) + return newTotalEth.sub(toBN(await lido.getTotalPooledEther())) + } + + const rebaseToShareRateBP = async (shareRateBP) => { + const stat = await lido.getBeaconStat() + const ethDiff = await calcCLBalanceIncreaseForShareRateBP(shareRateBP) const newCLBalance = toBN(stat.beaconBalance).add(ethDiff) await advanceTimeToNextFrame() @@ -114,9 +120,10 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use const totalRequests = numRebases * withdrawalRequestsPerRebase const shareRatesBP = [10010, 10020] + let shareRateBP for (let i = 0; i < numRebases; ++i) { - const shareRateBP = Math.floor(piecewiseModN({ + shareRateBP = Math.floor(piecewiseModN({ values: shareRatesBP, pointsPerValue: rebasesPerShareRateExtrema, x: i @@ -133,24 +140,88 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use const amounts = new Array(withdrawalRequestsPerRebase).fill(requestSize) await wQueue.requestWithdrawals(amounts, user, { from: user }) }) + + if (i == numRebases - 1) { + it(`users submit enough ETH to buffer to fullfill all withdrawals`, async () => { + // twice as much ETH will be enough in all scenarios + await lido.submit(ZERO_ADDRESS, { from: user2, value: toBN(userBalance).muln(2) }) + }) + } }) } - const finalizationShareRateBP = Math.floor((shareRatesBP[0] + shareRatesBP[1]) / 2) + const finalShareRateBP = Math.floor((shareRatesBP[0] + shareRatesBP[1]) / 2) + const finalShareRate27 = e27(finalShareRateBP / 10000) - context(`share rate: ${finalizationShareRateBP / 10000}`, () => { - it(`calculating batches`, async () => { - await rebaseToShareRateBP(finalizationShareRateBP) - const shareRate27 = e27(finalizationShareRateBP / 10000) + context(`share rate: ${finalShareRateBP / 10000}`, () => { + let batches, totals, oracleReportFields, ethAvailForWithdrawals + + it(`calculating available ETH`, async () => { + const { refSlot } = await consensus.getCurrentFrame() + + const stat = await lido.getBeaconStat() + const ethDiff = await calcCLBalanceIncreaseForShareRateBP(finalShareRateBP) + const newCLBalance = toBN(stat.beaconBalance).add(ethDiff) + + oracleReportFields = { + refSlot, + numValidators: stat.beaconValidators, + clBalance: newCLBalance, + withdrawalVaultBalance: 0, + elRewardsVaultBalance: 0, + sharesRequestedToBurn: 0, + withdrawalFinalizationBatches: [], + } - let calcState = { ethBudget: MAX_UINT256, finished: false, batches: [] } + const timestamp = await getSlotTimestamp(+refSlot, consensus) + const secondsElapsed = secondsPerFrame + + const [totalEth, totalShares, withdrawals, elRewards] = await lido.handleOracleReport.call( + timestamp, + secondsElapsed, + oracleReportFields.numValidators, + oracleReportFields.clBalance, + oracleReportFields.withdrawalVaultBalance, + oracleReportFields.elRewardsVaultBalance, + oracleReportFields.sharesRequestedToBurn, + [], // withdrawalFinalizationBatches + 0, // simulatedShareRate + { from: oracle.address } + ) + + assert.equals(withdrawals, 0) + assert.equals(elRewards, 0) + + const shareRateE27 = toBN(e27(totalEth)).div(toBN(totalShares)) + const oneWeiE27 = e9(1) + + assert.isClose(shareRateE27, finalShareRate27, oneWeiE27) + + const unfinalizedStETH = await wQueue.unfinalizedStETH() + const bufferedEth = await lido.getBufferedEther() + + ethAvailForWithdrawals = BN.min(toBN(unfinalizedStETH), toBN(bufferedEth)) + .add(toBN(withdrawals)) + .add(toBN(elRewards)) + + console.log(`ethAvailForWithdrawals: ${ethAvailForWithdrawals.div(toBN(10).pow(toBN(18)))}`) + }) + + it(`calculating batches`, async () => { + let calcState = { ethBudget: toStr(ethAvailForWithdrawals), finished: false, batches: [] } let i = 0 while (!calcState.finished) { - calcState = await wQueue.calculateFinalizationBatches(shareRate27, MAX_UINT256, calcState) - console.log(`calcState ${i}:`, calcState) + calcState = await wQueue.calculateFinalizationBatches(finalShareRate27, MAX_UINT256, calcState) + console.log(`calcState ${i}:`, processNamedTuple(calcState)) ++i } + + batches = calcState.batches + }) + + it.skip(`oracle report`, async () => { + // TODO }) }) } @@ -161,6 +232,6 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use `rebases per extrema: ${rebasesPerShareRateExtrema}` context(desc, () => test(numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema)) } - testWithParams(40, 1, 1) + testWithParams(2, 1, 1) }) }) From d66f1a23a16a7dbdae225c4e83fbf74ae434faac Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Fri, 3 Mar 2023 17:15:30 +0200 Subject: [PATCH 117/236] fix: OOB in extrema list --- contracts/0.8.9/WithdrawalQueueBase.sol | 54 ++++++++++++++----------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 3f2f91d86..ef2b744ba 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -23,7 +23,7 @@ abstract contract WithdrawalQueueBase { /// @notice precision base for share rate and discounting factor values in the contract uint256 internal constant E27_PRECISION_BASE = 1e27; - uint256 internal constant MAX_EXTREMA_PER_CALL = 36; + uint256 internal constant MAX_BATCHES_LENGTH = 36; uint256 internal constant MAX_REQUESTS_PER_CALL = 1000; uint256 internal constant SHARE_RATE_UNLIMITED = type(uint256).max; @@ -178,38 +178,45 @@ abstract contract WithdrawalQueueBase { { if (_state.finished) revert InvalidState(); + uint256 batchesLength; uint256 requestId; uint256 prevRequestShareRate; if (_state.batches.length == 0) { requestId = getLastFinalizedRequestId() + 1; // we'll store batches as a array where [MAX_REBASE_NUMBER] element is the array's length - _state.batches = new uint256[](MAX_EXTREMA_PER_CALL + 1); + _state.batches = new uint256[](MAX_BATCHES_LENGTH + 1); } else { - requestId = _state.batches[_state.batches[0]] + 1; - prevRequestShareRate = _calcShareRate(_state.batches[_state.batches[0]], _maxShareRate); + batchesLength = _state.batches[MAX_BATCHES_LENGTH]; + requestId = _state.batches[batchesLength] + 1; + prevRequestShareRate = _calcShareRate(_state.batches[batchesLength], _maxShareRate); } uint256 lastRequestId = getLastRequestId(); - uint256 maxPossibleRequestId = requestId + MAX_REQUESTS_PER_CALL; uint256 extemumStartIndex = _getLastCheckedExtremum() + 1; uint256 extremaCounter; - while (requestId < maxPossibleRequestId) { - if (requestId > lastRequestId) break; // if end of the queue - - if (requestId == _getExtrema()[extemumStartIndex + extremaCounter]) { + while (requestId < requestId + MAX_REQUESTS_PER_CALL) { + // end of the queue break + if (requestId > lastRequestId) break; + + if ( + extemumStartIndex + extremaCounter < _getExtrema().length && + requestId == _getExtrema()[extemumStartIndex + extremaCounter] + ) { + // max extrema counter break + // we can't allow that batches covers unbounded number of extrema + // it'll require an unbounded loop to check them onchain unchecked { ++extremaCounter; } - if (extremaCounter > MAX_EXTREMA_PER_CALL) break; + if (extremaCounter > MAX_BATCHES_LENGTH) break; } WithdrawalRequest memory request = _getQueue()[requestId]; - + // max timestamp break if (request.timestamp > _maxTimestamp) break; WithdrawalRequest memory prevRequest = _getQueue()[requestId - 1]; - uint256 ethToFinalize = request.cumulativeStETH - prevRequest.cumulativeStETH; uint256 shareRequested = request.cumulativeShares - prevRequest.cumulativeShares; uint256 requestShareRate = ethToFinalize * E27_PRECISION_BASE / shareRequested; @@ -222,25 +229,25 @@ abstract contract WithdrawalQueueBase { _state.ethBudget -= ethToFinalize; - if (_state.batches[MAX_EXTREMA_PER_CALL] != 0 && ( + if (batchesLength != 0 && ( prevRequest.reportTimestamp == request.reportTimestamp || prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || prevRequestShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { - _state.batches[_state.batches[MAX_EXTREMA_PER_CALL] - 1] = requestId; + _state.batches[batchesLength - 1] = requestId; } else { - _state.batches[_state.batches[MAX_EXTREMA_PER_CALL]] = requestId; - ++_state.batches[MAX_EXTREMA_PER_CALL]; + _state.batches[batchesLength] = requestId; + batchesLength = ++_state.batches[MAX_BATCHES_LENGTH]; } prevRequestShareRate = requestShareRate; unchecked{ ++requestId; } } - _state.finished = requestId < maxPossibleRequestId || requestId == lastRequestId + 1; + _state.finished = requestId < requestId + MAX_REQUESTS_PER_CALL || requestId == lastRequestId + 1; if (_state.finished) { - MemUtils.trimUint256Array(_state.batches, _state.batches.length - _state.batches[MAX_EXTREMA_PER_CALL]); + MemUtils.trimUint256Array(_state.batches, _state.batches.length - batchesLength); } return _state; @@ -432,15 +439,11 @@ abstract contract WithdrawalQueueBase { if (prevRequest.reportTimestamp == newRequest.reportTimestamp) return; uint256[] storage extrema = _getExtrema(); - // bootstrap the algo adding thee first request as an extrema by default - if (extrema.length == 1 && newRequestId > 0) { - extrema.push(newRequestId); + if (extrema.length == 1) { + extrema.push(newRequestId); // first request is always an extremum return; } - uint256 lastExtremumId = extrema[extrema.length - 1]; - WithdrawalRequest memory lastExtremumRequest = _getQueue()[lastExtremumId]; - uint256 newRequestShareRate = _calcShareRate(prevRequest, newRequest, SHARE_RATE_UNLIMITED); uint256 prevRequestShareRate = _calcShareRate(newRequestId - 1, SHARE_RATE_UNLIMITED); @@ -448,6 +451,9 @@ abstract contract WithdrawalQueueBase { // there can't be rounding jitter because we skipped on the same report requests in the beginning if (newRequestShareRate == prevRequestShareRate) return; + uint256 lastExtremumId = extrema[extrema.length - 1]; + WithdrawalRequest memory lastExtremumRequest = _getQueue()[lastExtremumId]; + uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId, lastExtremumRequest); bool wasGrowing = lastExtremumShareRate < prevRequestShareRate; From c372c14a8891ad065f8b94d5b458c18de42423ea Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Fri, 3 Mar 2023 17:16:19 +0200 Subject: [PATCH 118/236] test: fix a burner test --- test/0.8.9/burner.test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/0.8.9/burner.test.js b/test/0.8.9/burner.test.js index 70d1969d5..42ea04ef7 100644 --- a/test/0.8.9/burner.test.js +++ b/test/0.8.9/burner.test.js @@ -130,10 +130,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { }) it(`only Lido can commit shares to burn`, async () => { - assert.revertsWithCustomError( - burner.commitSharesToBurn(0, { from: anotherAccount }), - `AppAuthLidoFailed('${anotherAccount}')` - ) + assert.revertsWithCustomError(burner.commitSharesToBurn(0, { from: anotherAccount }), `AppAuthLidoFailed()`) await burner.commitSharesToBurn(0, { from: lido.address }) }) From 8e80a6e20f59ed447fb1f9cb50756231a489dbd1 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Fri, 3 Mar 2023 18:13:31 +0200 Subject: [PATCH 119/236] docs: better docs and checks for wq --- contracts/0.8.9/WithdrawalQueueBase.sol | 124 ++++++++++++++++-------- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 4 files changed, 87 insertions(+), 43 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index ef2b744ba..80f753d9f 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -31,26 +31,26 @@ abstract contract WithdrawalQueueBase { /// @dev return value for the `find...` methods in case of no result uint256 internal constant NOT_FOUND = 0; - // queue for withdrawal requests, indexes (requestId) start from 1 + /// @dev queue for withdrawal requests, indexes (requestId) start from 1 bytes32 internal constant QUEUE_POSITION = keccak256("lido.WithdrawalQueue.queue"); - // length of the queue + /// @dev length of the queue bytes32 internal constant LAST_REQUEST_ID_POSITION = keccak256("lido.WithdrawalQueue.lastRequestId"); - // length of the finalized part of the queue. Always <= `requestCounter` + /// @dev length of the finalized part of the queue. Always <= `requestCounter` bytes32 internal constant LAST_FINALIZED_REQUEST_ID_POSITION = keccak256("lido.WithdrawalQueue.lastFinalizedRequestId"); - /// finalization discount history, indexes start from 1 + /// @dev finalization discount history, indexes start from 1 bytes32 internal constant CHECKPOINTS_POSITION = keccak256("lido.WithdrawalQueue.checkpoints"); - /// length of the checkpoints + /// @dev length of the checkpoints bytes32 internal constant LAST_CHECKPOINT_INDEX_POSITION = keccak256("lido.WithdrawalQueue.lastCheckpointIndex"); - /// amount of eth locked on contract for withdrawal + /// @dev amount of eth locked on contract for withdrawal bytes32 internal constant LOCKED_ETHER_AMOUNT_POSITION = keccak256("lido.WithdrawalQueue.lockedEtherAmount"); - /// withdrawal requests mapped to the owners + /// @dev withdrawal requests mapped to the owners bytes32 internal constant REQUEST_BY_OWNER_POSITION = keccak256("lido.WithdrawalQueue.requestsByOwner"); - /// list of extremum requests for shareRate(request_id) function + /// @dev list of extremum requests for shareRate(request_id) function bytes32 internal constant EXTREMA_POSITION = keccak256("lido.WithdrawalQueue.extrema"); - /// last extreum index that was already checked for finalization + /// @dev last extreum index that was already checked for finalization bytes32 internal constant LAST_CHECKED_EXTREMUM_POSITION = keccak256("lido.WithdrawalQueue.lastCheckedExtremum"); - + /// @dev timestamp of the last oracle report bytes32 internal constant LAST_REPORT_TIMESTAMP_POSITION = keccak256("lido.WithdrawalQueue.lastReportTimestamp"); @@ -66,7 +66,7 @@ abstract contract WithdrawalQueueBase { uint40 timestamp; /// @notice flag if the request was claimed bool claimed; - /// @notice timestamp of lastReport + /// @notice timestamp of last oracle report for this request uint40 reportTimestamp; } @@ -115,7 +115,7 @@ abstract contract WithdrawalQueueBase { error InvalidRequestId(uint256 _requestId); error InvalidRequestIdRange(uint256 startId, uint256 endId); error InvalidState(); - error InvalidBatches(); + error InvalidBatch(uint256 index); error EmptyBatches(); error RequestNotFoundOrNotFinalized(uint256 _requestId); error NotEnoughEther(); @@ -154,47 +154,82 @@ abstract contract WithdrawalQueueBase { _getQueue()[getLastRequestId()].cumulativeStETH - _getQueue()[getLastFinalizedRequestId()].cumulativeStETH; } - // FINALIZATION. - // Process when protocol is fixing the withdrawal request value and lock the required amount of stETH. - // It is driven by the oracle report - // Right now finalization consists of several steps: - // 1. Oracle daemon precalculates finalization batches' boundaries that is valid on oracle report refSlot - // and post it with the report - `calculateFinalizationBatches()` - // 2. AccountingOracle contract invokes `onOracleReport()` handler to update ShareRate extremum list - // 3. Lido contract, during the report handling, calculates the value of finalization batchs in eth and shares - // and checks its correctness - `prefinalize()` - // 4. Lido contract finalize the requests passing the required ether along with `finalize()` method + // + // FINALIZATION + // + // Process when protocol is fixing the withdrawal request value and lock the required amount of ETH. + // Locked ETH can be claimed by the owner of the request + // Finalization is a part of the oracle report + // Steps: + // Off-chain + // 1. Oracle daemon precalculates finalization batches' boundaries using `calculateFinalizationBatches()` + // On-chain + // 2. AccountingOracle contract invokes `onOracleReport()` handler to update last report timestamp for the queue + // 3. Lido contract, during the report handling, calculates the value of finalization batch in eth and shares + // and checks its correctness using `prefinalize()` + // 4. Lido contract finalize the batch of requests passing the required ether along with `finalize()` method + // + /// @notice transient state that is used to pass intemediate results between several `calculateFinalizationBatches` + // invokations struct CalcState { + /// @notice amount of ether available in the protocol that can be used to finalize withdrawal requests + /// Will decrease on each invokation and will be equal to the remainder when calculation is finished + /// Should be set before the first invokation uint256 ethBudget; + /// @notice flag that is `true` if returned state is final and `false` if more invokations required bool finished; + /// @notice contains finalization batches once calculation is finished. Can't be used if finished is false. uint256[] batches; } + /// Offchain view for the oracle daemon that calculates how many requests can be finalized within the given budget + /// and timestamp and share rate limits. Returned requests are split into the batches. + /// Each batch consist of the requests that all have the share rate below the `_maxShareRate` or above it. + /// Below you can see an example how 14 requests with different share rates will be split into 5 batches by + /// this algorithm + /// + /// ^ share rate + /// | + /// | • • + /// | • • • • • + /// |----------------------•------ _maxShareRate + /// | • • • • • + /// | • + /// +-------------------------------> requestId + /// | 1st| 2nd |3| 4th | 5th | + /// + /// @param _maxShareRate current share rate of the protocol with 1e27 precision + /// @param _maxTimestamp max timestamp of the request that can be finalized + /// @param _state structure that accumulates the state across multiple invokations to overcome gas limits. + /// To start calculation you should pass `state.ethBudget` and `state.finished == false` and then invoke + /// the function with returned `state` until it returns a state with `finished` flag set + /// @return state state that was changed dring this function invokation. + /// If (state.finished) than calculation is finished and you can use state.batches is ready to be used function calculateFinalizationBatches(uint256 _maxShareRate, uint256 _maxTimestamp, CalcState memory _state) external view - returns (CalcState memory) + returns (CalcState memory state) { - if (_state.finished) revert InvalidState(); + if (_state.finished || _state.ethBudget == 0) revert InvalidState(); uint256 batchesLength; uint256 requestId; - uint256 prevRequestShareRate; + uint256 prevShareRate; if (_state.batches.length == 0) { requestId = getLastFinalizedRequestId() + 1; - // we'll store batches as a array where [MAX_REBASE_NUMBER] element is the array's length + // we'll store batches as a array where [MAX_BATCHES_LENGTH] element is the array's length _state.batches = new uint256[](MAX_BATCHES_LENGTH + 1); } else { batchesLength = _state.batches[MAX_BATCHES_LENGTH]; requestId = _state.batches[batchesLength] + 1; - prevRequestShareRate = _calcShareRate(_state.batches[batchesLength], _maxShareRate); + prevShareRate = _calcShareRate(_state.batches[batchesLength], _maxShareRate); } uint256 lastRequestId = getLastRequestId(); - uint256 extemumStartIndex = _getLastCheckedExtremum() + 1; + uint256 firstUncheckedExtremum = _getLastCheckedExtremum() + 1; uint256 extremaCounter; while (requestId < requestId + MAX_REQUESTS_PER_CALL) { @@ -202,8 +237,8 @@ abstract contract WithdrawalQueueBase { if (requestId > lastRequestId) break; if ( - extemumStartIndex + extremaCounter < _getExtrema().length && - requestId == _getExtrema()[extemumStartIndex + extremaCounter] + firstUncheckedExtremum + extremaCounter < _getExtrema().length && + requestId == _getExtrema()[firstUncheckedExtremum + extremaCounter] ) { // max extrema counter break // we can't allow that batches covers unbounded number of extrema @@ -225,14 +260,14 @@ abstract contract WithdrawalQueueBase { ethToFinalize = shareRequested * _maxShareRate / E27_PRECISION_BASE; } + // budget break if (ethToFinalize > _state.ethBudget) break; - _state.ethBudget -= ethToFinalize; if (batchesLength != 0 && ( prevRequest.reportTimestamp == request.reportTimestamp || - prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || - prevRequestShareRate > _maxShareRate && requestShareRate > _maxShareRate + prevShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || + prevShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { _state.batches[batchesLength - 1] = requestId; } else { @@ -240,7 +275,7 @@ abstract contract WithdrawalQueueBase { batchesLength = ++_state.batches[MAX_BATCHES_LENGTH]; } - prevRequestShareRate = requestShareRate; + prevShareRate = requestShareRate; unchecked{ ++requestId; } } @@ -252,7 +287,11 @@ abstract contract WithdrawalQueueBase { return _state; } - + /// @notice Checks the finalization batches, calculates required ether and the amount of shares to burn and + /// @param _batches finalization batches calculated offchain using `calculateFinalizationBatches` + /// @param _maxShareRate max possible share rate that will be used for request finalization + /// @return ethToLock amount of ether that should be sent with `finalize()` method later + /// @return sharesToBurn amount of shares that belongs tho finalizable requests function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate) external returns (uint256 ethToLock, uint256 sharesToBurn) @@ -292,7 +331,12 @@ abstract contract WithdrawalQueueBase { unchecked{ ++batchIndex; } } while (batchIndex < _batches.length); } - + /// @dev checks batches integrity across extrema list and `_maxShareRate` value and reverts if something is wrong + /// Invariants checked + /// - if shareRate(batch[i]) is below _maxShareRate => shareRate(batch[i+1]) is above and vice versa + /// - if batch includes an extremum: + /// shareRate(extremum) is above the _maxShareRate if shareRate(batch) is above it + /// shareRate(extremum) is below the _maxShareRate if shareRate(batch) is below it function _checkFinalizationBatchesIntegrity(uint256[] memory _batches, uint256 _maxShareRate) internal view @@ -318,8 +362,8 @@ abstract contract WithdrawalQueueBase { // check extremum uint256 extremumShareRate = _calcShareRate(extremumId, SHARE_RATE_UNLIMITED); - if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatches(); - if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatches(); + if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatch(batchIndex); + if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatch(batchIndex); } unchecked { ++extremumIndex; } } else { @@ -331,11 +375,11 @@ abstract contract WithdrawalQueueBase { ); // avg batch rate before crossing point and after crossing point // can't be both below `_maxShareRate` - if (batchShareRate <= _maxShareRate && nextBatchShareRate <= _maxShareRate) revert InvalidBatches(); + if (batchShareRate <= _maxShareRate && nextBatchShareRate <= _maxShareRate) revert InvalidBatch(batchIndex); // avg batch rate before crossing point and after crossing point // can't be both above `_maxShareRate` - if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) revert InvalidBatches(); + if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) revert InvalidBatch(batchIndex); batchShareRate = nextBatchShareRate; batchPreStartId = batchEndId; diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index a55253658..6daa81adc 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index cd9dbd396..cc531288e 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index a9f9a9cb3..7482c3a82 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file From b6281e657ea7ba679ecc5adf6869afc133843d59 Mon Sep 17 00:00:00 2001 From: KRogLA Date: Fri, 3 Mar 2023 18:15:39 +0100 Subject: [PATCH 120/236] fix: eliminate revert on setting large targetLimit --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 5 +++-- test/0.4.24/node-operators-registry.test.js | 11 +++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 124c9817c..d1dbbae24 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -772,9 +772,10 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { newMaxSigningKeysCount = vettedSigningKeysCount; } else { // correct max count according to target if target is enabled - uint64 targetLimit = exitedSigningKeysCount.add(operatorTargetStats.get(TARGET_VALIDATORS_COUNT_OFFSET)); + // targetLimit is limited to UINT64_MAX + uint256 targetLimit = Math256.min(uint256(exitedSigningKeysCount).add(operatorTargetStats.get(TARGET_VALIDATORS_COUNT_OFFSET)), UINT64_MAX); if (targetLimit > depositedSigningKeysCount) { - newMaxSigningKeysCount = uint64(Math256.min(uint256(vettedSigningKeysCount), uint256(targetLimit))); + newMaxSigningKeysCount = uint64(Math256.min(vettedSigningKeysCount, targetLimit)); } } } // else newMaxSigningKeysCount = depositedSigningKeysCount, so depositable keys count = 0 diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index 65c2f2302..2a59b9db6 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -1630,6 +1630,17 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.exitedSigningKeysCount, 1) }) + it.only('allow set large targetLimit (=UINT64_MAX)', async () => { + let firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) + assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) + + const targetLimit = toBN('0x1FFFFFFFFFFFFFFFF') // UINT64_MAX + await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, targetLimit, { from: voting }) + + firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) + assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) + }) + it.skip('respects staking limit', async () => { const [firstNodeOperatorKeysStats, secondNodeOperatorKeysStats] = await Promise.all([ app.getNodeOperatorSummary(firstNodeOperatorId), From 5f4f315c9190db7f4775687ce1c337387a1718f4 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 6 Mar 2023 01:59:26 +0400 Subject: [PATCH 121/236] Add zero deposits test to lido deposits scenario --- test/0.4.24/lido-deposit-scenarios.test.js | 36 +++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/test/0.4.24/lido-deposit-scenarios.test.js b/test/0.4.24/lido-deposit-scenarios.test.js index 182e941c8..c794e56d3 100644 --- a/test/0.4.24/lido-deposit-scenarios.test.js +++ b/test/0.4.24/lido-deposit-scenarios.test.js @@ -9,7 +9,7 @@ const { PUBKEY_LENGTH, FakeValidatorKeys, SIGNATURE_LENGTH } = require('../helpe const { GenericStub } = require('../helpers/stubs/generic.stub') contract('Lido deposit scenarios', ([staker, depositor]) => { - const CURATED_MODULE_ID = 1 + const STAKING_MODULE_ID = 1 const DEPOSIT_CALLDATA = '0x0' let lido, stakingRouter let stakingModuleStub, depositContractStub @@ -77,7 +77,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { assert.equal(await getBalance(lido), initialLidoETHBalance + unaccountedLidoETHBalance + submitAmount) const maxDepositsCount = 10 - await lido.deposit(maxDepositsCount, CURATED_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }) + await lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }) assert.equals(await getBalance(stakingRouter), initialStakingRouterBalance) const depositedEther = wei`32 ether` * wei.min(maxDepositsCount, availableValidatorsCount) @@ -114,7 +114,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { const maxDepositsCount = 10 await assert.reverts( - lido.deposit(maxDepositsCount, CURATED_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), + lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), 'InvalidPublicKeysBatchLength', [PUBKEY_LENGTH * depositDataLength, PUBKEY_LENGTH * availableValidatorsCount] ) @@ -150,7 +150,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { const maxDepositsCount = 10 await assert.reverts( - lido.deposit(maxDepositsCount, CURATED_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), + lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), 'InvalidPublicKeysBatchLength', [PUBKEY_LENGTH * depositDataLength, PUBKEY_LENGTH * availableValidatorsCount] ) @@ -186,7 +186,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { const maxDepositsCount = 10 await assert.reverts( - lido.deposit(maxDepositsCount, CURATED_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), + lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), 'InvalidSignaturesBatchLength', [SIGNATURE_LENGTH * depositDataLength, SIGNATURE_LENGTH * availableValidatorsCount] ) @@ -216,7 +216,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { return: { depositDataLength }, }) const maxDepositsCount = 10 - await assert.reverts(lido.deposit(maxDepositsCount, CURATED_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor })) + await assert.reverts(lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor })) }) it('StakingModule reverted on obtainData', async () => { @@ -239,9 +239,31 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { const maxDepositsCount = 10 await assert.reverts( - lido.deposit(maxDepositsCount, CURATED_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), + lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), 'INVALID_ALLOCATED_KEYS_COUNT' ) }) + + it('Zero deposit updates lastDepositAt and lastDepositBlock fields', async () => { + const submitAmount = wei`100 ether` + await lido.submit(ZERO_ADDRESS, { from: staker, value: wei.str(submitAmount) }) + + const availableValidatorsCount = 2 + await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { + totalExitedValidators: 5, + totalDepositedValidators: 16, + availableValidatorsCount, + }) + + const stakingModuleStateBefore = await stakingRouter.getStakingModule(STAKING_MODULE_ID) + + const maxDepositsCount = 0 + await lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }) + + const stakingModuleStateAfter = await stakingRouter.getStakingModule(STAKING_MODULE_ID) + + assert.notEquals(stakingModuleStateBefore.lastDepositAt, stakingModuleStateAfter.lastDepositAt) + assert.notEquals(stakingModuleStateBefore.lastDepositBlock, stakingModuleStateAfter.lastDepositBlock) + }) }) }) From 46769765988bbed7b0d67945defddef52cf5d0cf Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 6 Mar 2023 02:00:09 +0400 Subject: [PATCH 122/236] Add MANAGE_NODE_OPERATOR_ROLE test for updateTargetValidatorsLimit --- test/0.4.24/node-operators-registry.test.js | 55 ++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index 2a59b9db6..bc005c25a 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -1448,6 +1448,59 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) }) + describe('updateTargetValidatorsLimit()', () => { + const firstNodeOperatorId = 0 + const secondNodeOperatorId = 1 + + beforeEach(async () => { + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[firstNodeOperatorId] }, { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[secondNodeOperatorId], { from: voting }) + }) + + it('reverts with "APP_AUTH_FAILED" error when called by sender without MANAGE_NODE_OPERATOR_ROLE', async () => { + const hasPermission = await dao.hasPermission(nobody, app, 'MANAGE_NODE_OPERATOR_ROLE') + assert.isFalse(hasPermission) + const isTargetLimitSet = false + const targetLimit = 0 + await assert.reverts( + app.updateTargetValidatorsLimits(firstNodeOperatorId, isTargetLimitSet, targetLimit, { from: nobody }), + 'APP_AUTH_FAILED' + ) + }) + + it('updates node operator target limit if called by sender with MANAGE_NODE_OPERATOR_ROLE', async () => { + const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + assert.isTrue(hasPermission) + + const targetLimit = 10 + const isTargetLimitSet = true + await app.updateTargetValidatorsLimits(firstNodeOperatorId, isTargetLimitSet, targetLimit, { from: voting }) + + const keysStatTotal = await app.getStakingModuleSummary() + const expectedExitedValidatorsCount = + NODE_OPERATORS[firstNodeOperatorId].exitedSigningKeysCount + + NODE_OPERATORS[secondNodeOperatorId].exitedSigningKeysCount + assert.equals(keysStatTotal.totalExitedValidators, expectedExitedValidatorsCount) + + const expectedDepositedValidatorsCount = + NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount + + NODE_OPERATORS[secondNodeOperatorId].depositedSigningKeysCount + assert.equals(keysStatTotal.totalDepositedValidators, expectedDepositedValidatorsCount) + + const firstNodeOperatorDepositableValidators = + NODE_OPERATORS[firstNodeOperatorId].vettedSigningKeysCount - + NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount + + const secondNodeOperatorDepositableValidators = + NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - + NODE_OPERATORS[secondNodeOperatorId].depositedSigningKeysCount + + const expectedDepositableValidatorsCount = + Math.min(targetLimit, firstNodeOperatorDepositableValidators) + secondNodeOperatorDepositableValidators + assert.equals(keysStatTotal.depositableValidatorsCount, expectedDepositableValidatorsCount) + }) + }) + describe('onWithdrawalCredentialsChanged()', () => { beforeEach(async () => { await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) @@ -1630,7 +1683,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.exitedSigningKeysCount, 1) }) - it.only('allow set large targetLimit (=UINT64_MAX)', async () => { + it('allow set large targetLimit (=UINT64_MAX)', async () => { let firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) From 094a7647219a0b178b6701490c8f332cee8cfff8 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 6 Mar 2023 02:03:33 +0400 Subject: [PATCH 123/236] Remove outdated comment --- test/0.8.9/staking-router/staking-router-deposits.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/0.8.9/staking-router/staking-router-deposits.test.js b/test/0.8.9/staking-router/staking-router-deposits.test.js index f9dbfe0a2..7a5edf0dd 100644 --- a/test/0.8.9/staking-router/staking-router-deposits.test.js +++ b/test/0.8.9/staking-router/staking-router-deposits.test.js @@ -168,8 +168,6 @@ contract('StakingRouter', ([depositor, stranger]) => { }) }) - // the check for depositsValue == 0 occurs above in Lido.deposit(), so perhaps this check is redundant in SR. - // But if we untie the Lido contract from the StarkingRouter, we will need this check describe('test deposit from staking router directly', async () => { before(snapshot) after(revert) From 874fe7b5775744861337c7be65c77f16de5244b2 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Mon, 6 Mar 2023 15:07:11 +0700 Subject: [PATCH 124/236] feat: report lifecycle tests --- test/0.4.24/legacy-oracle.test.js | 77 ++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/test/0.4.24/legacy-oracle.test.js b/test/0.4.24/legacy-oracle.test.js index 92341bf61..a669f981f 100644 --- a/test/0.4.24/legacy-oracle.test.js +++ b/test/0.4.24/legacy-oracle.test.js @@ -1,14 +1,15 @@ -const { contract, ethers, artifacts } = require('hardhat') +const { contract, ethers, artifacts, web3 } = require('hardhat') const { assert } = require('../helpers/assert') const { impersonate } = require('../helpers/blockchain') - +const { e9, e18, e27 } = require('../helpers/utils') const { legacyOracleFactory } = require('../helpers/factories') const OssifiableProxy = artifacts.require('OssifiableProxy') - const LegacyOracle = artifacts.require('LegacyOracle') const MockLegacyOracle = artifacts.require('MockLegacyOracle') +const LegacyOracleAbi = require('../../lib/abi/LegacyOracle.json') + const { deployAccountingOracleSetup, initAccountingOracle, @@ -16,8 +17,32 @@ const { SLOTS_PER_EPOCH, SECONDS_PER_SLOT, GENESIS_TIME, + calcAccountingReportDataHash, + getAccountingReportDataItems, + computeTimestampAtSlot, + ZERO_HASH, + CONSENSUS_VERSION, + SLOTS_PER_FRAME, } = require('../0.8.9/oracle/accounting-oracle-deploy.test') +const getReportFields = (override = {}) => ({ + consensusVersion: CONSENSUS_VERSION, + numValidators: 10, + clBalanceGwei: e9(320), + stakingModuleIdsWithNewlyExitedValidators: [1], + numExitedValidatorsByStakingModule: [3], + withdrawalVaultBalance: e18(1), + elRewardsVaultBalance: e18(2), + sharesRequestedToBurn: e18(3), + lastFinalizableWithdrawalRequestId: 1, + simulatedShareRate: e27(1), + isBunkerMode: true, + extraDataFormat: 0, + extraDataHash: ZERO_HASH, + extraDataItemsCount: 0, + ...override, +}) + async function deployLegacyOracleWithAccountingOracle({ admin, initialEpoch = 1, lastProcessingRefSlot = 31 }) { const legacyOracle = await legacyOracleFactory({ appManager: { address: admin } }) const { locatorAddr, consensus, oracle, lido } = await deployAccountingOracleSetup(admin, { @@ -37,9 +62,8 @@ module.exports = { } contract('LegacyOracle', ([admin, stranger]) => { - let legacyOracle, accountingOracle, lido, consensus - context('Fresh deploy and puppet methods checks', () => { + let legacyOracle, accountingOracle, lido, consensus before('deploy', async () => { const deployed = await deployLegacyOracleWithAccountingOracle({ admin }) legacyOracle = deployed.legacyOracle @@ -139,6 +163,7 @@ contract('LegacyOracle', ([admin, stranger]) => { getLegacyOracle: () => { return proxyAsOldImplementation }, + dataSubmitter: admin, }) const { consensus, oracle } = deployedInfra await initAccountingOracle({ admin, oracle, consensus, shouldMigrateLegacyOracle: true }) @@ -150,6 +175,46 @@ contract('LegacyOracle', ([admin, stranger]) => { await proxyAsNewImplementation.finalizeUpgrade_v4(deployedInfra.oracle.address) }) - it.skip('lifecycle tests') + it('submit report', async () => { + await deployedInfra.consensus.advanceTimeToNextFrameStart() + const { refSlot } = await deployedInfra.consensus.getCurrentFrame() + const reportFields = getReportFields({ + refSlot: +refSlot, + }) + const reportItems = getAccountingReportDataItems(reportFields) + const reportHash = calcAccountingReportDataHash(reportItems) + await deployedInfra.consensus.addMember(admin, 1, { from: admin }) + await deployedInfra.consensus.submitReport(refSlot, reportHash, CONSENSUS_VERSION, { from: admin }) + const oracleVersion = +(await deployedInfra.oracle.getContractVersion()) + const tx = await deployedInfra.oracle.submitReportData(reportItems, oracleVersion, { from: admin }) + + const epochId = Math.floor((+refSlot + 1) / SLOTS_PER_EPOCH) + assert.emits( + tx, + 'Completed', + { + epochId, + beaconBalance: web3.utils.toWei(reportFields.clBalanceGwei, 'gwei'), + beaconValidators: reportFields.numValidators, + }, + { abi: LegacyOracleAbi } + ) + const completedEpoch = await proxyAsNewImplementation.getLastCompletedEpochId() + assert.equals(completedEpoch, epochId) + }) + + it('time in sync with consensus', async () => { + await deployedInfra.consensus.advanceTimeToNextFrameStart() + const epochId = await proxyAsNewImplementation.getCurrentEpochId() + const { frameEpochId, frameStartTime, frameEndTime } = await proxyAsNewImplementation.getCurrentFrame() + assert.equals(epochId, frameEpochId) + const consensusFrame = await deployedInfra.consensus.getCurrentFrame() + const refSlot = consensusFrame.refSlot.toNumber() + assert.equals(epochId, Math.floor((refSlot + 1) / SLOTS_PER_EPOCH)) + assert.equals(frameStartTime, computeTimestampAtSlot(refSlot + 1)) + assert.equals(frameEndTime, computeTimestampAtSlot(refSlot + 1 + SLOTS_PER_FRAME) - 1) + }) + + it.skip('handlePostTokenRebase from lido') }) }) From 8b041139281c240d3903305ce848f1f01378dfee Mon Sep 17 00:00:00 2001 From: KRogLA Date: Mon, 6 Mar 2023 11:07:24 +0100 Subject: [PATCH 125/236] test: NOR + minor fixes --- .../NodeOperatorsRegistryMock.sol | 2 +- .../0.8.9/test_helpers/StakingModuleMock.sol | 2 +- .../node-operators-registry-penalty.test.js | 16 ++++----- test/0.4.24/node-operators-registry.test.js | 34 +++++++++---------- test/0.8.9/staking-router/digest.test.js | 2 +- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol b/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol index 8f0912221..82b02a9c5 100644 --- a/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol +++ b/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol @@ -202,7 +202,7 @@ contract NodeOperatorsRegistryMock is NodeOperatorsRegistry { event ValidatorsKeysLoaded(bytes publicKeys, bytes signatures); - function testing__distributeRewards() external returns (uint256) { + function testing_distributeRewards() external returns (uint256) { return _distributeRewards(); } } diff --git a/contracts/0.8.9/test_helpers/StakingModuleMock.sol b/contracts/0.8.9/test_helpers/StakingModuleMock.sol index f6cb7fdf0..f6de118c3 100644 --- a/contracts/0.8.9/test_helpers/StakingModuleMock.sol +++ b/contracts/0.8.9/test_helpers/StakingModuleMock.sol @@ -87,7 +87,7 @@ contract StakingModuleMock is IStakingModule { function getNodeOperatorsCount() public view returns (uint256) { return nodeOperatorsCount; } - function testing__setNodeOperatorsCount(uint256 _count) external { + function testing_setNodeOperatorsCount(uint256 _count) external { nodeOperatorsCount = _count; } 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 9c810fadf..5951e9ba8 100644 --- a/test/0.4.24/node-operators-registry-penalty.test.js +++ b/test/0.4.24/node-operators-registry-penalty.test.js @@ -99,7 +99,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use ]) // calls distributeRewards() inside - await app.testing__distributeRewards({ from: voting }) + await app.testing_distributeRewards({ from: voting }) const recipientsSharesAfter = await Promise.all([ steth.sharesOf(user1), @@ -117,7 +117,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.mintShares(app.address, ETH(10)) // calls distributeRewards() inside - await app.testing__distributeRewards({ from: voting }) + await app.testing_distributeRewards({ from: voting }) assert.equals(await steth.sharesOf(user1), ETH(3)) assert.equals(await steth.sharesOf(user2), ETH(7)) @@ -129,7 +129,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await steth.mintShares(app.address, ETH(10)) // calls distributeRewards() inside - const receipt = await app.testing__distributeRewards({ from: voting }) + const 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) }) @@ -167,7 +167,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use // perValidatorShare 10*10^18 / 8 = 1250000000000000000 == 1.25 * 10^18 // calls distributeRewards() inside - const receipt = await app.testing__distributeRewards({ from: voting }) + const 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) }) @@ -207,7 +207,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use // but half goes to burner // calls distributeRewards() inside - const receipt = await app.testing__distributeRewards({ from: voting }) + const 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) }) @@ -226,7 +226,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await app.updateRefundedValidatorsCount(firstNodeOperator, 1, { from: voting }) // calls distributeRewards() inside - const receipt = await app.testing__distributeRewards({ from: voting }) + const 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) }) @@ -258,7 +258,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use await app.updateRefundedValidatorsCount(firstNodeOperator, 1, { from: voting }) // calls distributeRewards() inside - const receipt = await app.testing__distributeRewards({ from: voting }) + const 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) }) assert.notEmits(receipt, 'RewardsDistributed', { rewardAddress: user3, sharesAmount: 0 }) @@ -284,7 +284,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, use assert.isFalse(await app.testing_isNodeOperatorPenalized(firstNodeOperator)) // calls distributeRewards() inside - const receipt = await app.testing__distributeRewards({ from: voting }) + const 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/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index bc005c25a..458d058dc 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -1694,22 +1694,26 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) }) - it.skip('respects staking limit', async () => { + it('_getSigningKeysAllocationData respects staking limit', async () => { const [firstNodeOperatorKeysStats, secondNodeOperatorKeysStats] = await Promise.all([ app.getNodeOperatorSummary(firstNodeOperatorId), - app.getValidatorsKeysStats(secondNodeOperatorId), + app.getNodeOperatorSummary(secondNodeOperatorId), ]) - assert.isTrue(firstNodeOperatorKeysStats.readyToDepositValidatorsKeysCount.toNumber() > 0) - assert.isTrue(secondNodeOperatorKeysStats.readyToDepositValidatorsKeysCount.toNumber() > 0) + assert.isTrue(firstNodeOperatorKeysStats.depositableValidatorsCount.toNumber() > 0) + assert.isTrue(secondNodeOperatorKeysStats.depositableValidatorsCount.toNumber() > 0) - assert.equals(firstNodeOperatorKeysStats.exitedValidatorsCount, 1) - assert.equals(firstNodeOperatorKeysStats.activeValidatorsKeysCount, 4) - assert.equals(firstNodeOperatorKeysStats.readyToDepositValidatorsKeysCount, 3) + const firstNodeOperatorActiveKeysCount = + firstNodeOperatorKeysStats.totalDepositedValidators.toNumber() - + firstNodeOperatorKeysStats.totalExitedValidators.toNumber() + assert.equals(firstNodeOperatorActiveKeysCount, 4) + assert.equals(firstNodeOperatorKeysStats.depositableValidatorsCount, 3) - assert.equals(secondNodeOperatorKeysStats.exitedValidatorsCount, 0) - assert.equals(secondNodeOperatorKeysStats.activeValidatorsKeysCount, 5) - assert.equals(secondNodeOperatorKeysStats.readyToDepositValidatorsKeysCount, 5) + const secondNodeOperatorActiveKeysCount = + secondNodeOperatorKeysStats.totalDepositedValidators.toNumber() - + secondNodeOperatorKeysStats.totalExitedValidators.toNumber() + assert.equals(secondNodeOperatorActiveKeysCount, 5) + assert.equals(secondNodeOperatorKeysStats.depositableValidatorsCount, 5) const keysToAllocate = 7 const { allocatedKeysCount, nodeOperatorIds, activeKeyCountsAfterAllocation } = @@ -1722,15 +1726,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(activeKeyCountsAfterAllocation.length, 2) // the first node operator has to receive 3 deposits cause reached limit - assert.equals( - activeKeyCountsAfterAllocation[0], - firstNodeOperatorKeysStats.activeValidatorsKeysCount.toNumber() + 3 - ) + assert.equals(activeKeyCountsAfterAllocation[0], firstNodeOperatorActiveKeysCount + 3) // the second receives 4 deposits - assert.equals( - activeKeyCountsAfterAllocation[1], - secondNodeOperatorKeysStats.activeValidatorsKeysCount.toNumber() + 4 - ) + assert.equals(activeKeyCountsAfterAllocation[1], secondNodeOperatorActiveKeysCount + 4) }) }) diff --git a/test/0.8.9/staking-router/digest.test.js b/test/0.8.9/staking-router/digest.test.js index 75c53bb63..877eed769 100644 --- a/test/0.8.9/staking-router/digest.test.js +++ b/test/0.8.9/staking-router/digest.test.js @@ -88,7 +88,7 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { } await module1.setNodeOperatorSummary(nodeOperator1, summary) - await module1.testing__setNodeOperatorsCount(1) + await module1.testing_setNodeOperatorsCount(1) }) it('get digest with one nodeOperator', async () => { From a0b51d8ca9eb4fc7071168e51233344f74939b8a Mon Sep 17 00:00:00 2001 From: Artyom Veremeenko Date: Mon, 6 Mar 2023 15:21:14 +0400 Subject: [PATCH 126/236] feature: add pauseUntil(resumeSince) in addition to pause(duration) --- contracts/0.8.9/WithdrawalQueue.sol | 14 ++++++++++++-- .../0.8.9/oracle/ValidatorsExitBusOracle.sol | 11 +++++++++-- .../PausableUntilPrivateExposed.sol | 2 +- contracts/0.8.9/utils/PausableUntil.sol | 19 ++++++++++++++----- lib/abi/ValidatorsExitBusOracle.json | 2 +- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 7 files changed, 39 insertions(+), 13 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 1f190a64d..241f5efed 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -104,8 +104,18 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @notice Pause withdrawal requests placement and finalization. Claiming finalized requests will still be available /// @param _duration pause duration, seconds (use `PAUSE_INFINITELY` for unlimited) + /// @dev Reverts with `ResumedExpected()` if contract is already paused + /// @dev Reverts with `AccessControl:...` reason if sender has no `PAUSE_ROLE` + /// @dev Reverts with `ZeroPauseDuration()` if zero duration is passed function pause(uint256 _duration) external onlyRole(PAUSE_ROLE) { - _pause(_duration); + _pauseFor(_duration); + } + + /// @notice Pause withdrawal requests placement and finalization. Claiming finalized requests will still be available + /// @param _resumeSince the first second to resume since + /// @dev Reverts with `ResumeSinceInPast()` if the timestamp is in the past + function pauseUntil(uint256 _resumeSince) external onlyRole(PAUSE_ROLE) { + _pauseUntil(_resumeSince); } /// @notice Request the sequence of stETH withdrawals according to passed `withdrawalRequestInputs` data @@ -361,7 +371,7 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit internal { _initializeQueue(); - _pause(PAUSE_INFINITELY); + _pauseFor(PAUSE_INFINITELY); _initializeContractVersionTo(1); diff --git a/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol b/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol index 585e1323d..295321808 100644 --- a/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol +++ b/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol @@ -105,7 +105,7 @@ contract ValidatorsExitBusOracle is BaseOracle, PausableUntil { if (admin == address(0)) revert AdminCannotBeZero(); _setupRole(DEFAULT_ADMIN_ROLE, admin); - _pause(PAUSE_INFINITELY); + _pauseFor(PAUSE_INFINITELY); _initialize(consensusContract, consensusVersion, lastProcessingRefSlot); } @@ -126,7 +126,14 @@ contract ValidatorsExitBusOracle is BaseOracle, PausableUntil { /// @dev Reverts with `ZeroPauseDuration()` if zero duration is passed /// function pause(uint256 _duration) external onlyRole(PAUSE_ROLE) { - _pause(_duration); + _pauseFor(_duration); + } + + /// @notice Pause withdrawal requests placement and finalization. Claiming finalized requests will still be available + /// @param _resumeSince the first second to resume since + /// @dev Reverts with `ResumeSinceInPast()` if the timestamp is in the past + function pauseUntil(uint256 _resumeSince) external onlyRole(PAUSE_ROLE) { + _pauseUntil(_resumeSince); } /// diff --git a/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol b/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol index acf1d7973..ed86baf14 100644 --- a/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol +++ b/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol @@ -21,7 +21,7 @@ contract PausableUntilPrivateExposed is PausableUntil { } function pause(uint256 _duration) external { - _pause(_duration); + _pauseFor(_duration); } } diff --git a/contracts/0.8.9/utils/PausableUntil.sol b/contracts/0.8.9/utils/PausableUntil.sol index 0fe8a8356..8dc5e88d7 100644 --- a/contracts/0.8.9/utils/PausableUntil.sol +++ b/contracts/0.8.9/utils/PausableUntil.sol @@ -21,6 +21,7 @@ contract PausableUntil { error ZeroPauseDuration(); error PausedExpected(); error ResumedExpected(); + error ResumeSinceInPast(); /// @notice Reverts when resumed modifier whenPaused() { @@ -57,18 +58,26 @@ contract PausableUntil { emit Resumed(); } - function _pause(uint256 _duration) internal whenResumed { + function _pauseFor(uint256 _duration) internal whenResumed { if (_duration == 0) revert ZeroPauseDuration(); - uint256 pausedUntil; + uint256 resumeSince; if (_duration == PAUSE_INFINITELY) { - pausedUntil = PAUSE_INFINITELY; + resumeSince = PAUSE_INFINITELY; } else { - pausedUntil = block.timestamp + _duration; + resumeSince = block.timestamp + _duration; } - RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(pausedUntil); + RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(resumeSince); emit Paused(_duration); } + + function _pauseUntil(uint256 _resumeSince) internal whenResumed { + if (_resumeSince < block.timestamp) revert ResumeSinceInPast(); + + RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(_resumeSince); + + emit Paused(_resumeSince - block.timestamp); + } } diff --git a/lib/abi/ValidatorsExitBusOracle.json b/lib/abi/ValidatorsExitBusOracle.json index 8a8260583..a5b3bedbf 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":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":[],"name":"getResumeSinceTimestamp","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":"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":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":"ResumeSinceInPast","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":[],"name":"getResumeSinceTimestamp","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":"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":"uint256","name":"_resumeSince","type":"uint256"}],"name":"pauseUntil","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/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 630bba300..1f7507407 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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":"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":[],"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":[{"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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":"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":[],"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_resumeSince","type":"uint256"}],"name":"pauseUntil","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 728ac3391..ce3c1a5a4 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.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":"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":[],"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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":"uint256","name":"_resumeSince","type":"uint256"}],"name":"pauseUntil","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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 2a1fb0f781b64bdc9e315bf32d2e0a328fd60899 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 11:35:51 +0300 Subject: [PATCH 127/236] chore: restrict visibility as compiler warns --- contracts/0.8.9/StakingRouter.sol | 2 +- contracts/0.8.9/oracle/AccountingOracle.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index e35d8c831..b03255f4e 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -1027,7 +1027,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version function _checkValidatorsByNodeOperatorReportData( bytes calldata _nodeOperatorIds, bytes calldata _validatorsCounts - ) internal { + ) internal pure { if (_nodeOperatorIds.length % 8 != 0 || _validatorsCounts.length % 16 != 0) { revert InvalidReportData(3); } diff --git a/contracts/0.8.9/oracle/AccountingOracle.sol b/contracts/0.8.9/oracle/AccountingOracle.sol index e5357b444..fb4e6cd0c 100644 --- a/contracts/0.8.9/oracle/AccountingOracle.sol +++ b/contracts/0.8.9/oracle/AccountingOracle.sol @@ -692,7 +692,7 @@ contract AccountingOracle is BaseOracle { } function _checkCanSubmitExtraData(ExtraDataProcessingState memory procState, uint256 format) - internal + internal view { _checkMsgSenderIsAllowedToSubmitData(); _checkProcessingDeadline(); From 001e97d79d94f25e9d5db43a4a8d12761995d9e9 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 27 Feb 2023 11:36:25 +0300 Subject: [PATCH 128/236] chore: visible broken ABI err for pre-commit hook --- .husky/pre-commit | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index c79d6bcc2..b63c34415 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,7 +1,10 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" +RED_COLOR='\033[0;31m' +NO_COLOR='\033[0m' + yarn compile -git diff --quiet lib/abi +git diff --quiet lib/abi || (echo -e "${RED_COLOR}Unstaged ABIs detected${NO_COLOR}"; exit 1) yarn lint From 083efa3e89b231b3fa48a66819001d3ab8bb0689 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 27 Feb 2023 14:40:22 +0200 Subject: [PATCH 129/236] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F:=20optimize=20WQ?= =?UTF-8?q?=20contract=20size=20-=20remove=20roles=20from=20initializer=20?= =?UTF-8?q?-=20remove=20wsteth=20related=20methods=20-=20remove=20findChec?= =?UTF-8?q?kpointHintsUnbounded?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueue.sol | 98 +++------------------- contracts/0.8.9/WithdrawalQueueERC721.sol | 6 +- lib/abi/IWstETH.json | 1 - lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- test/0.8.9/withdrawal-queue-deploy.test.js | 5 +- test/0.8.9/withdrawal-request-nft.test.js | 4 +- test/helpers/factories.js | 4 +- test/helpers/withdrawals.js | 4 +- test/scenario/helpers/deploy.js | 4 +- 10 files changed, 22 insertions(+), 108 deletions(-) delete mode 100644 lib/abi/IWstETH.json diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 1f190a64d..4faf17b60 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -21,14 +21,6 @@ interface IStETH is IERC20, IERC20Permit { function getSharesByPooledEth(uint256 _pooledEthAmount) external view returns (uint256); } -/// @notice Interface defining a Lido liquid staking pool wrapper -/// @dev see WstETH.sol for full docs -interface IWstETH is IERC20, IERC20Permit { - function unwrap(uint256 _wstETHAmount) external returns (uint256); - function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); - function stETH() external view returns (IStETH); -} - /// @title A contract for handling stETH withdrawal request queue within the Lido protocol /// @author folkyatina abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, WithdrawalQueueBase, Versioned { @@ -57,12 +49,10 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit uint256 public constant MAX_STETH_WITHDRAWAL_AMOUNT = 1000 * 1e18; /// @notice Lido stETH token address to be set upon construction - IStETH public immutable STETH; - /// @notice Lido wstETH token address to be set upon construction - IWstETH public immutable WSTETH; + IStETH internal immutable STETH; /// @notice Emitted when the contract initialized - event InitializedV1(address _admin, address _pauser, address _resumer, address _finalizer, address _bunkerReporter); + event InitializedV1(address _admin); event BunkerModeEnabled(uint256 _sinceTimestamp); event BunkerModeDisabled(); @@ -73,28 +63,23 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit error RequestIdsNotSorted(); error ZeroRecipient(); - /// @param _wstETH address of WstETH contract - constructor(IWstETH _wstETH) { + /// @param _stETH address of stETH contract + constructor(address _stETH) { // init immutables - WSTETH = _wstETH; - STETH = WSTETH.stETH(); + STETH = IStETH(_stETH); } /// @notice Initialize the contract storage explicitly. /// @param _admin admin address that can change every role. - /// @param _pauser address that will be able to pause the withdrawals - /// @param _resumer address that will be able to resume the withdrawals after pause - /// @param _finalizer address that can finalize requests in the queue - /// @param _bunkerReporter address that can report a bunker mode /// @dev Reverts if `_admin` equals to `address(0)` /// @dev NB! It's initialized in paused state by default and should be resumed explicitly to start /// @dev NB! Bunker mode is disabled by default - function initialize(address _admin, address _pauser, address _resumer, address _finalizer, address _bunkerReporter) + function initialize(address _admin) external { if (_admin == address(0)) revert AdminZeroAddress(); - _initialize(_admin, _pauser, _resumer, _finalizer, _bunkerReporter); + _initialize(_admin); } /// @notice Resume withdrawal requests placement and finalization @@ -127,24 +112,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } } - /// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data - /// @param amounts an array of stETH amount values. The standalone withdrawal request will - /// be created for each item in the passed list. - /// @param _owner address that will be able to transfer or claim the request. - /// If `owner` is set to `address(0)`, `msg.sender` will be used as owner. - /// @return requestIds an array of the created withdrawal requests - function requestWithdrawalsWstETH(uint256[] calldata amounts, address _owner) - public - whenResumed - returns (uint256[] memory requestIds) - { - if (_owner == address(0)) _owner = msg.sender; - requestIds = new uint256[](amounts.length); - for (uint256 i = 0; i < amounts.length; ++i) { - requestIds[i] = _requestWithdrawalWstETH(amounts[i], _owner); - } - } - struct PermitInput { uint256 value; uint256 deadline; @@ -170,23 +137,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit return requestWithdrawals(_amounts, _owner); } - /// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data - /// using EIP-2612 Permit - /// @param _amounts an array of stETH amount values. The standalone withdrawal request will - /// be created for each item in the passed list. - /// @param _owner address that will be able to transfer or claim the request. - /// If `owner` is set to `address(0)`, `msg.sender` will be used as owner. - /// @param _permit data required for the wstETH.permit() method to set the allowance - /// @return requestIds an array of the created withdrawal requests - function requestWithdrawalsWstETHWithPermit( - uint256[] calldata _amounts, - address _owner, - PermitInput calldata _permit - ) external whenResumed returns (uint256[] memory requestIds) { - WSTETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s); - return requestWithdrawalsWstETH(_amounts, _owner); - } - /// @notice Returns all withdrawal requests that belongs to the `_owner` address /// /// WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed @@ -280,7 +230,7 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @param _lastIndex right boundary of the search range /// @return hintIds the hints for `claimWithdrawal` to find the checkpoint for the passed request ids function findCheckpointHints(uint256[] calldata _requestIds, uint256 _firstIndex, uint256 _lastIndex) - public + external view returns (uint256[] memory hintIds) { @@ -294,18 +244,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } } - /// @notice Finds the list of hints for the given `_requestIds` searching among the checkpoints with indices - /// in the range `[1, lastCheckpointIndex]`. NB! Array of request ids should be sorted - /// @dev WARNING! OOG is possible if used onchain. - /// @param _requestIds ids of the requests sorted in the ascending order to get hints for - function findCheckpointHintsUnbounded(uint256[] calldata _requestIds) - public - view - returns (uint256[] memory hintIds) - { - return findCheckpointHints(_requestIds, 1, getLastCheckpointIndex()); - } - /// @notice Finalize requests from last finalized one up to `_lastRequestIdToFinalize` /// @dev ether to finalize all the requests should be calculated using `finalizationBatch()` and sent along /// @@ -357,7 +295,7 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit function _emitTransfer(address from, address to, uint256 _requestId) internal virtual; /// @dev internal initialization helper. Doesn't check provided addresses intentionally - function _initialize(address _admin, address _pauser, address _resumer, address _finalizer, address _bunkerReporter) + function _initialize(address _admin) internal { _initializeQueue(); @@ -366,14 +304,10 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit _initializeContractVersionTo(1); _grantRole(DEFAULT_ADMIN_ROLE, _admin); - if (_pauser != address(0)) _grantRole(PAUSE_ROLE, _pauser); - if (_resumer != address(0)) _grantRole(RESUME_ROLE, _resumer); - if (_finalizer != address(0)) _grantRole(FINALIZE_ROLE, _finalizer); - if (_bunkerReporter != address(0)) _grantRole(BUNKER_MODE_REPORT_ROLE, _bunkerReporter); BUNKER_MODE_SINCE_TIMESTAMP_POSITION.setStorageUint256(BUNKER_MODE_DISABLED_TIMESTAMP); - emit InitializedV1(_admin, _pauser, _resumer, _finalizer, _bunkerReporter); + emit InitializedV1(_admin); } function _requestWithdrawal(uint256 _amountOfStETH, address _owner) internal returns (uint256 requestId) { @@ -386,18 +320,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit _emitTransfer(address(0), _owner, requestId); } - function _requestWithdrawalWstETH(uint256 _amountOfWstETH, address _owner) internal returns (uint256 requestId) { - WSTETH.transferFrom(msg.sender, address(this), _amountOfWstETH); - uint256 amountOfStETH = WSTETH.unwrap(_amountOfWstETH); - _checkWithdrawalRequestAmount(amountOfStETH); - - uint256 amountOfShares = STETH.getSharesByPooledEth(amountOfStETH); - - requestId = _enqueue(uint128(amountOfStETH), uint128(amountOfShares), _owner); - - _emitTransfer(address(0), _owner, requestId); - } - function _checkWithdrawalRequestAmount(uint256 _amountOfStETH) internal pure { if (_amountOfStETH < MIN_STETH_WITHDRAWAL_AMOUNT) { revert RequestAmountTooSmall(_amountOfStETH); diff --git a/contracts/0.8.9/WithdrawalQueueERC721.sol b/contracts/0.8.9/WithdrawalQueueERC721.sol index e22d8201f..d15150c39 100644 --- a/contracts/0.8.9/WithdrawalQueueERC721.sol +++ b/contracts/0.8.9/WithdrawalQueueERC721.sol @@ -13,7 +13,7 @@ import {EnumerableSet} from "@openzeppelin/contracts-v4.4/utils/structs/Enumerab import {Address} from "@openzeppelin/contracts-v4.4/utils/Address.sol"; import {Strings} from "@openzeppelin/contracts-v4.4/utils/Strings.sol"; -import {IWstETH, WithdrawalQueue} from "./WithdrawalQueue.sol"; +import {WithdrawalQueue} from "./WithdrawalQueue.sol"; import {AccessControlEnumerable} from "./utils/access/AccessControlEnumerable.sol"; import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; @@ -73,10 +73,10 @@ contract WithdrawalQueueERC721 is IERC721Metadata, WithdrawalQueue { bytes32 private immutable NAME; bytes32 private immutable SYMBOL; - /// @param _wstETH address of WstETH contract + /// @param _stETH address of WstETH contract /// @param _name IERC721Metadata name string. Should be shorter than 32 bytes /// @param _symbol IERC721Metadata symbol string. Should be shorter than 32 bytes - constructor(address _wstETH, string memory _name, string memory _symbol) WithdrawalQueue(IWstETH(_wstETH)) { + constructor(address _stETH, string memory _name, string memory _symbol) WithdrawalQueue(_stETH) { if (bytes(_name).length == 0 || bytes(_symbol).length == 0) revert ZeroMetadata(); NAME = _toBytes32(_name); SYMBOL = _toBytes32(_symbol); diff --git a/lib/abi/IWstETH.json b/lib/abi/IWstETH.json deleted file mode 100644 index b034090cf..000000000 --- a/lib/abi/IWstETH.json +++ /dev/null @@ -1 +0,0 @@ -[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"getStETHByWstETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"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"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"unwrap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 630bba300..107f524ef 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"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":"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":[],"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":[],"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":[{"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 728ac3391..184369ced 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.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":"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":[],"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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"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":[],"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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":[{"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index e9ab7a2f4..8831ecb93 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -6,7 +6,6 @@ const withdrawals = require('../helpers/withdrawals') const { assert } = require('../helpers/assert') const StETHMock = artifacts.require('StETHPermitMock.sol') -const WstETH = artifacts.require('WstETHMock.sol') const EIP712StETH = artifacts.require('EIP712StETH') const NFTDescriptorMock = artifacts.require('NFTDescriptorMock.sol') @@ -27,11 +26,10 @@ async function deployWithdrawalQueue({ }) { const nftDescriptor = await NFTDescriptorMock.new(NFT_DESCRIPTOR_BASE_URI) const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) - const wsteth = await WstETH.new(steth.address, { from: stethOwner }) const eip712StETH = await EIP712StETH.new(steth.address, { from: stethOwner }) await steth.initializeEIP712StETH(eip712StETH.address) - const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, wsteth.address, queueName, symbol) + const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, steth.address, queueName, symbol) const initTx = await withdrawalQueue.initialize( queueAdmin, @@ -48,7 +46,6 @@ async function deployWithdrawalQueue({ return { initTx, steth, - wsteth, withdrawalQueue, nftDescriptor, } diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index 747f3c7e6..0ee2e8d7a 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -7,7 +7,6 @@ const { shares, ETH, shareRate } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') const StETH = artifacts.require('StETHMock') -const WstETH = artifacts.require('WstETHMock') const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock') contract('WithdrawalNFT', (addresses) => { @@ -20,9 +19,8 @@ contract('WithdrawalNFT', (addresses) => { stETH = await StETH.new({ value: ETH(1), from: deployer }) await setBalance(stETH.address, ETH(100)) - wstETH = await WstETH.new(stETH.address, { from: deployer }) erc721ReceiverMock = await ERC721ReceiverMock.new({ from: deployer }) - withdrawalQueueERC721 = (await withdrawals.deploy(deployer, wstETH.address, 'Lido TEST Request', 'unstEsT')).queue + withdrawalQueueERC721 = (await withdrawals.deploy(deployer, stETH.address, 'Lido TEST Request', 'unstEsT')).queue await withdrawalQueueERC721.initialize( deployer, // owner deployer, // pauser diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 6a7a5832b..102926327 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -260,8 +260,8 @@ async function elRewardsVaultFactory({ pool, treasury }) { return await LidoExecutionLayerRewardsVault.new(pool.address, treasury.address) } -async function withdrawalQueueFactory({ appManager, oracle, wsteth }) { - const withdrawalQueue = (await withdrawals.deploy(appManager.address, wsteth.address)).queue +async function withdrawalQueueFactory({ appManager, oracle, pool }) { + const withdrawalQueue = (await withdrawals.deploy(appManager.address, pool.address)).queue await withdrawalQueue.initialize( appManager.address, diff --git a/test/helpers/withdrawals.js b/test/helpers/withdrawals.js index 0413bd2f5..1c4bc53bf 100644 --- a/test/helpers/withdrawals.js +++ b/test/helpers/withdrawals.js @@ -3,8 +3,8 @@ const { artifacts } = require('hardhat') const OssifiableProxy = artifacts.require('OssifiableProxy.sol') const WithdrawalQueueERC721 = artifacts.require('WithdrawalQueueERC721Mock.sol') -async function deploy(ownerAddress, wstethAddress, name = 'Lido: Withdrawal Request NFT', symbol = 'unstETH') { - const impl = await WithdrawalQueueERC721.new(wstethAddress, name, symbol) +async function deploy(ownerAddress, stethAddress, name = 'Lido: Withdrawal Request NFT', symbol = 'unstETH') { + const impl = await WithdrawalQueueERC721.new(stethAddress, name, symbol) const proxy = await OssifiableProxy.new(impl.address, ownerAddress, '0x') const queue = await WithdrawalQueueERC721.at(proxy.address) diff --git a/test/scenario/helpers/deploy.js b/test/scenario/helpers/deploy.js index 633bd0c27..52a9bb416 100644 --- a/test/scenario/helpers/deploy.js +++ b/test/scenario/helpers/deploy.js @@ -4,7 +4,6 @@ const withdrawals = require('../../helpers/withdrawals') const { newDao, newApp } = require('../../0.4.24/helpers/dao') const Lido = artifacts.require('LidoMock.sol') -const WstETH = artifacts.require('WstETH.sol') const LidoELRewardsVault = artifacts.require('LidoExecutionLayerRewardsVault.sol') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') const OracleMock = artifacts.require('AccountingOracleMock.sol') @@ -132,8 +131,7 @@ async function deployDaoAndPool(appManager, voting) { const eip712StETH = await EIP712StETH.new({ from: appManager }) - const wsteth = await WstETH.new(pool.address) - const withdrawalQueue = (await withdrawals.deploy(appManager, wsteth.address)).queue + const withdrawalQueue = (await withdrawals.deploy(appManager, pool.address)).queue await pool.initialize( oracleMock.address, From a0956dcbae720b7c3c5e309edb10b39128cea2a5 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Mon, 27 Feb 2023 17:56:24 +0200 Subject: [PATCH 130/236] tests: fix WQ scenario test setup broken by the latest changes --- test/helpers/factories.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 102926327..26ccad6ae 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -263,17 +263,18 @@ async function elRewardsVaultFactory({ pool, treasury }) { async function withdrawalQueueFactory({ appManager, oracle, pool }) { const withdrawalQueue = (await withdrawals.deploy(appManager.address, pool.address)).queue - await withdrawalQueue.initialize( - appManager.address, - appManager.address, - appManager.address, - appManager.address, - appManager.address - ) + await withdrawalQueue.initialize(appManager.address) const BUNKER_MODE_REPORT_ROLE = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() await withdrawalQueue.grantRole(BUNKER_MODE_REPORT_ROLE, oracle.address, { from: appManager.address }) + await grantRoles({ + by: appManager.address, + on: withdrawalQueue, + to: appManager.address, + roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'BUNKER_MODE_REPORT_ROLE'] + }) + return withdrawalQueue } @@ -363,6 +364,12 @@ async function postSetup({ await pool.resumeProtocolAndStaking({ from: voting.address }) } +async function grantRoles({by, on, to, roles}) { + await Promise.all(roles.map(async (role) => { + await on.grantRole(await on[role](), to, { from: by }) + })) +} + module.exports = { appManagerFactory, treasuryFactory, @@ -392,4 +399,5 @@ module.exports = { oracleReportSanityCheckerFactory, validatorExitBusFactory, oracleReportSanityCheckerStubFactory, + grantRoles, } From 189835996eb7e9f2a033ce636833eee9c542dc2d Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 13:21:48 +0200 Subject: [PATCH 131/236] =?UTF-8?q?=F0=9F=92=85:=20fix=20prettier=20lint?= =?UTF-8?q?=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/helpers/factories.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 26ccad6ae..0fa7ebcae 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -272,7 +272,7 @@ async function withdrawalQueueFactory({ appManager, oracle, pool }) { by: appManager.address, on: withdrawalQueue, to: appManager.address, - roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'BUNKER_MODE_REPORT_ROLE'] + roles: ['PAUSE_ROLE', 'RESUME_ROLE', 'FINALIZE_ROLE', 'BUNKER_MODE_REPORT_ROLE'], }) return withdrawalQueue @@ -364,10 +364,12 @@ async function postSetup({ await pool.resumeProtocolAndStaking({ from: voting.address }) } -async function grantRoles({by, on, to, roles}) { - await Promise.all(roles.map(async (role) => { - await on.grantRole(await on[role](), to, { from: by }) - })) +async function grantRoles({ by, on, to, roles }) { + await Promise.all( + roles.map(async (role) => { + await on.grantRole(await on[role](), to, { from: by }) + }) + ) } module.exports = { From 36b9f854a5d2fb23ad9a6d3810e483d11a93878f Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 13:30:09 +0200 Subject: [PATCH 132/236] test: fix initialization tests --- test/0.8.9/withdrawal-queue-deploy.test.js | 74 ++++------------------ 1 file changed, 11 insertions(+), 63 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 8831ecb93..4c7a4797b 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -31,12 +31,17 @@ async function deployWithdrawalQueue({ const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, steth.address, queueName, symbol) - const initTx = await withdrawalQueue.initialize( - queueAdmin, - queuePauser || queueAdmin, - queueResumer || queueAdmin, - queueFinalizer || steth.address, - queueBunkerReporter || steth.address + const initTx = await withdrawalQueue.initialize(queueAdmin) + + await withdrawalQueue.grantRole(await withdrawalQueue.FINALIZE_ROLE(), queueFinalizer || steth.address, { + from: queueAdmin, + }) + await withdrawalQueue.grantRole(await withdrawalQueue.PAUSE_ROLE(), queuePauser || queueAdmin, { from: queueAdmin }) + await withdrawalQueue.grantRole(await withdrawalQueue.RESUME_ROLE(), queueResumer || queueAdmin, { from: queueAdmin }) + await withdrawalQueue.grantRole( + await withdrawalQueue.BUNKER_MODE_REPORT_ROLE(), + queueBunkerReporter || steth.address, + { from: queueAdmin } ) if (doResume) { @@ -99,10 +104,6 @@ contract( }) assert.emits(initTx, 'InitializedV1', { _admin: queueAdmin, - _pauser: queuePauser, - _resumer: queueResumer, - _finalizer: queueFinalizer, - _bunkerReporter: queueBunkerReporter, }) }) @@ -147,59 +148,6 @@ contract( 'ZeroMetadata()' ) }) - - context('no roles for zero addresses', () => { - it('check if pauser is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser: ZERO_ADDRESS, - queueResumer, - }) - const role = await withdrawalQueue.PAUSE_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - - it('check if pauser is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser, - queueResumer: ZERO_ADDRESS, - doResume: false, - }) - const role = await withdrawalQueue.RESUME_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - - it('check if finalizer is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser, - queueResumer, - queueFinalizer: ZERO_ADDRESS, - }) - const role = await withdrawalQueue.FINALIZE_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - - it('check if bunker reporter is zero', async () => { - const { withdrawalQueue } = await deployWithdrawalQueue({ - stethOwner, - queueAdmin, - queuePauser, - queueResumer, - queueBunkerReporter: ZERO_ADDRESS, - }) - const role = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() - const memberCount = await withdrawalQueue.getRoleMemberCount(role) - assert.equals(memberCount, 0) - }) - }) }) } ) From 56997385c96463fced15d47198abde7f0b49d647 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 15:55:43 +0200 Subject: [PATCH 133/236] test: add test 2 requests 2 batches --- ...ithdrawal-queue-share-rate-changes.test.js | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index b860af6bc..959db8d68 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -41,7 +41,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { await snapshot() }) - context(`multiple requests with diff entry share rate`, async () => { + context(`2 requests with diff share rate, maxShareRate == shareRate(1)`, async () => { /// /// invariant 1: all requests in the same batch should be finalized using the same share rate /// @@ -97,4 +97,73 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { assert.isClose(claimableEther[1], e18(1), 10) }) }) + + context(`2 requests 2 batches, shareRate(2) > maxShareRate > shareRate(1)`, async () => { + /// + /// invariant 1: all requests in the same batch should be finalized using the same share rate + /// + /// invariant 2: a withdrawal request cannot be finalized using a lower share rate than the + /// minimum share rate that was reported by the oracle since the last oracle report before + /// the request was added to the queue + /// + after(rollback) + + const requestIds = [0, 0] + + it(`share rate 1.0: a user requests a withdrawal of 1 stETH (10**18 shares)`, async () => { + const tx = await queue.requestWithdrawals([e18(1)], user, { from: user }) + requestIds[0] = +getFirstEventArgs(tx, 'WithdrawalRequested').requestId + assert.equals(await queue.unfinalizedStETH(), e18(1)) + }) + + it(`protocol receives rewards, changing share rate to 2.0`, async () => { + await queue.onPreRebase() + await setShareRate(2) + }) + + it(`share rate 2.0: a user requests a withdrawal of 2 stETH (10**18 shares)`, async () => { + const tx = await queue.requestWithdrawals([e18(2)], user, { from: user }) + requestIds[1] = +getFirstEventArgs(tx, 'WithdrawalRequested').requestId + assert.equals(await queue.unfinalizedStETH(), e18(3)) + }) + + it(`protocol receives slashing, changing share rate to 1.0`, async () => { + await queue.onPreRebase() + await setShareRate(1) + }) + + let batches + const maxShareRate = e27(1.5) + + it(`both requests can be finalized with 2 ETH`, async () => { + const result = await queue.calculateFinalizationBatches(maxShareRate, MAX_UINT256, [e18(2.5), false, []]) + assert.isTrue(result.finished) + + console.log(result) + + const batch = await queue.prefinalize.call(result.batches, maxShareRate) + assert.equals(batch.ethToLock, e18(2.5)) + assert.equals(batch.sharesToBurn, e18(2)) + + batches = result.batches + }) + + let claimableEther + + it(`requests get finalized`, async () => { + await queue.finalize(batches, maxShareRate, { from: finalizer, value: e18(2.5) }) + assert.equals(await queue.getLastFinalizedRequestId(), requestIds[1]) + + const hints = await queue.findCheckpointHints(requestIds, 1, await queue.getLastCheckpointIndex()) + claimableEther = await queue.getClaimableEther(requestIds, hints) + }) + + it(`first request is fullfilled with 1 ETH`, async () => { + assert.isClose(claimableEther[0], e18(1), 10) + }) + + it(`second request is fullfilled with 1 ETH`, async () => { + assert.isClose(claimableEther[1], e18(1.5), 10) + }) + }) }) From 02f9c7960124f152c62a863d366bec96a1625819 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 28 Feb 2023 16:37:15 +0200 Subject: [PATCH 134/236] test: remove withdrawal tests for wsteth --- test/0.8.9/withdrawal-queue.test.js | 135 +--------------------------- 1 file changed, 3 insertions(+), 132 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 82bda3c98..d2a5d2013 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -3,14 +3,14 @@ const { bn, getEventArgument, ZERO_ADDRESS, ZERO_BYTES32 } = require('@aragon/co const { ETH, StETH, shareRate, shares } = require('../helpers/utils') const { assert } = require('../helpers/assert') -const { signPermit, makeDomainSeparator } = require('../0.6.12/helpers/permit_helpers') +const { signPermit } = require('../0.6.12/helpers/permit_helpers') const { MAX_UINT256, ACCOUNTS_AND_KEYS } = require('../0.6.12/helpers/constants') const { impersonate, EvmSnapshot, getCurrentBlockTimestamp, setBalance } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, bunkerReporter]) => { - let withdrawalQueue, steth, wsteth + let withdrawalQueue, steth const snapshot = new EvmSnapshot(ethers.provider) @@ -23,7 +23,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) steth = deployed.steth - wsteth = deployed.wsteth withdrawalQueue = deployed.withdrawalQueue await steth.setTotalPooledEther(ETH(600)) @@ -70,20 +69,12 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.pause(100000000, { from: daoAgent }) assert(await withdrawalQueue.isPaused()) await assert.reverts(withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }), 'ResumedExpected()') - await assert.reverts( - withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], owner, { from: user }), - 'ResumedExpected()' - ) const stubPermit = [0, 0, ZERO_BYTES32, ZERO_BYTES32, ZERO_BYTES32] await assert.reverts( withdrawalQueue.requestWithdrawalsWithPermit([ETH(1)], owner, stubPermit, { from: user }), 'ResumedExpected()' ) - await assert.reverts( - withdrawalQueue.requestWithdrawalsWstETHWithPermit([ETH(1)], owner, stubPermit, { from: user }), - 'ResumedExpected()' - ) - await assert.reverts(withdrawalQueue.finalize(1, { from: owner }), 'ResumedExpected()') + await assert.reverts(withdrawalQueue.finalize(1, 0, { from: owner }), 'ResumedExpected()') }) it('cant resume if not paused', async () => { @@ -262,10 +253,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const PAUSE_INFINITELY = await withdrawalQueue.PAUSE_INFINITELY() await withdrawalQueue.pause(PAUSE_INFINITELY, { from: daoAgent }) await assert.reverts(withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), 'ResumedExpected()') - await assert.reverts( - withdrawalQueue.requestWithdrawalsWstETH([ETH(300)], owner, { from: user }), - 'ResumedExpected()' - ) }) it('data is being accumulated properly', async () => { @@ -1061,39 +1048,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) - context('findCheckpointHintsUnbounded()', () => { - let requestId - const amount = ETH(20) - - beforeEach('Enqueue a request', async () => { - await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - requestId = await withdrawalQueue.getLastRequestId() - }) - - it('returns correct hints array for given request ids', async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(20) }) - - await steth.mintShares(owner, shares(1)) - await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) - - const secondRequestAmount = ETH(10) - await withdrawalQueue.requestWithdrawals([secondRequestAmount], owner, { from: owner }) - const secondRequestId = await withdrawalQueue.getLastRequestId() - - const thirdRequestAmount = ETH(30) - await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) - const thirdRequestId = await withdrawalQueue.getLastRequestId() - - await withdrawalQueue.finalize(thirdRequestId, { from: steth.address, value: ETH(40) }) - - const hints = await withdrawalQueue.findCheckpointHintsUnbounded([requestId, secondRequestId, thirdRequestId]) - assert.equal(hints.length, 3) - assert.equals(hints[0], 1) - assert.equals(hints[1], 1) - assert.equals(hints[2], 1) - }) - }) - context('claimWithdrawals()', () => { const amount = ETH(20) @@ -1133,89 +1087,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) - context('requestWithdrawalsWstETH()', () => { - it('works correctly with non empty payload and different tokens', async () => { - await wsteth.mint(user, ETH(100)) - await steth.mintShares(wsteth.address, shares(100)) - await steth.mintShares(user, shares(100)) - await wsteth.approve(withdrawalQueue.address, ETH(300), { from: user }) - const requests = [ETH(10), ETH(20)] - const wstETHBalanceBefore = await wsteth.balanceOf(user) - const lastRequestIdBefore = await withdrawalQueue.getLastRequestId() - - await withdrawalQueue.requestWithdrawalsWstETH(requests, stranger, { from: user }) - - assert.equals(await withdrawalQueue.getLastRequestId(), lastRequestIdBefore.add(bn(requests.length))) - const wstETHBalanceAfter = await wsteth.balanceOf(user) - assert.equals(wstETHBalanceAfter, wstETHBalanceBefore.sub(bn(requests[0])).sub(bn(requests[1]))) - }) - - it('uses sender address as owner if zero passed', async () => { - await wsteth.mint(user, ETH(1)) - await steth.mintShares(wsteth.address, shares(1)) - await steth.mintShares(user, shares(1)) - await wsteth.approve(withdrawalQueue.address, ETH(1), { from: user }) - - const tx = await withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], ZERO_ADDRESS, { from: user }) - - assert.emits(tx, 'WithdrawalRequested', { - requestId: 1, - requestor: user.toLowerCase(), - owner: user.toLowerCase(), - amountOfStETH: await steth.getPooledEthByShares(ETH(1)), - amountOfShares: shares(1), - }) - }) - }) - - context('requestWithdrawalsWstETHWithPermit()', () => { - const [alice] = ACCOUNTS_AND_KEYS - it('works correctly with non empty payload', async () => { - await wsteth.mint(user, ETH(100)) - await steth.mintShares(wsteth.address, shares(100)) - await steth.mintShares(user, shares(100)) - await wsteth.approve(withdrawalQueue.address, ETH(300), { from: user }) - await impersonate(ethers.provider, alice.address) - await web3.eth.sendTransaction({ to: alice.address, from: user, value: ETH(1) }) - await wsteth.transfer(alice.address, ETH(100), { from: user }) - - const requests = [] - - const withdrawalRequestsCount = 5 - for (let i = 0; i < withdrawalRequestsCount; ++i) { - requests.push(ETH(10)) - } - - const amount = bn(ETH(10)).mul(bn(withdrawalRequestsCount)) - const chainId = await wsteth.getChainId() - const deadline = MAX_UINT256 - const domainSeparator = makeDomainSeparator('Wrapped liquid staked Ether 2.0', '1', chainId, wsteth.address) - const { v, r, s } = signPermit( - alice.address, - withdrawalQueue.address, - amount, // amount - 0, // nonce - deadline, - domainSeparator, - alice.key - ) - const permission = [ - amount, - deadline, // deadline - v, - r, - s, - ] - - const aliceBalancesBefore = await wsteth.balanceOf(alice.address) - const lastRequestIdBefore = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.requestWithdrawalsWstETHWithPermit(requests, owner, permission, { from: alice.address }) - assert.equals(await withdrawalQueue.getLastRequestId(), lastRequestIdBefore.add(bn(requests.length))) - const aliceBalancesAfter = await wsteth.balanceOf(alice.address) - assert.equals(aliceBalancesAfter, aliceBalancesBefore.sub(bn(ETH(10)).mul(bn(withdrawalRequestsCount)))) - }) - }) - context('requestWithdrawalsWithPermit()', () => { const [alice] = ACCOUNTS_AND_KEYS it('works correctly with non empty payload', async () => { From a96ec097eb8445cf5792e01574a3f76155b395c1 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 28 Feb 2023 11:09:17 +0300 Subject: [PATCH 135/236] fix: naming fixes within sanity checker contract --- .../0.8.9/sanity_checks/OracleReportSanityChecker.sol | 8 ++++---- lib/abi/OracleReportSanityChecker.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index acf729969..b8e336525 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -532,9 +532,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { function _checkSharesRequestedToBurn(uint256 _sharesRequestedToBurn) internal view { (uint256 coverShares, uint256 nonCoverShares) = IBurner(LIDO_LOCATOR.burner()).getSharesRequestedToBurn(); - uint256 actualBurnerRequests = coverShares + nonCoverShares; - if (_sharesRequestedToBurn > actualBurnerRequests) { - revert IncorrectBurnerRequests(actualBurnerRequests); + uint256 actualSharesToBurn = coverShares + nonCoverShares; + if (_sharesRequestedToBurn > actualSharesToBurn) { + revert IncorrectSharesRequestedToBurn(actualSharesToBurn); } } @@ -696,7 +696,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { error IncorrectLimitValue(uint256 value, uint256 maxAllowedValue); error IncorrectWithdrawalsVaultBalance(uint256 actualWithdrawalVaultBalance); error IncorrectELRewardsVaultBalance(uint256 actualELRewardsVaultBalance); - error IncorrectBurnerRequests(uint256 actualBurnerRequests); + error IncorrectSharesRequestedToBurn(uint256 actualSharesToBurn); error IncorrectCLBalanceDecrease(uint256 oneOffCLBalanceDecreaseBP); error IncorrectCLBalanceIncrease(uint256 annualBalanceDiff); error IncorrectAppearedValidators(uint256 churnLimit); diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index a824c32f6..db7f6a9b8 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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"actualBurnerRequests","type":"uint256"}],"name":"IncorrectBurnerRequests","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"actualSharesToBurn","type":"uint256"}],"name":"IncorrectSharesRequestedToBurn","type":"error"},{"inputs":[{"internalType":"uint256","name":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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 a19b30364fce24ff176df3e84da692082ee001a7 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 28 Feb 2023 11:11:08 +0300 Subject: [PATCH 136/236] chore: remove extra awaits --- .../lido_rewards_distribution_math.test.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/scenario/lido_rewards_distribution_math.test.js b/test/scenario/lido_rewards_distribution_math.test.js index c4a73c3cb..4fb0ccf27 100644 --- a/test/scenario/lido_rewards_distribution_math.test.js +++ b/test/scenario/lido_rewards_distribution_math.test.js @@ -729,10 +729,10 @@ contract('Lido: rewards distribution math', (addresses) => { const rewardsAmount = ETH(1) const newBeaconBalance = totalPooledEtherBefore.sub(bufferedBefore).add(toBN(rewardsAmount)) - const treasurySharesBefore = await await token.sharesOf(treasuryAddr) - const nodeOperator1SharesBefore = await await token.sharesOf(nodeOperator1.address) - const nodeOperator2SharesBefore = await await token.sharesOf(nodeOperator2.address) - const nodeOperator3SharesBefore = await await token.sharesOf(nodeOperator3.address) + const treasurySharesBefore = await token.sharesOf(treasuryAddr) + const nodeOperator1SharesBefore = await token.sharesOf(nodeOperator1.address) + const nodeOperator2SharesBefore = await token.sharesOf(nodeOperator2.address) + const nodeOperator3SharesBefore = await token.sharesOf(nodeOperator3.address) await reportBeacon(3, newBeaconBalance) @@ -786,10 +786,10 @@ contract('Lido: rewards distribution math', (addresses) => { await stakingRouter.setStakingModuleStatus(firstModule.id, StakingModuleStatus.Stopped, { from: voting }) - const treasurySharesBefore = await await token.sharesOf(treasuryAddr) - const nodeOperator1SharesBefore = await await token.sharesOf(nodeOperator1.address) - const nodeOperator2SharesBefore = await await token.sharesOf(nodeOperator2.address) - const nodeOperator3SharesBefore = await await token.sharesOf(nodeOperator3.address) + const treasurySharesBefore = await token.sharesOf(treasuryAddr) + const nodeOperator1SharesBefore = await token.sharesOf(nodeOperator1.address) + const nodeOperator2SharesBefore = await token.sharesOf(nodeOperator2.address) + const nodeOperator3SharesBefore = await token.sharesOf(nodeOperator3.address) await reportBeacon(3, newBeaconBalance) @@ -828,10 +828,10 @@ contract('Lido: rewards distribution math', (addresses) => { await stakingRouter.setStakingModuleStatus(secondModule.id, StakingModuleStatus.Stopped, { from: voting }) - const treasurySharesBefore = await await token.sharesOf(treasuryAddr) - const nodeOperator1SharesBefore = await await token.sharesOf(nodeOperator1.address) - const nodeOperator2SharesBefore = await await token.sharesOf(nodeOperator2.address) - const nodeOperator3SharesBefore = await await token.sharesOf(nodeOperator3.address) + const treasurySharesBefore = await token.sharesOf(treasuryAddr) + const nodeOperator1SharesBefore = await token.sharesOf(nodeOperator1.address) + const nodeOperator2SharesBefore = await token.sharesOf(nodeOperator2.address) + const nodeOperator3SharesBefore = await token.sharesOf(nodeOperator3.address) await reportBeacon(3, newBeaconBalance) From 4b3010b7a0c0795e4b777c760268f1b0931a5931 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 28 Feb 2023 11:11:50 +0300 Subject: [PATCH 137/236] test: refactor handle-oracle-report test --- test/0.4.24/lido-handle-oracle-report.test.js | 355 +++++++++++++++--- 1 file changed, 307 insertions(+), 48 deletions(-) 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 e6c70cce5..08ba6f238 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1,7 +1,7 @@ const { artifacts, contract, ethers } = require('hardhat') const { assert } = require('../helpers/assert') -const { ETH, toBN, genKeys, StETH, calcSharesMintedAsFees } = require('../helpers/utils') +const { shareRate, ETH, toBN, genKeys, StETH, calcSharesMintedAsFees } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') const { EvmSnapshot, setBalance } = require('../helpers/blockchain') const { ZERO_ADDRESS, INITIAL_HOLDER } = require('../helpers/constants') @@ -23,6 +23,18 @@ const ORACLE_REPORT_LIMITS_BOILERPLATE = { maxPositiveTokenRebase: 1000000000, } +const DEFAULT_LIDO_ORACLE_REPORT = { + reportTimestamp: 0, // uint256, seconds + timeElapsed: 0, // uint256, seconds + clValidators: 0, // uint256, counter + postCLBalance: ETH(0), // uint256, wei + withdrawalVaultBalance: ETH(0), // uint256, wei + elRewardsVaultBalance: ETH(0), // uint256, wei + sharesRequestedToBurn: StETH(0), // uint256, wad + withdrawalFinalizationBatches: [], // uint256[], indexes + simulatedShareRate: shareRate(0), // uint256, 10e27 +} + const checkEvents = async ({ tx, reportTimestamp = 0, @@ -212,16 +224,22 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another } it('handleOracleReport access control', async () => { - await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'APP_AUTH_FAILED') + await assert.reverts( + lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: stranger }), + 'APP_AUTH_FAILED' + ) }) - it('handleOracleReport reverts whe protocol stopped', async () => { + it('handleOracleReport reverts when protocol is stopped', async () => { await lido.stop({ from: deployed.voting.address }) - await assert.reverts(lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, 0, { from: stranger }), 'CONTRACT_IS_STOPPED') + await assert.reverts( + lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: stranger }), + 'CONTRACT_IS_STOPPED' + ) }) it('zero report should do nothing', async () => { - const tx = await lido.handleOracleReport(0, 0, 0, 0, 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport(...Object.values(DEFAULT_LIDO_ORACLE_REPORT), { from: oracle }) await checkEvents({ tx, preCLValidators: 0, @@ -252,7 +270,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another describe('clBalance', () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -265,7 +283,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit without rewards', async () => { - const tx = await lido.handleOracleReport(0, 0, 1, ETH(32), 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 1, postCLBalance: ETH(32) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 0, @@ -295,7 +316,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) it('first report after deposit with rewards', async () => { - const tx = await lido.handleOracleReport(0, ONE_YEAR, 1, ETH(33), 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 1, + postCLBalance: ETH(33), + }), + { from: oracle } + ) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) await checkEvents({ tx, @@ -329,41 +358,60 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another describe('sanity checks', async () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) }) it('reverts on reported more than deposited', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 4, 0, 0, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 4 }), { from: oracle }), 'REPORTED_MORE_DEPOSITED' ) }) it('reverts on reported less than reported previously', async () => { - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await assert.reverts( - lido.handleOracleReport(0, 0, 2, 0, 0, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 2 }), { from: oracle }), 'REPORTED_LESS_VALIDATORS' ) }) it('withdrawal vault balance check', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, withdrawalVaultBalance: 1 }), { + from: oracle, + }), 'IncorrectWithdrawalsVaultBalance(0)' ) }) - it('withdrawal vault balance check 2', async () => { + it('execution layer rewards vault balance check', async () => { await assert.reverts( - lido.handleOracleReport(0, 0, 0, 0, 1, 0, 0, 0, 0, { from: oracle }), - 'IncorrectWithdrawalsVaultBalance(0)' + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, elRewardsVaultBalance: 1 }), { + from: oracle, + }), + 'IncorrectELRewardsVaultBalance(0)' + ) + }) + + it('burner shares to burn check', async () => { + await assert.reverts( + lido.handleOracleReport(...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, sharesRequestedToBurn: 1 }), { + from: oracle, + }), + 'IncorrectSharesRequestedToBurn(0)' ) }) it('does not revert on new total balance stay the same', async () => { - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + let tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 0, @@ -389,7 +437,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 3, @@ -421,7 +472,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - let tx = await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + let tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 0, @@ -447,7 +501,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - tx = await lido.handleOracleReport(0, 0, 3, ETH(95.04), 0, 0, 0, 0, 0, { from: oracle }) + tx = await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(95.04) }), + { from: oracle } + ) await checkEvents({ tx, preCLValidators: 3, @@ -480,7 +537,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another // set oneOffCLBalanceDecreaseBPLimit = 1% await oracleReportSanityChecker.setOracleReportLimits(ORACLE_REPORT_LIMITS_BOILERPLATE, { from: voting }) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -491,7 +551,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport(0, 0, 3, ETH(95.03), 0, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(95.03) }), + { from: oracle } + ), 'IncorrectCLBalanceDecrease(101)' ) }) @@ -506,7 +569,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -516,7 +582,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another curatedModuleBalanceDiff: 0, initialHolderBalanceDiff: 0, }) - const tx = await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.96), 0, 0, 0, 0, 0, { from: oracle }) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.96), + }), + { from: oracle } + ) const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.96), 10, 100, ETH(100), ETH(100.96)) await checkEvents({ tx, @@ -556,7 +630,10 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting } ) - await lido.handleOracleReport(0, 0, 3, ETH(96), 0, 0, 0, 0, 0, { from: oracle }) + await lido.handleOracleReport( + ...Object.values({ ...DEFAULT_LIDO_ORACLE_REPORT, clValidators: 3, postCLBalance: ETH(96) }), + { from: oracle } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -567,7 +644,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another initialHolderBalanceDiff: 0, }) await assert.reverts( - lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.97), 0, 0, 0, 0, 0, { from: oracle }), + lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.97), + }), + { from: oracle } + ), 'IncorrectCLBalanceIncrease(101)' ) }) @@ -584,7 +669,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 100, ETH(3200), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 100, + postCLBalance: ETH(3200), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 100, beaconValidators: 100, beaconBalance: ETH(3200) }) }) @@ -600,7 +693,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another { from: voting, gasPrice: 1 } ) await assert.reverts( - lido.handleOracleReport(0, ONE_DAY, 101, ETH(3200), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }), + lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 101, + postCLBalance: ETH(3200), + }), + { from: oracle, gasPrice: 1 } + ), 'IncorrectAppearedValidators(101)' ) }) @@ -608,7 +709,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another describe('smooth report', async () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -628,7 +729,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(97), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(97), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(97) }) }) @@ -640,7 +749,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(100), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(100), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(100) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(4), @@ -663,7 +780,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -687,7 +813,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), ETH(1.1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -712,7 +847,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -738,7 +882,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(95.5), 0, ETH(1.5), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(95.5), + elRewardsVaultBalance: ETH(1.5), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.5) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -763,7 +916,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -787,7 +949,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(0.9), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.9), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ @@ -813,7 +984,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_YEAR, 3, ETH(96.1), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -829,7 +1009,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) describe('daily reports', () => { beforeEach(async () => { - await await lido.deposit(3, 1, '0x', { from: depositor }) + await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) await checkBalanceDeltas({ totalPooledEtherDiff: 0, @@ -851,7 +1031,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -872,7 +1061,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.0027), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.0027), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.0027) }) }) @@ -885,7 +1082,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96 + 0.0028), 0, 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.0028), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96 + clIncrease) }) assert( 0.00014 + 0.0028 * 0.9 * 0.3 + 0.0028 * 0.9 * 0.69 + 0.0028 * 0.01 * 0.9 + 0.00014 === clIncrease, @@ -912,7 +1117,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -936,7 +1150,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), ETH(1.1), 0, 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + withdrawalVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -961,7 +1184,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ @@ -987,7 +1219,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(95.5), 0, ETH(1.5), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(95.5), + elRewardsVaultBalance: ETH(1.5), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(95.5) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -1012,7 +1253,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96), 0, ETH(1.1), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(1.1), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) await checkBalanceDeltas({ totalPooledEtherDiff: ETH(1), @@ -1036,7 +1286,16 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }, { from: voting, gasPrice: 1 } ) - await lido.handleOracleReport(0, ONE_DAY, 3, ETH(96.1), 0, ETH(0.9), 0, 0, 0, { from: oracle, gasPrice: 1 }) + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.9), + }), + { from: oracle, gasPrice: 1 } + ) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) await checkBalanceDeltas({ From 5964bb5fb61a9932c05f6ed8e98870d063cc98d6 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 00:55:08 +0300 Subject: [PATCH 138/236] test: assign REQUEST_BURN_SHARES_ROLE in factory --- test/helpers/factories.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 0fa7ebcae..f8e35b3cd 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -300,13 +300,15 @@ async function guardiansFactory({ deployParams }) { async function burnerFactory({ appManager, treasury, pool, voting }) { const burner = await Burner.new(appManager.address, treasury.address, pool.address, 0, 0) - const [REQUEST_BURN_MY_STETH_ROLE, RECOVER_ASSETS_ROLE] = await Promise.all([ + const [REQUEST_BURN_MY_STETH_ROLE, REQUEST_BURN_SHARES_ROLE, RECOVER_ASSETS_ROLE] = await Promise.all([ burner.REQUEST_BURN_MY_STETH_ROLE(), + burner.REQUEST_BURN_SHARES_ROLE(), burner.RECOVER_ASSETS_ROLE(), ]) await burner.grantRole(REQUEST_BURN_MY_STETH_ROLE, voting.address, { from: appManager.address }) await burner.grantRole(RECOVER_ASSETS_ROLE, voting.address, { from: appManager.address }) + await burner.grantRole(REQUEST_BURN_SHARES_ROLE, voting.address, { from: appManager.address }) return burner } From 5a7eb7575bc8f49ad4254c8129ae052b28b10c5f Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 00:55:51 +0300 Subject: [PATCH 139/236] test: handleOracleReport with shares burning --- test/0.4.24/lido-handle-oracle-report.test.js | 401 +++++++++++++++++- 1 file changed, 395 insertions(+), 6 deletions(-) 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 08ba6f238..df5679741 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1,7 +1,17 @@ const { artifacts, contract, ethers } = require('hardhat') const { assert } = require('../helpers/assert') -const { shareRate, ETH, toBN, genKeys, StETH, calcSharesMintedAsFees } = require('../helpers/utils') +const { + e9, + shareRate, + ETH, + toBN, + genKeys, + StETH, + calcSharesMintedAsFees, + calcShareRateDeltaE27, + limitRebase, +} = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') const { EvmSnapshot, setBalance } = require('../helpers/blockchain') const { ZERO_ADDRESS, INITIAL_HOLDER } = require('../helpers/constants') @@ -97,8 +107,8 @@ const checkEvents = async ({ ) } -contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, anotherStranger, depositor, operator]) => { - let deployed, snapshot, lido, treasury, voting, oracle +contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anotherStranger, depositor, operator]) => { + let deployed, snapshot, lido, treasury, voting, oracle, burner let curatedModule, oracleReportSanityChecker, elRewardsVault let withdrawalVault let strangerBalanceBefore, @@ -137,6 +147,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another await curatedModule.setNodeOperatorStakingLimit(0, keysAmount, { from: deployed.voting.address }) lido = deployed.pool + burner = deployed.burner treasury = deployed.treasury.address voting = deployed.voting.address oracle = deployed.oracle.address @@ -268,7 +279,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another }) }) - describe('clBalance', () => { + describe('clBalance', async () => { beforeEach(async () => { await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) @@ -340,7 +351,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another preTotalEther: ETH(100), postTotalShares: toBN(ETH(100)).add(sharesMintedAsFees).toString(), postTotalEther: ETH(101), - sharesMintedAsFees, + sharesMintedAsFees: sharesMintedAsFees.toString(), }) await checkStat({ depositedValidators: 3, beaconValidators: 1, beaconBalance: ETH(33) }) @@ -1006,8 +1017,306 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.2)) }) + + it('does not smooth shares to burn if report in limit with shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + + const sharesToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + sharesRequestedToBurn: sharesToBurn, + }), + { from: oracle, gasPrice: 1 } + ) + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0), + postBufferedEther: ETH(5), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: toBN(ETH(101)).sub(sharesToBurn).toString(), + postTotalEther: ETH(101), + sharesMintedAsFees: 0, + }) + + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1), // bob's deposit + treasuryBalanceDiff: ETH(0), // no rewards reported + strangerBalanceDiff: ETH(0.3), // though, bob has sacrificed stETH shares for all users + anotherStrangerBalanceDiff: ETH(0.69), + curatedModuleBalanceDiff: ETH(0), // no rewards reported + initialHolderBalanceDiff: ETH(0.01), + }) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(coverShares.add(nonCoverShares), StETH(0)) + assert.equals(await lido.balanceOf(burner.address), StETH(0)) + }) + + it('smooth shares to burn if report in limit without shares and no fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.5)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(0.5), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0), + ETH(0.5), + sharesRequestedToBurn + ) + + const postTotalShares = toBN(ETH(101)).sub(toBN(sharesToBurn)) + const postTotalEther = toBN(ETH(101)).add(toBN(elBalanceUpdate)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.5), + postBufferedEther: ETH(5.5), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: 0, // no rewards on CL side => no minted fee + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: ETH(0), // no fee minted + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), // though, bob has sacrificed stETH shares for all users + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: ETH(0), // no fee minted + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) + }) + + it('smooth shares to burn if report in limit without shares and fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.4)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.4), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(0.4), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.5), 10, 100, ETH(101), postTotalEther) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.4), + postBufferedEther: ETH(5.4), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), // no rewards on CL side => no minted fee + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) + }) + + it('postpone all shares to burn if report out of limit even without shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(4.9)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_YEAR, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(4.9), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(4.9), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees( + toBN(ETH(0.1)).add(elBalanceUpdate), + 10, + 100, + ETH(101), + postTotalEther + ) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: elBalanceUpdate.toString(), + postBufferedEther: toBN(ETH(5)).add(elBalanceUpdate).toString(), + timeElapsed: ONE_YEAR, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: toBN(ETH(1.1)).add(elBalanceUpdate), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), toBN(ETH(4.9)).sub(elBalanceUpdate)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesToBurn, 0) + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + assert.equals(await lido.balanceOf(burner.address), await lido.getPooledEthByShares(sharesRequestedToBurn)) + }) }) - describe('daily reports', () => { + + describe('daily reports', async () => { beforeEach(async () => { await lido.deposit(3, 1, '0x', { from: depositor }) await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: 0 }) @@ -1309,5 +1618,85 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , , stranger, another assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.1)) }) + + it.skip('does not smooth shares to burn if report in limit with shares', async () => { + // TODO + }) + + it.skip('smooth shares to burn if report in limit without shares', async () => { + // TODO + }) + + it.skip('postpone all shares to burn if report out of limit without shares', async () => { + // TODO + }) + }) + + describe('reports with withdrawals finalization', () => { + beforeEach(async () => { + 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, + initialHolderBalanceDiff: 0, + }) + }) + + it('dry-run eth_call works and returns proper values', async () => { + await setBalance(elRewardsVault, ETH(0.5)) + await setBalance(withdrawalVault, ETH(0.5)) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + churnValidatorsPerDayLimit: 100, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + + const [postTotalPooledEther, postTotalShares, withdrawals, elRewards] = await lido.handleOracleReport.call( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.5), + withdrawalVaultBalance: ETH(0.5), + }), + { from: oracle, gasPrice: 1 } + ) + + await checkStat({ depositedValidators: 3, beaconValidators: 0, beaconBalance: ETH(0) }) + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(0), + treasuryBalanceDiff: ETH(0), + strangerBalanceDiff: ETH(0), + anotherStrangerBalanceDiff: ETH(0), + curatedModuleBalanceDiff: ETH(0), + initialHolderBalanceDiff: ETH(0), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.5)) + assert.equals(await ethers.provider.getBalance(withdrawalVault), ETH(0.5)) + + const sharesMintedAsFees = calcSharesMintedAsFees(ETH(1), 10, 100, ETH(100), ETH(101)) + + assert.equals(postTotalPooledEther, ETH(101)) + assert.equals(postTotalShares, toBN(ETH(100)).add(sharesMintedAsFees)) + assert.equals(withdrawals, ETH(0.5)) + assert.equals(elRewards, ETH(0.4)) + }) + + it.skip('withdrawal finalization works after dry-run call', async () => { + // TODO + }) + + it.skip('check simulated share rate correctness when limit is higher due to withdrawals', async () => { + // TODO + }) }) }) From 104c089dcaa5e80aa90c6b7d868d90cdad310284 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Wed, 1 Mar 2023 01:03:45 +0300 Subject: [PATCH 140/236] chore: minor contract updates --- contracts/0.4.24/Lido.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 59aef31fa..d2cb600ed 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -1232,6 +1232,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 4. // Pass the accounting values to sanity checker to smoothen positive token rebase + + uint256 withdrawals; + uint256 elRewards; ( withdrawals, elRewards, reportContext.simulatedSharesToBurn, reportContext.sharesToBurn ) = IOracleReportSanityChecker(contracts.oracleReportSanityChecker).smoothenTokenRebase( @@ -1284,8 +1287,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Step 8. // Complete token rebase by informing observers (emit an event and call the external receivers if any) ( - postTotalShares, - postTotalPooledEther + uint256 postTotalShares, + uint256 postTotalPooledEther ) = _completeTokenRebase( _reportedData, reportContext, From 9f74350338f52fe632fa55c337f73b27deba94a2 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 2 Mar 2023 15:41:05 +0200 Subject: [PATCH 141/236] test: fix withdrawal nft tests --- contracts/0.4.24/Lido.sol | 18 ++------ lib/abi/Lido.json | 2 +- test/0.8.9/withdrawal-request-nft.test.js | 50 +++++++++-------------- 3 files changed, 25 insertions(+), 45 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index d2cb600ed..62052e55c 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -585,12 +585,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { // Decision about withdrawals processing uint256 _lastFinalizableRequestId, uint256 _simulatedShareRate - ) external returns ( - uint256 postTotalPooledEther, - uint256 postTotalShares, - uint256 withdrawals, - uint256 elRewards - ) { + ) external returns (uint256[4] postRebaseAmounts) { _whenNotStopped(); return _handleOracleReport( @@ -1182,14 +1177,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * 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 - ) internal returns ( - uint256 postTotalPooledEther, - uint256 postTotalShares, - uint256 withdrawals, - uint256 elRewards - ) { + function _handleOracleReport(OracleReportedData memory _reportedData) internal returns (uint256[4]) { OracleReportContracts memory contracts = _loadOracleReportContracts(); require(msg.sender == contracts.accountingOracle, "APP_AUTH_FAILED"); @@ -1305,6 +1293,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { _reportedData.simulatedShareRate ); } + + return [postTotalPooledEther, postTotalShares, withdrawals, elRewards]; } /** diff --git a/lib/abi/Lido.json b/lib/abi/Lido.json index 6585318ab..5c6df83d2 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":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":true,"stateMutability":"payable","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":"eip712Domain","outputs":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","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":true,"inputs":[],"name":"getEIP712StETH","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","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":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":"_sharesRequestedToBurn","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":true,"inputs":[],"name":"getDepositableEther","outputs":[{"name":"","type":"uint256"}],"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":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":true,"stateMutability":"payable","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":"eip712Domain","outputs":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","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":true,"inputs":[],"name":"getEIP712StETH","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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":"removeStakingLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","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":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":"_sharesRequestedToBurn","type":"uint256"},{"name":"_lastFinalizableRequestId","type":"uint256"},{"name":"_simulatedShareRate","type":"uint256"}],"name":"handleOracleReport","outputs":[{"name":"postRebaseAmounts","type":"uint256[4]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getDepositableEther","outputs":[{"name":"","type":"uint256"}],"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":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/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index 0ee2e8d7a..61efae021 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -10,9 +10,9 @@ const StETH = artifacts.require('StETHMock') const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock') contract('WithdrawalNFT', (addresses) => { - const [deployer, stEthHolder, wstEthHolder, nftHolderStETH, nftHolderWstETH, recipient, stranger] = addresses - let withdrawalQueueERC721, stETH, wstETH, erc721ReceiverMock - let nftHolderStETHTokenIds, nftHolderWstETHTokenIds, nonExistedTokenId + const [deployer, stEthHolder, nftHolderStETH, recipient, stranger] = addresses + let withdrawalQueueERC721, stETH, erc721ReceiverMock + let nftHolderStETHTokenIds, nonExistedTokenId const snapshot = new EvmSnapshot(ethers.provider) before(async () => { @@ -21,26 +21,18 @@ contract('WithdrawalNFT', (addresses) => { erc721ReceiverMock = await ERC721ReceiverMock.new({ from: deployer }) withdrawalQueueERC721 = (await withdrawals.deploy(deployer, stETH.address, 'Lido TEST Request', 'unstEsT')).queue - await withdrawalQueueERC721.initialize( - deployer, // owner - deployer, // pauser - deployer, // resumer - deployer, // finalizer - deployer - ) + await withdrawalQueueERC721.initialize(deployer) + await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.RESUME_ROLE(), deployer) + await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.FINALIZE_ROLE(), deployer) await withdrawalQueueERC721.resume({ from: deployer }) await stETH.setTotalPooledEther(ETH(101)) - await stETH.mintShares(stEthHolder, shares(50)) - await stETH.mintShares(wstETH.address, shares(50)) - await wstETH.mint(wstEthHolder, ETH(25)) + await stETH.mintShares(stEthHolder, shares(100)) await stETH.approve(withdrawalQueueERC721.address, ETH(50), { from: stEthHolder }) - await wstETH.approve(withdrawalQueueERC721.address, ETH(25), { from: wstEthHolder }) + await withdrawalQueueERC721.requestWithdrawals([ETH(25), ETH(25)], nftHolderStETH, { from: stEthHolder }) nftHolderStETHTokenIds = [1, 2] - await withdrawalQueueERC721.requestWithdrawalsWstETH([ETH(25)], nftHolderWstETH, { from: wstEthHolder }) - nftHolderWstETHTokenIds = [3] nonExistedTokenId = 4 await snapshot.make() }) @@ -84,7 +76,6 @@ contract('WithdrawalNFT', (addresses) => { it('return correct withdrawal requests count', async () => { assert.equals(await withdrawalQueueERC721.balanceOf(nftHolderStETH), 2) - assert.equals(await withdrawalQueueERC721.balanceOf(nftHolderWstETH), 1) }) it('reverts for zero address', async () => { @@ -104,7 +95,6 @@ contract('WithdrawalNFT', (addresses) => { it('reverts correct owner', async () => { assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), nftHolderStETH) assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[1]), nftHolderStETH) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), nftHolderWstETH) }) }) @@ -190,8 +180,8 @@ contract('WithdrawalNFT', (addresses) => { it('reverts with message "TransferToNonIERC721Receiver()" when transfer to contract that not implements IERC721Receiver interface', async () => { await assert.reverts( - withdrawalQueueERC721.safeTransferFrom(nftHolderWstETH, stETH.address, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, stETH.address, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }), `TransferToNonIERC721Receiver("${stETH.address}")` ) @@ -232,8 +222,8 @@ contract('WithdrawalNFT', (addresses) => { it('reverts when transfer to the same address', async () => { await assert.reverts( - withdrawalQueueERC721.transferFrom(nftHolderWstETH, nftHolderWstETH, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + withdrawalQueueERC721.transferFrom(nftHolderStETH, nftHolderStETH, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }), 'TransferToThemselves()' ) @@ -259,11 +249,11 @@ contract('WithdrawalNFT', (addresses) => { }) it('transfers if called by owner', async () => { - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), recipient) - await withdrawalQueueERC721.transferFrom(nftHolderWstETH, recipient, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) + await withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), recipient) + assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) }) it('transfers if token approval set', async () => { @@ -308,11 +298,11 @@ contract('WithdrawalNFT', (addresses) => { }) it("doesn't reverts when transfer to contract that not implements IERC721Receiver interface", async () => { - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), nftHolderWstETH) - await withdrawalQueueERC721.transferFrom(nftHolderWstETH, stETH.address, nftHolderWstETHTokenIds[0], { - from: nftHolderWstETH, + assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), nftHolderStETH) + await withdrawalQueueERC721.transferFrom(nftHolderStETH, stETH.address, nftHolderStETHTokenIds[0], { + from: nftHolderStETH, }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderWstETHTokenIds[0]), stETH.address) + assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), stETH.address) }) }) From 71aa3e06c45d0fbb56c119869da9bc4352fb3c59 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Mon, 6 Mar 2023 20:51:26 +0700 Subject: [PATCH 142/236] fix: legacy oracle getCurrentFrame bug --- contracts/0.4.24/oracle/LegacyOracle.sol | 15 ++++++++++----- test/0.4.24/legacy-oracle.test.js | 4 ++-- .../0.8.9/oracle/accounting-oracle-deploy.test.js | 2 +- test/0.8.9/oracle/hash-consensus-deploy.test.js | 1 - 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/contracts/0.4.24/oracle/LegacyOracle.sol b/contracts/0.4.24/oracle/LegacyOracle.sol index 4893ba5a1..7cd084640 100644 --- a/contracts/0.4.24/oracle/LegacyOracle.sol +++ b/contracts/0.4.24/oracle/LegacyOracle.sol @@ -162,7 +162,11 @@ contract LegacyOracle is Versioned, AragonApp { * Returns the epoch calculated from current timestamp */ function getCurrentEpochId() external view returns (uint256 epochId) { - (epochId, ,) = _getCurrentFrameFromAccountingOracle(); + ChainSpec memory spec = _getChainSpec(); + IHashConsensus consensus = _getAccountingConsensusContract(); + uint256 refSlot; + (refSlot,) = consensus.getCurrentFrame(); + epochId = (refSlot + 1) / spec.slotsPerEpoch; } /** @@ -369,12 +373,13 @@ contract LegacyOracle is Versioned, AragonApp { ChainSpec memory spec = _getChainSpec(); IHashConsensus consensus = _getAccountingConsensusContract(); uint256 refSlot; - (refSlot, frameEndTime) = consensus.getCurrentFrame(); - // new accounting oracle's frame ends at the timestamp of the frame's last slot; old oracle's frame - // ended a second before the timestamp of the first slot of the next frame - frameEndTime += spec.secondsPerSlot - 1; + (refSlot,) = consensus.getCurrentFrame(); + // new accounting oracle's ref. slot is the last slot of the epoch preceding the one the frame starts at frameStartTime = spec.genesisTime + (refSlot + 1) * spec.secondsPerSlot; + // new accounting oracle's frame ends at the timestamp of the frame's last slot; old oracle's frame + // ended a second before the timestamp of the first slot of the next frame + frameEndTime = frameStartTime + spec.secondsPerSlot*spec.slotsPerEpoch*spec.epochsPerFrame - 1; frameEpochId = (refSlot + 1) / spec.slotsPerEpoch; } diff --git a/test/0.4.24/legacy-oracle.test.js b/test/0.4.24/legacy-oracle.test.js index a669f981f..67e0035fc 100644 --- a/test/0.4.24/legacy-oracle.test.js +++ b/test/0.4.24/legacy-oracle.test.js @@ -22,7 +22,7 @@ const { computeTimestampAtSlot, ZERO_HASH, CONSENSUS_VERSION, - SLOTS_PER_FRAME, + computeTimestampAtEpoch, } = require('../0.8.9/oracle/accounting-oracle-deploy.test') const getReportFields = (override = {}) => ({ @@ -212,7 +212,7 @@ contract('LegacyOracle', ([admin, stranger]) => { const refSlot = consensusFrame.refSlot.toNumber() assert.equals(epochId, Math.floor((refSlot + 1) / SLOTS_PER_EPOCH)) assert.equals(frameStartTime, computeTimestampAtSlot(refSlot + 1)) - assert.equals(frameEndTime, computeTimestampAtSlot(refSlot + 1 + SLOTS_PER_FRAME) - 1) + assert.equals(frameEndTime, computeTimestampAtEpoch(+epochId + EPOCHS_PER_FRAME) - 1) }) it.skip('handlePostTokenRebase from lido') diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index a298b75b5..d3e0dea95 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -246,7 +246,7 @@ async function deployAndConfigureAccountingOracle(admin) { /// 2. set HashConsensus initial epoch /// 3. deploy AccountingOracle proxy (skipped in these tests as they're not testing the proxy setup) /// 4. initialize AccountingOracle - const finalizeResult = await configureAccountingOracleSetup(deployed) + const finalizeResult = await configureAccountingOracleSetup({ admin, ...deployed }) // pretend we're at the first slot of the new oracle's initial epoch const initialEpoch = V1_ORACLE_LAST_COMPLETED_EPOCH + EPOCHS_PER_FRAME 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 13261f88a..fb67f085d 100644 --- a/test/0.8.9/oracle/hash-consensus-deploy.test.js +++ b/test/0.8.9/oracle/hash-consensus-deploy.test.js @@ -106,7 +106,6 @@ module.exports = { contract('HashConsensus', ([admin, member1]) => { context('Deployment and initial configuration', () => { const INITIAL_EPOCH = 3 - let consensus it('deploying hash consensus', async () => { From 652c3e86951a49943193bf7f59804aa0309fee9c Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 2 Mar 2023 18:52:47 +0300 Subject: [PATCH 143/236] fix: wq request status iface for sanity checker --- .../OracleReportSanityChecker.sol | 39 +++++++++++------ .../OracleReportSanityCheckerMocks.sol | 43 ++++++++++++------- lib/abi/IWithdrawalQueue.json | 2 +- .../oracle-report-sanity-checker.test.js | 6 +-- 4 files changed, 56 insertions(+), 34 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index b8e336525..ecad9f8ec 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -13,17 +13,25 @@ import {ILidoLocator} from "../../common/interfaces/ILidoLocator.sol"; import {IBurner} from "../../common/interfaces/IBurner.sol"; interface IWithdrawalQueue { - function getWithdrawalRequestStatus(uint256 _requestId) + struct WithdrawalRequestStatus { + /// @notice stETH token amount that was locked on withdrawal queue for this request + uint256 amountOfStETH; + /// @notice amount of stETH shares locked on withdrawal queue for this request + uint256 amountOfShares; + /// @notice address that can claim or transfer this request + address owner; + /// @notice timestamp of when the request was created, in seconds + uint256 timestamp; + /// @notice true, if request is finalized + bool isFinalized; + /// @notice true, if request is claimed. Request is claimable if (isFinalized && !isClaimed) + bool isClaimed; + } + + function getWithdrawalStatus(uint256[] calldata _requestIds) external view - returns ( - uint256 amountOfStETH, - uint256 amountOfShares, - address recipient, - uint256 timestamp, - bool isFinalized, - bool isClaimed - ); + returns (WithdrawalRequestStatus[] memory statuses); } /// @notice The set of restrictions used in the sanity checks of the oracle report @@ -596,13 +604,16 @@ contract OracleReportSanityChecker is AccessControlEnumerable { function _checkRequestIdToFinalizeUpTo( LimitsList memory _limitsList, address _withdrawalQueue, - uint256 _requestIdToFinalizeUpTo, + uint256 _lastFinalizableId, uint256 _reportTimestamp ) internal view { - (, , , uint256 requestTimestampToFinalizeUpTo, , ) = IWithdrawalQueue(_withdrawalQueue) - .getWithdrawalRequestStatus(_requestIdToFinalizeUpTo); - if (_reportTimestamp < requestTimestampToFinalizeUpTo + _limitsList.requestTimestampMargin) - revert IncorrectRequestFinalization(requestTimestampToFinalizeUpTo); + uint256[] memory requestIds = new uint256[](1); + requestIds[0] = _lastFinalizableId; + + IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = IWithdrawalQueue(_withdrawalQueue) + .getWithdrawalStatus(requestIds); + if (_reportTimestamp < statuses[0].timestamp + _limitsList.requestTimestampMargin) + revert IncorrectRequestFinalization(statuses[0].timestamp); } function _checkSimulatedShareRate( diff --git a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol index 23d597ba2..e4ad80a35 100644 --- a/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol +++ b/contracts/0.8.9/test_helpers/OracleReportSanityCheckerMocks.sol @@ -19,25 +19,36 @@ contract LidoStub { } contract WithdrawalQueueStub { - mapping(uint256 => uint256) private _blockNumbers; + struct WithdrawalRequestStatus { + /// @notice stETH token amount that was locked on withdrawal queue for this request + uint256 amountOfStETH; + /// @notice amount of stETH shares locked on withdrawal queue for this request + uint256 amountOfShares; + /// @notice address that can claim or transfer this request + address owner; + /// @notice timestamp of when the request was created, in seconds + uint256 timestamp; + /// @notice true, if request is finalized + bool isFinalized; + /// @notice true, if request is claimed. Request is claimable if (isFinalized && !isClaimed) + bool isClaimed; + } + + mapping(uint256 => uint256) private _timestamps; - function setRequestBlockNumber(uint256 _requestId, uint256 _blockNumber) external { - _blockNumbers[_requestId] = _blockNumber; + function setRequestTimestamp(uint256 _requestId, uint256 _timestamp) external { + _timestamps[_requestId] = _timestamp; } - function getWithdrawalRequestStatus(uint256 _requestId) - external - view - returns ( - uint256, - uint256, - address, - uint256 blockNumber, - bool, - bool - ) - { - blockNumber = _blockNumbers[_requestId]; + function getWithdrawalStatus( + uint256[] calldata _requestIds + ) external view returns ( + WithdrawalRequestStatus[] memory statuses + ) { + statuses = new WithdrawalRequestStatus[](_requestIds.length); + for (uint256 i; i < _requestIds.length; ++i) { + statuses[i].timestamp = _timestamps[_requestIds[i]]; + } } } diff --git a/lib/abi/IWithdrawalQueue.json b/lib/abi/IWithdrawalQueue.json index b70a929f2..4c65f3257 100644 --- a/lib/abi/IWithdrawalQueue.json +++ b/lib/abi/IWithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getWithdrawalRequestStatus","outputs":[{"internalType":"uint256","name":"amountOfStETH","type":"uint256"},{"internalType":"uint256","name":"amountOfShares","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"bool","name":"isClaimed","type":"bool"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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 IWithdrawalQueue.WithdrawalRequestStatus[]","name":"statuses","type":"tuple[]"}],"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 e78914ec8..93501159e 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -251,10 +251,10 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa const currentBlockTimestamp = await getCurrentBlockTimestamp() correctWithdrawalQueueOracleReport.refReportTimestamp = currentBlockTimestamp oldRequestCreationTimestamp = currentBlockTimestamp - defaultLimitsList.requestTimestampMargin - correctWithdrawalQueueOracleReport.requestIdToFinalizeUpTo = oldRequestCreationTimestamp - await withdrawalQueueMock.setRequestBlockNumber(oldRequestId, oldRequestCreationTimestamp) + correctWithdrawalQueueOracleReport.lastFinalizableRequestId = oldRequestCreationTimestamp + await withdrawalQueueMock.setRequestTimestamp(oldRequestId, oldRequestCreationTimestamp) newRequestCreationTimestamp = currentBlockTimestamp - Math.floor(defaultLimitsList.requestTimestampMargin / 2) - await withdrawalQueueMock.setRequestBlockNumber(newRequestId, newRequestCreationTimestamp) + await withdrawalQueueMock.setRequestTimestamp(newRequestId, newRequestCreationTimestamp) }) it('reverts with the error IncorrectRequestFinalization() when the creation timestamp of requestIdToFinalizeUpTo is too close to report timestamp', async () => { From dbc9920bf4d1b6f630a5496580be6301bbe26122 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Fri, 3 Mar 2023 11:42:07 +0300 Subject: [PATCH 144/236] test: handleOracleReport daily shares burn cases --- test/0.4.24/lido-handle-oracle-report.test.js | 285 +++++++++++++++++- 1 file changed, 277 insertions(+), 8 deletions(-) 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 df5679741..338424d75 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -1153,7 +1153,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot ) }) - it('smooth shares to burn if report in limit without shares and fees', async () => { + it('smooth shares to burn if report in limit without shares and some fees', async () => { await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) await setBalance(elRewardsVault, ETH(0.4)) @@ -1210,7 +1210,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot preTotalEther: ETH(101), postTotalShares: postTotalShares.toString(), postTotalEther: postTotalEther.toString(), - sharesMintedAsFees: sharesMintedAsFees.toString(), // no rewards on CL side => no minted fee + sharesMintedAsFees: sharesMintedAsFees.toString(), }) await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) @@ -1619,16 +1619,285 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0.1)) }) - it.skip('does not smooth shares to burn if report in limit with shares', async () => { - // TODO + it('does not smooth shares to burn if report in limit with shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + + const sharesToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + sharesRequestedToBurn: sharesToBurn, + }), + { 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.69), + curatedModuleBalanceDiff: 0, + initialHolderBalanceDiff: ETH(0.01), + }) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(coverShares.add(nonCoverShares), StETH(0)) + assert.equals(await lido.balanceOf(burner.address), StETH(0)) }) - it.skip('smooth shares to burn if report in limit without shares', async () => { - // TODO + it('smooth shares to burn if report in limit without shares and no fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.5)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96), + elRewardsVaultBalance: ETH(0.5), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0), + ETH(0.5), + sharesRequestedToBurn + ) + + const postTotalShares = toBN(ETH(101)).sub(toBN(sharesToBurn)) + const postTotalEther = toBN(ETH(101)).add(toBN(elBalanceUpdate)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.5), + postBufferedEther: ETH(5.5), + timeElapsed: ONE_DAY, // NB: day-long + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: 0, // no rewards on CL side => no minted fee + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: ETH(0), // no fee minted + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), // though, bob has sacrificed stETH shares for all users + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: ETH(0), // no fee minted + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) }) - it.skip('postpone all shares to burn if report out of limit without shares', async () => { - // TODO + it('smooth shares to burn if report in limit without shares and some fees', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(0.4)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.4), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(0.4), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees(ETH(0.5), 10, 100, ETH(101), postTotalEther) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: ETH(0.4), + postBufferedEther: ETH(5.4), + timeElapsed: ONE_DAY, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: ETH(1.5), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), ETH(0)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesRequestedToBurn.sub(coverShares.add(nonCoverShares)), sharesToBurn) + assert.equals( + await lido.balanceOf(burner.address), + await lido.getPooledEthByShares(toBN(sharesRequestedToBurn).sub(sharesToBurn)) + ) + }) + + it('postpone all shares to burn if report out of limit without shares', async () => { + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + await setBalance(elRewardsVault, ETH(4.9)) + + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + maxPositiveTokenRebase: 10000000, // 1% + }, + { from: voting, gasPrice: 1 } + ) + + const tx = await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(4.9), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + + const { elBalanceUpdate, sharesToBurn } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(4.9), + sharesRequestedToBurn + ) + + const postTotalEther = toBN(ETH(101.1)).add(toBN(elBalanceUpdate)) + const sharesMintedAsFees = calcSharesMintedAsFees( + toBN(ETH(0.1)).add(elBalanceUpdate), + 10, + 100, + ETH(101), + postTotalEther + ) + const postTotalShares = toBN(ETH(101)).add(sharesMintedAsFees).sub(toBN(sharesToBurn)) + + await checkEvents({ + tx, + preCLValidators: 0, + postCLValidators: 3, + preCLBalance: ETH(96), + postCLBalance: ETH(96.1), + withdrawalsWithdrawn: 0, + executionLayerRewardsWithdrawn: elBalanceUpdate.toString(), + postBufferedEther: toBN(ETH(5)).add(elBalanceUpdate).toString(), + timeElapsed: ONE_DAY, + preTotalShares: ETH(101), + preTotalEther: ETH(101), + postTotalShares: postTotalShares.toString(), + postTotalEther: postTotalEther.toString(), + sharesMintedAsFees: sharesMintedAsFees.toString(), + }) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + const shareRateDeltaE27 = calcShareRateDeltaE27(ETH(101), postTotalEther, ETH(101), postTotalShares) + + await checkBalanceDeltas({ + totalPooledEtherDiff: toBN(ETH(1.1)).add(elBalanceUpdate), + treasuryBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + strangerBalanceDiff: shareRateDeltaE27.mul(toBN(30)).div(toBN(e9(1))), + anotherStrangerBalanceDiff: shareRateDeltaE27.mul(toBN(69)).div(toBN(e9(1))), + curatedModuleBalanceDiff: await lido.getPooledEthByShares(sharesMintedAsFees.div(toBN(2))), + initialHolderBalanceDiff: shareRateDeltaE27.mul(toBN(1)).div(toBN(e9(1))), + }) + assert.equals(await ethers.provider.getBalance(elRewardsVault), toBN(ETH(4.9)).sub(elBalanceUpdate)) + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(sharesToBurn, 0) + assert.equals(coverShares.add(nonCoverShares), sharesRequestedToBurn) + assert.equals(await lido.balanceOf(burner.address), await lido.getPooledEthByShares(sharesRequestedToBurn)) }) }) From 993c5a68ba6c291f79c9af78b2551b8ae489c1cc Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Mon, 6 Mar 2023 17:56:20 +0400 Subject: [PATCH 145/236] Revert zero deposits with unset wc and not active modules --- contracts/0.8.9/StakingRouter.sol | 47 ++++++++++--------- test/0.4.24/lido.test.js | 6 ++- .../staking-router-deposits.test.js | 2 +- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 8a9767f6f..dfcfa7e26 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -965,40 +965,41 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version ) external payable { if (msg.sender != LIDO_POSITION.getStorageAddress()) revert AppAuthLidoFailed(); + bytes32 withdrawalCredentials = getWithdrawalCredentials(); + if (withdrawalCredentials == 0) revert EmptyWithdrawalsCredentials(); + StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); + if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) + revert StakingModuleNotActive(); - uint256 depositsValue = msg.value; - /// @dev at first, modify the local state to prevent reentrancy + /// @dev firstly update the local state of the contract to prevent a reentrancy attack /// even though the staking modules are trusted contracts stakingModule.lastDepositAt = uint64(block.timestamp); stakingModule.lastDepositBlock = block.number; + + uint256 depositsValue = msg.value; emit StakingRouterETHDeposited(_stakingModuleId, depositsValue); - if (depositsValue == 0) return; if (depositsValue != _depositsCount * DEPOSIT_SIZE) revert InvalidDepositsValue(depositsValue, _depositsCount); - bytes32 withdrawalCredentials = getWithdrawalCredentials(); - if (withdrawalCredentials == 0) revert EmptyWithdrawalsCredentials(); - - if (StakingModuleStatus(stakingModule.status) != StakingModuleStatus.Active) - revert StakingModuleNotActive(); - - (bytes memory publicKeysBatch, bytes memory signaturesBatch) = - IStakingModule(stakingModule.stakingModuleAddress) - .obtainDepositData(_depositsCount, _depositCalldata); - - uint256 etherBalanceBeforeDeposits = address(this).balance; - _makeBeaconChainDeposits32ETH( - _depositsCount, - abi.encodePacked(withdrawalCredentials), - publicKeysBatch, - signaturesBatch - ); - uint256 etherBalanceAfterDeposits = address(this).balance; + if (_depositsCount > 0) { + (bytes memory publicKeysBatch, bytes memory signaturesBatch) = + IStakingModule(stakingModule.stakingModuleAddress) + .obtainDepositData(_depositsCount, _depositCalldata); + + uint256 etherBalanceBeforeDeposits = address(this).balance; + _makeBeaconChainDeposits32ETH( + _depositsCount, + abi.encodePacked(withdrawalCredentials), + publicKeysBatch, + signaturesBatch + ); + uint256 etherBalanceAfterDeposits = address(this).balance; - /// @dev all sent ETH must be deposited and self balance stay the same - assert(etherBalanceBeforeDeposits - etherBalanceAfterDeposits == depositsValue); + /// @dev all sent ETH must be deposited and self balance stay the same + assert(etherBalanceBeforeDeposits - etherBalanceAfterDeposits == depositsValue); + } } /** diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index 57550ae92..1feda53da 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -486,7 +486,11 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody // +1 ETH await web3.eth.sendTransaction({ to: app.address, from: user1, value: ETH(1) }) - await app.methods['deposit(uint256,uint256,bytes)'](MAX_DEPOSITS, CURATED_MODULE_ID, CALLDATA, { from: depositor }) + // can not deposit with unset withdrawalCredentials even with O ETH deposit + await assert.reverts( + app.deposit(MAX_DEPOSITS, CURATED_MODULE_ID, CALLDATA, { from: depositor }), + 'EmptyWithdrawalsCredentials()' + ) await checkStat({ depositedValidators: 0, beaconValidators: 0, beaconBalance: ETH(0) }) assert.equals(await depositContract.totalCalls(), 0) assert.equals(await app.getTotalPooledEther(), ETH(2)) diff --git a/test/0.8.9/staking-router/staking-router-deposits.test.js b/test/0.8.9/staking-router/staking-router-deposits.test.js index 7a5edf0dd..57a7c3e30 100644 --- a/test/0.8.9/staking-router/staking-router-deposits.test.js +++ b/test/0.8.9/staking-router/staking-router-deposits.test.js @@ -215,7 +215,7 @@ contract('StakingRouter', ([depositor, stranger]) => { }) it('zero deposits just updates module lastDepositBlock', async () => { - const depositsCount = 1 + const depositsCount = 0 // allow tx `StakingRouter.deposit()` from the Lido contract addr await ethers.provider.send('hardhat_impersonateAccount', [lido.address]) const value = ETH(0) From eb71d9a49c77b4b8d9cbfac71d0b2f2469e83335 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Fri, 3 Mar 2023 17:16:19 +0200 Subject: [PATCH 146/236] test: fix a burner test --- test/0.8.9/burner.test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/0.8.9/burner.test.js b/test/0.8.9/burner.test.js index 70d1969d5..42ea04ef7 100644 --- a/test/0.8.9/burner.test.js +++ b/test/0.8.9/burner.test.js @@ -130,10 +130,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { }) it(`only Lido can commit shares to burn`, async () => { - assert.revertsWithCustomError( - burner.commitSharesToBurn(0, { from: anotherAccount }), - `AppAuthLidoFailed('${anotherAccount}')` - ) + assert.revertsWithCustomError(burner.commitSharesToBurn(0, { from: anotherAccount }), `AppAuthLidoFailed()`) await burner.commitSharesToBurn(0, { from: lido.address }) }) From 0e8f867059470c8df3699c3749b137d824b23464 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 16:33:07 +0200 Subject: [PATCH 147/236] fix: max shareRate finalization --- contracts/0.4.24/Lido.sol | 10 ++-- contracts/0.8.9/WithdrawalQueue.sol | 4 +- contracts/0.8.9/WithdrawalQueueBase.sol | 49 +++++++++---------- .../WithdrawalQueueERC721Mock.sol | 2 +- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 62052e55c..dd3e0873b 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -118,7 +118,7 @@ interface IWithdrawalQueue { view returns (uint128 eth, uint128 shares); - function finalize(uint256 _lastIdToFinalize) external payable; + function finalize(uint256 _lastIdToFinalize, uint256 _currentShareRate) external payable; function isPaused() external view returns (bool); @@ -828,7 +828,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 _withdrawalsToWithdraw, uint256 _elRewardsToWithdraw, uint256 _lastFinalizableRequestId, - uint256 _etherToLockOnWithdrawalQueue + uint256 _etherToLockOnWithdrawalQueue, + uint256 _simulatedShareRate ) internal { // withdraw execution layer rewards and put them to the buffer if (_elRewardsToWithdraw > 0) { @@ -843,7 +844,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { // finalize withdrawals (send ether, assign shares for burning) if (_etherToLockOnWithdrawalQueue > 0) { IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(_contracts.withdrawalQueue); - withdrawalQueue.finalize.value(_etherToLockOnWithdrawalQueue)(_lastFinalizableRequestId); + withdrawalQueue.finalize.value(_etherToLockOnWithdrawalQueue)(_lastFinalizableRequestId, _simulatedShareRate); } uint256 preBufferedEther = _getBufferedEther(); @@ -1244,7 +1245,8 @@ contract Lido is Versioned, StETHPermit, AragonApp { withdrawals, elRewards, _reportedData.lastFinalizableRequestId, - reportContext.etherToLockOnWithdrawalQueue + reportContext.etherToLockOnWithdrawalQueue, + _reportedData.simulatedShareRate ); emit ETHDistributed( diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 4faf17b60..05691eca6 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -248,8 +248,8 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @dev ether to finalize all the requests should be calculated using `finalizationBatch()` and sent along /// /// @param _nextFinalizedRequestId request index in the queue that will be last finalized request in a batch - function finalize(uint256 _nextFinalizedRequestId) external payable whenResumed onlyRole(FINALIZE_ROLE) { - _finalize(_nextFinalizedRequestId, msg.value); + function finalize(uint256 _nextFinalizedRequestId, uint256 _shareRate) external payable whenResumed onlyRole(FINALIZE_ROLE) { + _finalize(_nextFinalizedRequestId, msg.value, _shareRate); } /// @notice Update bunker mode state diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 74487cec4..76b6a26cb 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -7,6 +7,7 @@ pragma solidity 0.8.9; import "@openzeppelin/contracts-v4.4/utils/structs/EnumerableSet.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; +import {Math} from "./lib/Math.sol"; /// @title Queue to store and manage WithdrawalRequests. /// @dev Use an optimizations to store discounts heavily inspired @@ -20,8 +21,6 @@ abstract contract WithdrawalQueueBase { /// @notice precision base for share rate and discounting factor values in the contract uint256 public constant E27_PRECISION_BASE = 1e27; - /// @dev discount factor value that means no discount applying - uint96 internal constant NO_DISCOUNT = uint96(E27_PRECISION_BASE); /// @dev return value for the `find...` methods in case of no result uint256 internal constant NOT_FOUND = 0; @@ -56,13 +55,10 @@ abstract contract WithdrawalQueueBase { bool claimed; } - /// @notice structure to store discount factors for requests in the queue - struct DiscountCheckpoint { - /// @notice first `_requestId` the discount is valid for - /// @dev storing in uint160 to pack into one slot. Overflowing here is unlikely - uint160 fromRequestId; - /// @notice discount factor with 1e27 precision (0 - 100% discount, 1e27 - means no discount) - uint96 discountFactor; + /// @notice structure to store discounts for requests that are affected by negative rebase + struct Checkpoint { + uint256 fromRequestId; + uint256 maxShareRate; } /// @notice output format struct for `_getWithdrawalStatus()` method @@ -270,7 +266,7 @@ abstract contract WithdrawalQueueBase { /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` /// Emits WithdrawalBatchFinalized event. - function _finalize(uint256 _nextFinalizedRequestId, uint256 _amountOfETH) internal { + function _finalize(uint256 _nextFinalizedRequestId, uint256 _amountOfETH, uint256 _maxShareRate) internal { if (_nextFinalizedRequestId > getLastRequestId()) revert InvalidRequestId(_nextFinalizedRequestId); uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); uint256 firstUnfinalizedRequestId = lastFinalizedRequestId + 1; @@ -282,18 +278,13 @@ abstract contract WithdrawalQueueBase { uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); - uint256 discountFactor = NO_DISCOUNT; - if (stETHToFinalize > _amountOfETH) { - discountFactor = _amountOfETH * E27_PRECISION_BASE / stETHToFinalize; - } uint256 lastCheckpointIndex = getLastCheckpointIndex(); - DiscountCheckpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; + Checkpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; - if (discountFactor != lastCheckpoint.discountFactor) { + if (_maxShareRate != lastCheckpoint.maxShareRate) { // add a new discount if it differs from the previous - _getCheckpoints()[lastCheckpointIndex + 1] = - DiscountCheckpoint(uint160(firstUnfinalizedRequestId), uint96(discountFactor)); + _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstUnfinalizedRequestId, _maxShareRate); _setLastCheckpointIndex(lastCheckpointIndex + 1); } @@ -437,21 +428,29 @@ abstract contract WithdrawalQueueBase { uint256 lastCheckpointIndex = getLastCheckpointIndex(); if (_hint > lastCheckpointIndex) revert InvalidHint(_hint); - DiscountCheckpoint memory hintCheckpoint = _getCheckpoints()[_hint]; + Checkpoint memory checkpoint = _getCheckpoints()[_hint]; // ______(>______ // ^ hint - if (_requestId < hintCheckpoint.fromRequestId) revert InvalidHint(_hint); + if (_requestId < checkpoint.fromRequestId) revert InvalidHint(_hint); if (_hint < lastCheckpointIndex) { // ______(>______(>________ // hint hint+1 ^ - DiscountCheckpoint memory nextCheckpoint = _getCheckpoints()[_hint + 1]; + Checkpoint memory nextCheckpoint = _getCheckpoints()[_hint + 1]; if (nextCheckpoint.fromRequestId <= _requestId) { revert InvalidHint(_hint); } } - uint256 ethRequested = _request.cumulativeStETH - _getQueue()[_requestId - 1].cumulativeStETH; - return ethRequested * hintCheckpoint.discountFactor / E27_PRECISION_BASE; + WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; + + uint256 ethRequested = _request.cumulativeStETH - prevRequest.cumulativeStETH; + uint256 shareRequested = _request.cumulativeShares - prevRequest.cumulativeShares; + + if (ethRequested * E27_PRECISION_BASE / shareRequested <= checkpoint.maxShareRate) { + return ethRequested; + } + + return shareRequested * checkpoint.maxShareRate / E27_PRECISION_BASE; } // quazi-constructor @@ -460,7 +459,7 @@ abstract contract WithdrawalQueueBase { // to avoid uint underflows and related if-branches // 0-index is reserved as 'not_found' response in the interface everywhere _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint64(block.number), true); - _getCheckpoints()[getLastCheckpointIndex()] = DiscountCheckpoint(0, 0); + _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, 0); } function _sendValue(address _recipient, uint256 _amount) internal { @@ -481,7 +480,7 @@ abstract contract WithdrawalQueueBase { } } - function _getCheckpoints() internal pure returns (mapping(uint256 => DiscountCheckpoint) storage checkpoints) { + function _getCheckpoints() internal pure returns (mapping(uint256 => Checkpoint) storage checkpoints) { bytes32 position = CHECKPOINTS_POSITION; assembly { checkpoints.slot := position diff --git a/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol b/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol index 8ab843d98..4fe82c69e 100644 --- a/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol +++ b/contracts/0.8.9/test_helpers/WithdrawalQueueERC721Mock.sol @@ -18,7 +18,7 @@ contract WithdrawalQueueERC721Mock is WithdrawalQueueERC721 { return _getQueue()[id]; } - function getCheckpointItem(uint256 id) external view returns (DiscountCheckpoint memory) { + function getCheckpointItem(uint256 id) external view returns (Checkpoint memory) { return _getCheckpoints()[id]; } } diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 107f524ef..623cb5d60 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 184369ced..6816f15ef 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"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":[],"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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":[{"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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":"_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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"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":[],"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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":[{"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 10d7904048f445aa3446486769c2827e0fe5422e Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 17:44:56 +0300 Subject: [PATCH 148/236] fix: sanity checker tests --- test/0.8.9/oracle-report-sanity-checker.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 93501159e..0d724094d 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -243,7 +243,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa const newRequestId = 2 let oldRequestCreationTimestamp, newRequestCreationTimestamp const correctWithdrawalQueueOracleReport = { - requestIdToFinalizeUpTo: oldRequestId, + lastFinalizableRequestId: oldRequestId, refReportTimestamp: -1, } @@ -262,7 +262,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa oracleReportSanityChecker.checkWithdrawalQueueOracleReport( ...Object.values({ ...correctWithdrawalQueueOracleReport, - requestIdToFinalizeUpTo: newRequestId, + lastFinalizableRequestId: newRequestId, }) ), `IncorrectRequestFinalization(${newRequestCreationTimestamp})` From 583cd3745eeee13f22de037981defa150b1eb7ab Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 16:48:50 +0200 Subject: [PATCH 149/236] fix: wq initial checkpoint fix + test --- contracts/0.8.9/WithdrawalQueueBase.sol | 2 +- test/0.8.9/withdrawal-queue-deploy.test.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 76b6a26cb..853ea762f 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -459,7 +459,7 @@ abstract contract WithdrawalQueueBase { // to avoid uint underflows and related if-branches // 0-index is reserved as 'not_found' response in the interface everywhere _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint64(block.number), true); - _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, 0); + _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, type(uint256).max); } function _sendValue(address _recipient, uint256 _amount) internal { diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index 4c7a4797b..3c7ba3245 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -1,5 +1,5 @@ const { artifacts, contract } = require('hardhat') -const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') +const { ZERO_ADDRESS, MAX_UINT256 } = require('@aragon/contract-helpers-test') const { ETH } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') @@ -126,8 +126,8 @@ contract( assert.equals(queueItem.owner, ZERO_ADDRESS) assert.equals(queueItem.claimed, true) - assert.equals(+checkpointItem.fromRequestId, 0) - assert.equals(+checkpointItem.discountFactor, 0) + assert.equals(checkpointItem.fromRequestId, 0) + assert.equals(checkpointItem.maxShareRate, MAX_UINT256) }) it('check if pauser is zero', async () => { From 9052899a949b0a069b024e11209eb14fdde86121 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 16:50:45 +0200 Subject: [PATCH 150/236] test: fix nft tests --- test/0.8.9/withdrawal-queue-nft.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-nft.test.js b/test/0.8.9/withdrawal-queue-nft.test.js index 985b1373f..41ece8414 100644 --- a/test/0.8.9/withdrawal-queue-nft.test.js +++ b/test/0.8.9/withdrawal-queue-nft.test.js @@ -151,7 +151,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.balanceOf(user), 1) const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 0) @@ -176,7 +176,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(1), user) const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) await assert.reverts(withdrawalQueue.ownerOf(1), 'RequestAlreadyClaimed(1)') @@ -262,7 +262,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(2), user) const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 1) @@ -278,7 +278,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(2), user) const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: stranger }), `NotOwner("${stranger}", "${user}")`) @@ -300,7 +300,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(2), user) const batch = await withdrawalQueue.finalizationBatch(2, shareRate(1)) - await withdrawalQueue.finalize(2, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.finalize(2, shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 1) @@ -325,7 +325,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(1), stranger) const batch = await withdrawalQueue.finalizationBatch(2, shareRate(1)) - await withdrawalQueue.finalize(2, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.finalize(2, shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(2, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 0) @@ -376,7 +376,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(3), stranger) const batch = await withdrawalQueue.finalizationBatch(3, shareRate(1)) - await withdrawalQueue.finalize(3, { from: daoAgent, value: batch.ethToLock }) + await withdrawalQueue.finalize(3, shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) await withdrawalQueue.claimWithdrawal(3, { from: stranger }) From f25416a6dd341e8f9869e06555a9da78ccbd76ba Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 16:51:46 +0200 Subject: [PATCH 151/236] test: partial fix for wq different share rate changes --- ...ithdrawal-queue-share-rate-changes.test.js | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index 959db8d68..31a0705ee 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -82,10 +82,10 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { let claimableEther it(`requests get finalized`, async () => { - await queue.finalize(requestIds[1], { from: finalizer, value: e18(2) }) + await queue.finalize(requestIds[1], e27(1), { from: finalizer, value: e18(2) }) assert.equals(await queue.getLastFinalizedRequestId(), requestIds[1]) - const hints = await queue.findCheckpointHintsUnbounded(requestIds) + const hints = await queue.findCheckpointHints(requestIds, 1, await queue.getLastCheckpointIndex()) claimableEther = await queue.getClaimableEther(requestIds, hints) }) @@ -117,7 +117,6 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives rewards, changing share rate to 2.0`, async () => { - await queue.onPreRebase() await setShareRate(2) }) @@ -128,30 +127,19 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user]) => { }) it(`protocol receives slashing, changing share rate to 1.0`, async () => { - await queue.onPreRebase() await setShareRate(1) }) - let batches - const maxShareRate = e27(1.5) - - it(`both requests can be finalized with 2 ETH`, async () => { - const result = await queue.calculateFinalizationBatches(maxShareRate, MAX_UINT256, [e18(2.5), false, []]) - assert.isTrue(result.finished) - - console.log(result) - - const batch = await queue.prefinalize.call(result.batches, maxShareRate) + it(`both requests can be finalized with 2.5 ETH`, async () => { + const batch = await queue.finalizationBatch(requestIds[1], e27(1.5)) assert.equals(batch.ethToLock, e18(2.5)) assert.equals(batch.sharesToBurn, e18(2)) - - batches = result.batches }) let claimableEther it(`requests get finalized`, async () => { - await queue.finalize(batches, maxShareRate, { from: finalizer, value: e18(2.5) }) + await queue.finalize(requestIds[1], e27(1.5), { from: finalizer, value: e18(2.5) }) assert.equals(await queue.getLastFinalizedRequestId(), requestIds[1]) const hints = await queue.findCheckpointHints(requestIds, 1, await queue.getLastCheckpointIndex()) From e6af423e6b79588bd82d6430dfa947fe10d3b12d Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 17:52:07 +0300 Subject: [PATCH 152/236] fix: handleOracleReport docs --- contracts/0.4.24/Lido.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index dd3e0873b..ac0d4ebfd 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -559,17 +559,17 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer at `_reportTimestamp` * @param _elRewardsVaultBalance elRewards vault balance on Execution Layer at `_reportTimestamp` * @param _sharesRequestedToBurn shares requested to burn through Burner at `_reportTimestamp` - * @param _lastFinalizableRequestId right boundary of requestId range if equals 0, no requests should be finalized + * @param _lastFinalizableRequestId last withdrawal request id to finalize up to * @param _simulatedShareRate share rate that was simulated by oracle when the report data created (1e27 precision) * * NB: `_simulatedShareRate` should be calculated off-chain by calling the method with `eth_call` JSON-RPC API - * while passing `_lastFinalizableRequestId` == `_simulatedShareRate` == 0, and plugging the returned values + * while passing `_lastFinalizableRequestId == 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 + * @return postRebaseAmounts[0]: `postTotalPooledEther` amount of ether in the protocol after report + * @return postRebaseAmounts[1]: `postTotalShares` amount of shares in the protocol after report + * @return postRebaseAmounts[2]: `withdrawals` withdrawn from the withdrawals vault + * @return postRebaseAmounts[3]: `elRewards` withdrawn from the execution layer rewards vault */ function handleOracleReport( // Oracle timings From f080466cfbffb559f0a92557e79725dddc3b01c9 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 18:08:18 +0300 Subject: [PATCH 153/236] fix: Lido bytecode size opts --- contracts/0.4.24/Lido.sol | 33 +++++++++++++++++---------------- test/0.4.24/lido.test.js | 4 ++-- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index ac0d4ebfd..f285706cf 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -269,7 +269,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { onlyInit { uint256 amount = _bootstrapInitialHolder(); - BUFFERED_ETHER_POSITION.setStorageUint256(amount); + _setBufferedEther(amount); emit Submitted(INITIAL_TOKEN_HOLDER, amount, 0); @@ -475,7 +475,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * are treated as a user deposit */ function receiveELRewards() external payable { - require(msg.sender == getLidoLocator().elRewardsVault(), "EXECUTION_LAYER_REWARDS_VAULT_ONLY"); + require(msg.sender == getLidoLocator().elRewardsVault()); TOTAL_EL_REWARDS_COLLECTED_POSITION.setStorageUint256(getTotalELRewardsCollected().add(msg.value)); @@ -709,7 +709,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 depositsValue = depositsCount.mul(DEPOSIT_SIZE); /// @dev firstly update the local state of the contract to prevent a reentrancy attack, /// even if the StakingRouter is a trusted contract. - BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().sub(depositsValue)); + _setBufferedEther(_getBufferedEther().sub(depositsValue)); emit Unbuffered(depositsValue); uint256 newDepositedValidators = DEPOSITED_VALIDATORS_POSITION.getStorageUint256().add(depositsCount); @@ -847,16 +847,12 @@ contract Lido is Versioned, StETHPermit, AragonApp { withdrawalQueue.finalize.value(_etherToLockOnWithdrawalQueue)(_lastFinalizableRequestId, _simulatedShareRate); } - uint256 preBufferedEther = _getBufferedEther(); - uint256 postBufferedEther = preBufferedEther + uint256 postBufferedEther = _getBufferedEther() .add(_elRewardsToWithdraw) // Collected from ELVault .add(_withdrawalsToWithdraw) // Collected from WithdrawalVault .sub(_etherToLockOnWithdrawalQueue); // Sent to WithdrawalQueue - // Storing even the same value costs gas, so just avoid it - if (preBufferedEther != postBufferedEther) { - BUFFERED_ETHER_POSITION.setStorageUint256(postBufferedEther); - } + _setBufferedEther(postBufferedEther); } /** @@ -899,13 +895,12 @@ contract Lido is Versioned, StETHPermit, AragonApp { // See LIP-12 for details: // https://research.lido.fi/t/lip-12-on-chain-part-of-the-rewards-distribution-after-the-merge/1625 if (postCLTotalBalance > _reportContext.preCLBalance) { - uint256 consensusLayerRewards = postCLTotalBalance.sub(_reportContext.preCLBalance); - uint256 totalRewards = consensusLayerRewards.add(_withdrawnElRewards); + uint256 consensusLayerRewards = postCLTotalBalance - _reportContext.preCLBalance; sharesMintedAsFees = _distributeFee( _reportContext.preTotalPooledEther, _reportContext.preTotalShares, - totalRewards + consensusLayerRewards.add(_withdrawnElRewards) ); } } @@ -935,7 +930,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { _mintShares(msg.sender, sharesAmount); - BUFFERED_ETHER_POSITION.setStorageUint256(_getBufferedEther().add(msg.value)); + _setBufferedEther(_getBufferedEther().add(msg.value)); emit Submitted(msg.sender, msg.value, _referral); _emitTransferAfterMintingShares(msg.sender, sharesAmount); @@ -1062,10 +1057,9 @@ contract Lido is Versioned, StETHPermit, AragonApp { uint256 totalFee, uint256 totalRewards ) internal returns (uint256[] memory moduleRewards, uint256 totalModuleRewards) { - totalModuleRewards = 0; moduleRewards = new uint256[](recipients.length); - for (uint256 i = 0; i < recipients.length; i++) { + for (uint256 i; i < recipients.length; ++i) { if (modulesFees[i] > 0) { uint256 iModuleRewards = totalRewards.mul(modulesFees[i]).div(totalFee); moduleRewards[i] = iModuleRewards; @@ -1089,6 +1083,13 @@ contract Lido is Versioned, StETHPermit, AragonApp { return BUFFERED_ETHER_POSITION.getStorageUint256(); } + /** + * @dev Sets the amount of Ether temporary buffered on this contract balance + */ + function _setBufferedEther(uint256 _newBufferedEther) internal { + BUFFERED_ETHER_POSITION.setStorageUint256(_newBufferedEther); + } + /// @dev Calculates and returns the total base balance (multiple of 32) of validators in transient state, /// i.e. submitted to the official Deposit contract but not yet visible in the CL state. /// @return transient balance in wei (1e-18 Ether) @@ -1142,7 +1143,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @param _role Permission name */ function _auth(bytes32 _role) internal view auth(_role) { - // no-op + require(canPerform(msg.sender, _role, new uint256[](0)), "APP_AUTH_FAILED"); } /** diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index c1814c1bf..a18eb4cf2 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -381,14 +381,14 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody await app.setELRewardsWithdrawalLimit(initialValue, { from: voting }) // unable to receive execution layer rewards from arbitrary account - await assert.reverts(app.receiveELRewards({ from: user1, value: ETH(1) }), 'EXECUTION_LAYER_REWARDS_VAULT_ONLY') + await assert.reverts(app.receiveELRewards({ from: user1, value: ETH(1) })) }) }) }) describe('receiveELRewards()', async () => { it('unable to receive eth from arbitrary account', async () => { - await assert.reverts(app.receiveELRewards({ from: nobody, value: ETH(1) }), 'EXECUTION_LAYER_REWARDS_VAULT_ONLY') + await assert.reverts(app.receiveELRewards({ from: nobody, value: ETH(1) })) }) it('event work', async () => { From 1f38383162fb03c61c75ba0a752b21cbb3440382 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 16:55:43 +0200 Subject: [PATCH 154/236] test: fix another nft test --- test/0.8.9/withdrawal-request-nft.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index 61efae021..2135ab006 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -230,8 +230,8 @@ contract('WithdrawalNFT', (addresses) => { }) it('reverts with error "RequestAlreadyClaimed()" when called on claimed request', async () => { - const batch = await withdrawalQueueERC721.finalizationBatch(3, shareRate(1)) - await withdrawalQueueERC721.finalize(3, { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.finalizationBatch(2, shareRate(1)) + await withdrawalQueueERC721.finalize(2, shareRate(1), { from: deployer, value: batch.ethToLock }) const ownerETHBefore = await ethers.provider.getBalance(nftHolderStETH) const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { from: nftHolderStETH, @@ -285,8 +285,8 @@ contract('WithdrawalNFT', (addresses) => { }) assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - const batch = await withdrawalQueueERC721.finalizationBatch(3, shareRate(1)) - await withdrawalQueueERC721.finalize(3, { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.finalizationBatch(2, shareRate(1)) + await withdrawalQueueERC721.finalize(2, shareRate(1), { from: deployer, value: batch.ethToLock }) const recipientETHBefore = await ethers.provider.getBalance(recipient) const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { @@ -310,8 +310,8 @@ contract('WithdrawalNFT', (addresses) => { it('balanceOf decreases after claim', async () => { const balanceBefore = await withdrawalQueueERC721.balanceOf(nftHolderStETH) - const batch = await withdrawalQueueERC721.finalizationBatch(3, shareRate(1)) - await withdrawalQueueERC721.finalize(3, { from: deployer, value: batch.ethToLock }) + const batch = await withdrawalQueueERC721.finalizationBatch(2, shareRate(1)) + await withdrawalQueueERC721.finalize(2, shareRate(1), { from: deployer, value: batch.ethToLock }) await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { from: nftHolderStETH, From f09cbd41a8070b89be1a8c1804333781d04461d4 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 17:01:50 +0200 Subject: [PATCH 155/236] test: fix a bit more wq lhf tests --- test/0.8.9/withdrawal-queue.test.js | 92 +++++++++++++++-------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index d2a5d2013..c26847c32 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -301,8 +301,12 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('Finalizer can finalize a request', async () => { - await assert.revertsOZAccessControl(withdrawalQueue.finalize(1, { from: stranger }), stranger, 'FINALIZE_ROLE') - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await assert.revertsOZAccessControl( + withdrawalQueue.finalize(1, shareRate(300), { from: stranger }), + stranger, + 'FINALIZE_ROLE' + ) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), amount) assert.equals( @@ -312,7 +316,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('One can finalize requests with discount', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(150) }) + await withdrawalQueue.finalize(1, shareRate(150), { from: steth.address, value: ETH(150) }) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(150)) assert.equals( @@ -326,11 +330,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.mintShares(user, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(10) }) + await withdrawalQueue.finalize(1, shareRate(10), { from: steth.address, value: ETH(10) }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(10) }) + await withdrawalQueue.finalize(2, shareRate(10), { from: steth.address, value: ETH(10) }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) }) @@ -342,7 +346,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) const batch = await withdrawalQueue.finalizationBatch(2, shareRate(300)) - await withdrawalQueue.finalize(2, { from: steth.address, value: batch.ethToLock }) + await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: batch.ethToLock }) assert.equals(batch.sharesToBurn, shares(2)) assert.equals(await withdrawalQueue.getLastRequestId(), 2) @@ -361,7 +365,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 1) @@ -371,7 +375,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await ethers.provider.getBalance(withdrawalQueue.address) ) - await withdrawalQueue.finalize(2, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: amount }) assert.equals(await withdrawalQueue.getLastRequestId(), 2) assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), 2) @@ -390,7 +394,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const idAhead = +(await withdrawalQueue.getLastRequestId()) + 1 await assert.reverts( - withdrawalQueue.finalize(idAhead, { from: steth.address, value: amount }), + withdrawalQueue.finalize(idAhead, shareRate(300), { from: steth.address, value: amount }), `InvalidRequestId(${idAhead})` ) @@ -399,10 +403,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('reverts if request with given id was finalized already', async () => { const id = +(await withdrawalQueue.getLastRequestId()) - await withdrawalQueue.finalize(id, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amount }) await assert.reverts( - withdrawalQueue.finalize(id, { from: steth.address, value: amount }), + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amount }), `InvalidRequestId(${id})` ) @@ -414,7 +418,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const amountExceeded = bn(ETH(400)) await assert.reverts( - withdrawalQueue.finalize(id, { from: steth.address, value: amountExceeded }), + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: amountExceeded }), `TooMuchEtherToFinalize(${+amountExceeded}, ${+amount})` ) }) @@ -427,16 +431,16 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('works', async () => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: ETH(1) }) assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(1)) }) it('reverts if last hint checkpoint is ahead of requestId', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(0.5) }) + await withdrawalQueue.finalize(1, shareRate(150), { from: steth.address, value: ETH(0.5) }) await withdrawalQueue.requestWithdrawals([ETH(2)], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(0.5) }) + await withdrawalQueue.finalize(2, shareRate(150), { from: steth.address, value: ETH(0.5) }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') }) @@ -447,7 +451,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('return 0 for claimed request', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: ETH(1) }) await withdrawalQueue.claimWithdrawals([1], [1], { from: owner }) assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(0)) @@ -458,7 +462,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts(withdrawalQueue.getClaimableEther([0], [1]), 'InvalidRequestId(0)') await assert.reverts(withdrawalQueue.getClaimableEther([2], [1]), 'InvalidRequestId(2)') - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: ETH(1) }) await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') await assert.reverts(withdrawalQueue.getClaimableEther([1], [0]), 'InvalidHint(0)') @@ -466,8 +470,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts(withdrawalQueue.getClaimableEther([1], [2]), 'InvalidHint(2)') await withdrawalQueue.requestWithdrawals([ETH(1), ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: ETH(0.99) }) - await withdrawalQueue.finalize(3, { from: steth.address, value: ETH(0.98) }) + await withdrawalQueue.finalize(2, shareRate(300 * 0.99), { from: steth.address, value: ETH(0.99) }) + await withdrawalQueue.finalize(3, shareRate(300 * 0.98), { from: steth.address, value: ETH(0.98) }) await assert.reverts(withdrawalQueue.getClaimableEther([3], [1]), 'InvalidHint(1)') }) @@ -480,7 +484,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('Owner can claim a finalized request to recipient address', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) const balanceBefore = bn(await ethers.provider.getBalance(user)) @@ -502,7 +506,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts if sender is not owner', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) await assert.reverts( withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: stranger }), `NotOwner("${stranger}", "${owner}")` @@ -510,14 +514,14 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts if there is not enough balance', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) await setBalance(withdrawalQueue.address, ETH(200)) await assert.reverts(withdrawalQueue.claimWithdrawalsTo([1], [1], owner, { from: owner }), 'NotEnoughEther()') }) }) it('Owner can claim a finalized request without hint', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) @@ -545,20 +549,20 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize(2, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(2, shareRate(300), { from: steth.address, value: amount }) await assert.reverts(withdrawalQueue.claimWithdrawals([1], [0], { from: owner }), 'InvalidHint(0)') await assert.reverts(withdrawalQueue.claimWithdrawals([1], [2], { from: owner }), 'InvalidHint(2)') }) it('Cant withdraw token two times', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(1, { from: owner }) await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: owner }), 'RequestAlreadyClaimed(1)') }) it('Discounted withdrawals produce less eth', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(150) }) + await withdrawalQueue.finalize(1, shareRate(150), { from: steth.address, value: ETH(150) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) assert.equals(await withdrawalQueue.getLockedEtherAmount(), ETH(150)) @@ -576,7 +580,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.approve(withdrawalQueue.address, StETH(21), { from: user }) assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 0) - await withdrawalQueue.finalize(1, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) for (let i = 1; i <= 20; i++) { assert.equals(await withdrawalQueue.getLastCheckpointIndex(), i) @@ -610,7 +614,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('direct', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, { from: steth.address, value: total }) + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: total }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -622,7 +626,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('reverse', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, { from: steth.address, value: total }) + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: total }) for (let index = requestIds.length - 1; index >= 0; index--) { const requestId = requestIds[index] @@ -636,7 +640,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const randomIds = [...requestIds].sort(() => 0.5 - Math.random()) const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, { from: steth.address, value: total }) + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: total }) for (let index = 0; index < randomIds.length; index++) { const requestId = randomIds[index] @@ -671,7 +675,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const requestIds = await withdrawalQueue.getWithdrawalRequests(user, { from: user }) const id = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(id, { from: steth.address, value: finalizedWEI }) + await withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: finalizedWEI }) const hints = await withdrawalQueue.findCheckpointHintsUnbounded(requestIds) const claimableEth = await withdrawalQueue.getClaimableEther(requestIds, hints) @@ -731,7 +735,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('return zero if no unfinalized request found', async () => { const timestamp = (await withdrawalQueue.getWithdrawalStatus([1]))[0].timestamp - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH[10] }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: ETH(10) }) assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 2, 10), 0) }) @@ -750,7 +754,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, 'InvalidRequestIdRange(0, 11)' ) - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(20) }) + await withdrawalQueue.finalize(1, shareRate(20), { from: steth.address, value: ETH(20) }) await assert.reverts( withdrawalQueue.findLastFinalizableRequestIdByTimestamp(timestamp, 1, 10), 'InvalidRequestIdRange(1, 10)' @@ -783,7 +787,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('return zero if no unfinalized request found', async () => { - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH[10] }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: ETH[10] }) assert.equals(await withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 2, 10), 0) }) @@ -812,7 +816,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, 'InvalidRequestIdRange(0, 11)' ) - await withdrawalQueue.finalize(1, { from: steth.address, value: ETH(20) }) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: ETH(20) }) await assert.reverts( withdrawalQueue.findLastFinalizableRequestIdByBudget(ETH(1), shareRate(300), 1, 10), 'InvalidRequestIdRange(1, 10)' @@ -847,7 +851,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns zero if no unfinalized requests', async () => { - await withdrawalQueue.finalize(10, { from: steth.address, value: ETH[10] }) + await withdrawalQueue.finalize(10, shareRate(300), { from: steth.address, value: ETH[10] }) const timestamp = (await withdrawalQueue.getWithdrawalStatus([10]))[0].timestamp assert.equals(await withdrawalQueue.findLastFinalizableRequestId(ETH(100), shareRate(100), timestamp), 0) @@ -976,7 +980,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('returns not found when indexes have negative overlap', async () => { const batch = await withdrawalQueue.finalizationBatch(requestId, shareRate(300)) - await withdrawalQueue.finalize(requestId, { from: steth.address, value: batch.ethToLock }) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: batch.ethToLock }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints( [requestId], @@ -989,7 +993,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('returns hints array with one item for list from single request id', async () => { const batch = await withdrawalQueue.finalizationBatch(requestId, shareRate(300)) - await withdrawalQueue.finalize(requestId, { from: steth.address, value: batch.ethToLock }) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: batch.ethToLock }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints([requestId], 1, lastCheckpointIndex) assert.equal(hints.length, 1) @@ -997,7 +1001,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('returns correct hints array for given request ids', async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(20) }) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: ETH(20) }) await steth.mintShares(owner, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) @@ -1010,7 +1014,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) const thirdRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(thirdRequestId, { from: steth.address, value: ETH(40) }) + await withdrawalQueue.finalize(thirdRequestId, shareRate(300), { from: steth.address, value: ETH(40) }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() const hints = await withdrawalQueue.findCheckpointHints( @@ -1025,7 +1029,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('reverts with RequestIdsNotSorted error when request ids not in ascending order', async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(20) }) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: ETH(20) }) await steth.mintShares(owner, shares(1)) await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) @@ -1038,7 +1042,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) const thirdRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(thirdRequestId, { from: steth.address, value: ETH(40) }) + await withdrawalQueue.finalize(thirdRequestId, shareRate(300), { from: steth.address, value: ETH(40) }) const lastCheckpointIndex = await withdrawalQueue.getLastCheckpointIndex() await assert.reverts( @@ -1062,7 +1066,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const secondRequestAmount = ETH(10) await withdrawalQueue.requestWithdrawals([secondRequestAmount], owner, { from: owner }) const secondRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(secondRequestId, { from: steth.address, value: ETH(30) }) + await withdrawalQueue.finalize(secondRequestId, shareRate(300), { from: steth.address, value: ETH(30) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) const tx = await withdrawalQueue.claimWithdrawals([1, 2], [1, 1], { from: owner }) @@ -1169,7 +1173,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it("One can't change claimed request", async () => { - await withdrawalQueue.finalize(requestId, { from: steth.address, value: amount }) + await withdrawalQueue.finalize(requestId, shareRate(300), { from: steth.address, value: amount }) await withdrawalQueue.claimWithdrawal(requestId, { from: user }) await assert.reverts( From 5ed56673f950075fc59c865ba3b8ec41c11717fc Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 17:12:03 +0200 Subject: [PATCH 156/236] test: remove undounded findHints --- test/0.8.9/withdrawal-queue.test.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index c26847c32..796d64d59 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -677,7 +677,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const id = await withdrawalQueue.getLastRequestId() await withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: finalizedWEI }) - const hints = await withdrawalQueue.findCheckpointHintsUnbounded(requestIds) + const hints = await withdrawalQueue.findCheckpointHints( + requestIds, + 1, + await withdrawalQueue.getLastCheckpointIndex() + ) const claimableEth = await withdrawalQueue.getClaimableEther(requestIds, hints) const totalClaimable = claimableEth.reduce((s, i) => s.iadd(i) && s, bn(0)) assert.equals(totalClaimable, finalizedWEI, `Total Claimable doesn't add up to finalized amount`) @@ -880,14 +884,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, } assert.equals(await withdrawalQueue.getLastCheckpointIndex(), numOfRequests) assert.equals( - await withdrawalQueue.findCheckpointHintsUnbounded([await withdrawalQueue.getLastFinalizedRequestId()]), - await withdrawalQueue.getLastCheckpointIndex() - ) - }) - - it('works unbounded', async () => { - assert.equals( - await withdrawalQueue.findCheckpointHintsUnbounded([10]), + await withdrawalQueue.findCheckpointHints( + [await withdrawalQueue.getLastFinalizedRequestId()], + 1, + await withdrawalQueue.getLastCheckpointIndex() + ), await withdrawalQueue.getLastCheckpointIndex() ) }) @@ -895,12 +896,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('reverts if request is not finalized', async () => { await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) await assert.reverts(withdrawalQueue.findCheckpointHints([11], 1, 10), 'RequestNotFoundOrNotFinalized(11)') - await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([11]), 'RequestNotFoundOrNotFinalized(11)') }) it('reverts if there is no such a request', async () => { await assert.reverts(withdrawalQueue.findCheckpointHints([12], 1, 10), 'RequestNotFoundOrNotFinalized(12)') - await assert.reverts(withdrawalQueue.findCheckpointHintsUnbounded([12]), 'RequestNotFoundOrNotFinalized(12)') }) it('range search (found)', async () => { From b9778d4ee23fb16def620bc73d013abee9a4c92e Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 18:12:57 +0300 Subject: [PATCH 157/236] chore: fix Lido docs --- 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 f285706cf..c1953851a 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -559,7 +559,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @param _withdrawalVaultBalance withdrawal vault balance on Execution Layer at `_reportTimestamp` * @param _elRewardsVaultBalance elRewards vault balance on Execution Layer at `_reportTimestamp` * @param _sharesRequestedToBurn shares requested to burn through Burner at `_reportTimestamp` - * @param _lastFinalizableRequestId last withdrawal request id to finalize up to + * @param _lastFinalizableRequestId last withdrawal request id to finalize up to, pass 0 to not finalize requests * @param _simulatedShareRate share rate that was simulated by oracle when the report data created (1e27 precision) * * NB: `_simulatedShareRate` should be calculated off-chain by calling the method with `eth_call` JSON-RPC API From 495772bae628f4d1321e3e50ecfb77c59264b289 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 18:18:53 +0300 Subject: [PATCH 158/236] fix: bump ifaces in Lido --- contracts/0.4.24/Lido.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index c1953851a..ad703bd6a 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -67,7 +67,7 @@ interface IOracleReportSanityChecker { uint256 _postTotalPooledEther, uint256 _postTotalShares, uint256 _etherLockedOnWithdrawalQueue, - uint256 _sharesBurntFromWithdrawalQueue, + uint256 _sharesBurntDueToWithdrawals, uint256 _simulatedShareRate ) external view; } @@ -113,12 +113,12 @@ interface IStakingRouter { } interface IWithdrawalQueue { - function finalizationBatch(uint256 _newLastFinalizedRequestId, uint256 _shareRate) + function finalizationBatch(uint256 _nextFinalizedRequestId, uint256 _shareRate) external view - returns (uint128 eth, uint128 shares); + returns (uint256 ethToLock, uint256 sharesToBurn); - function finalize(uint256 _lastIdToFinalize, uint256 _currentShareRate) external payable; + function finalize(uint256 _nextFinalizedRequestId, uint256 _shareRate) external payable; function isPaused() external view returns (bool); From 433f546feb4ee844a64d53a0a61c4cfe532a74b7 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 18:20:21 +0300 Subject: [PATCH 159/236] chore: clean cmd --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 976ea1485..b70bc98b8 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "test:e2e": "npm run compile && ava -T 1000000 -v", "estimate-deposit-loop-gas": "yarn run test:unit ./estimate_deposit_loop_gas.js", "compile": "hardhat compile && yarn extract-abi", + "clean": "hardhat clean", "extract-abi": "node ./scripts/extract-abi.js", "size-contracts": "yarn run hardhat size-contracts", "deploy": "yarn run deploy:all", From e9e7fca02076fa41d55380aa849f2ee18984a3f8 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 17:23:35 +0200 Subject: [PATCH 160/236] =?UTF-8?q?=E2=9A=A1:wq=20contract=20size=20optimi?= =?UTF-8?q?zation=20with=20modifiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueue.sol | 16 ++++++++-------- contracts/0.8.9/utils/PausableUntil.sol | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 05691eca6..3bcced86b 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -83,13 +83,16 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } /// @notice Resume withdrawal requests placement and finalization - function resume() external whenPaused onlyRole(RESUME_ROLE) { + function resume() external { + _checkPaused(); + _checkRole(RESUME_ROLE, msg.sender); _resume(); } /// @notice Pause withdrawal requests placement and finalization. Claiming finalized requests will still be available /// @param _duration pause duration, seconds (use `PAUSE_INFINITELY` for unlimited) - function pause(uint256 _duration) external onlyRole(PAUSE_ROLE) { + function pause(uint256 _duration) external { + _checkRole(PAUSE_ROLE, msg.sender); _pause(_duration); } @@ -101,9 +104,9 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @return requestIds an array of the created withdrawal requests function requestWithdrawals(uint256[] calldata amounts, address _owner) public - whenResumed returns (uint256[] memory requestIds) { + _checkResumed(); if (_owner == address(0)) _owner = msg.sender; requestIds = new uint256[](amounts.length); for (uint256 i = 0; i < amounts.length; ++i) { @@ -130,7 +133,6 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @return requestIds an array of the created withdrawal requests function requestWithdrawalsWithPermit(uint256[] calldata _amounts, address _owner, PermitInput calldata _permit) external - whenResumed returns (uint256[] memory requestIds) { STETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s); @@ -257,10 +259,8 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// /// @param _isBunkerModeNow oracle report /// @param _sinceTimestamp timestamp of start of the bunker mode - function updateBunkerMode(bool _isBunkerModeNow, uint256 _sinceTimestamp) - external - onlyRole(BUNKER_MODE_REPORT_ROLE) - { + function updateBunkerMode(bool _isBunkerModeNow, uint256 _sinceTimestamp) external { + _checkRole(BUNKER_MODE_REPORT_ROLE, msg.sender); if (_sinceTimestamp >= block.timestamp) revert InvalidReportTimestamp(); bool isBunkerModeWasSetBefore = isBunkerModeActive(); diff --git a/contracts/0.8.9/utils/PausableUntil.sol b/contracts/0.8.9/utils/PausableUntil.sol index 0fe8a8356..6560f5d12 100644 --- a/contracts/0.8.9/utils/PausableUntil.sol +++ b/contracts/0.8.9/utils/PausableUntil.sol @@ -24,18 +24,26 @@ contract PausableUntil { /// @notice Reverts when resumed modifier whenPaused() { - if (!isPaused()) { - revert PausedExpected(); - } + _checkPaused(); _; } /// @notice Reverts when paused modifier whenResumed() { + _checkResumed(); + _; + } + + function _checkPaused() internal view { + if (!isPaused()) { + revert PausedExpected(); + } + } + + function _checkResumed() internal view { if (isPaused()) { revert ResumedExpected(); } - _; } /// @notice Returns whether the contract is paused From 7c3ca2a6b73776d29504eb6f69ca773d39c1fec3 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 18:42:20 +0300 Subject: [PATCH 161/236] fix: remove extra `auth` modifier call --- 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 ad703bd6a..a777b24ed 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -1142,7 +1142,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { * @dev Size-efficient analog of the `auth(_role)` modifier * @param _role Permission name */ - function _auth(bytes32 _role) internal view auth(_role) { + function _auth(bytes32 _role) internal view { require(canPerform(msg.sender, _role, new uint256[](0)), "APP_AUTH_FAILED"); } From f915bbffa408703742bad7dc90055f21e4d47dfb Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 17:46:57 +0200 Subject: [PATCH 162/236] =?UTF-8?q?=F0=9F=92=85:=20lint=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ido-wq-acct-oracle-integration-gas.test.js | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js index c4c3b88f5..55d540fc7 100644 --- a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js +++ b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js @@ -1,32 +1,30 @@ +const { contract, artifacts } = require('hardhat') const { BN } = require('bn.js') const { assert } = require('../helpers/assert') const { MAX_UINT256 } = require('../helpers/constants') const { ZERO_ADDRESS, toBN, e9, e18, e27, toStr } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') -const { prepareOracleReport, reportOracle, getSecondsPerFrame, getSlotTimestamp } = require('../helpers/oracle') +const { reportOracle, getSecondsPerFrame, getSlotTimestamp } = require('../helpers/oracle') const { advanceChainTime } = require('../helpers/blockchain') const { processNamedTuple } = require('../helpers/debug') const StakingModuleMock = artifacts.require('StakingModuleMock') - -function piecewiseModN({values, pointsPerValue, x}) { +function piecewiseModN({ values, pointsPerValue, x }) { const iValue = Math.floor(x / pointsPerValue) const leftValue = values[iValue % values.length] const rightValue = values[(iValue + 1) % values.length] - return leftValue + (rightValue - leftValue) * (x % pointsPerValue) / pointsPerValue + return leftValue + ((rightValue - leftValue) * (x % pointsPerValue)) / pointsPerValue } - -contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, user, user2, stranger]) => { - +contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, user, user2]) => { const test = (numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema) => { let lido, router, wQueue, oracle, consensus, voting, stakingModule, stakingModuleId let secondsPerFrame before('deploy contracts', async () => { const deployed = await deployProtocol({ - stakingModulesFactory: async (protocol) => { + stakingModulesFactory: async () => { stakingModule = await StakingModuleMock.new() return [ { @@ -123,11 +121,13 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use let shareRateBP for (let i = 0; i < numRebases; ++i) { - shareRateBP = Math.floor(piecewiseModN({ - values: shareRatesBP, - pointsPerValue: rebasesPerShareRateExtrema, - x: i - })) + shareRateBP = Math.floor( + piecewiseModN({ + values: shareRatesBP, + pointsPerValue: rebasesPerShareRateExtrema, + x: i, + }) + ) context(`rebase ${i}, share rate: ${shareRateBP / 10000}`, () => { before(async () => { @@ -141,7 +141,7 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use await wQueue.requestWithdrawals(amounts, user, { from: user }) }) - if (i == numRebases - 1) { + if (i === numRebases - 1) { it(`users submit enough ETH to buffer to fullfill all withdrawals`, async () => { // twice as much ETH will be enough in all scenarios await lido.submit(ZERO_ADDRESS, { from: user2, value: toBN(userBalance).muln(2) }) @@ -154,7 +154,7 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use const finalShareRate27 = e27(finalShareRateBP / 10000) context(`share rate: ${finalShareRateBP / 10000}`, () => { - let batches, totals, oracleReportFields, ethAvailForWithdrawals + let oracleReportFields, ethAvailForWithdrawals it(`calculating available ETH`, async () => { const { refSlot } = await consensus.getCurrentFrame() @@ -216,8 +216,6 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use console.log(`calcState ${i}:`, processNamedTuple(calcState)) ++i } - - batches = calcState.batches }) it.skip(`oracle report`, async () => { @@ -228,7 +226,8 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use context('handleOracleReport gas consumption', () => { const testWithParams = (numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema) => { - const desc = `rebases: ${numRebases}, requests per rebase: ${withdrawalRequestsPerRebase}, ` + + const desc = + `rebases: ${numRebases}, requests per rebase: ${withdrawalRequestsPerRebase}, ` + `rebases per extrema: ${rebasesPerShareRateExtrema}` context(desc, () => test(numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema)) } From 2e8beba481f0f04a653203090553ad4fde29821a Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 17:50:16 +0200 Subject: [PATCH 163/236] fix: forgotten part of size optimization --- contracts/0.8.9/WithdrawalQueue.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 3bcced86b..8974231d6 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -250,7 +250,10 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @dev ether to finalize all the requests should be calculated using `finalizationBatch()` and sent along /// /// @param _nextFinalizedRequestId request index in the queue that will be last finalized request in a batch - function finalize(uint256 _nextFinalizedRequestId, uint256 _shareRate) external payable whenResumed onlyRole(FINALIZE_ROLE) { + function finalize(uint256 _nextFinalizedRequestId, uint256 _shareRate) external payable { + _checkResumed(); + _checkRole(FINALIZE_ROLE, msg.sender); + _finalize(_nextFinalizedRequestId, msg.value, _shareRate); } From caa319717820c4904c658b0fb6927c8dd9c01e13 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 6 Mar 2023 19:07:28 +0300 Subject: [PATCH 164/236] chore: add forgotten changes --- .../sanity_checks/OracleReportSanityChecker.sol | 7 +++---- test/scenario/lido_happy_path.test.js | 14 ++++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index ecad9f8ec..0f3e37c55 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -478,8 +478,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { } /// @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 _lastFinalizableRequestId last finalizable withdrawal request id /// @param _reportTimestamp timestamp when the originated oracle report was submitted function checkWithdrawalQueueOracleReport( uint256 _lastFinalizableRequestId, @@ -491,7 +490,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { LimitsList memory limitsList = _limits.unpack(); address withdrawalQueue = LIDO_LOCATOR.withdrawalQueue(); - _checkRequestIdToFinalizeUpTo(limitsList, withdrawalQueue, _lastFinalizableRequestId, _reportTimestamp); + _checkLastFinalizableId(limitsList, withdrawalQueue, _lastFinalizableRequestId, _reportTimestamp); } /// @notice Applies sanity checks to the simulated share rate for withdrawal requests finalization @@ -601,7 +600,7 @@ contract OracleReportSanityChecker is AccessControlEnumerable { if (_appearedValidators > churnLimit) revert IncorrectAppearedValidators(_appearedValidators); } - function _checkRequestIdToFinalizeUpTo( + function _checkLastFinalizableId( LimitsList memory _limitsList, address _withdrawalQueue, uint256 _lastFinalizableId, diff --git a/test/scenario/lido_happy_path.test.js b/test/scenario/lido_happy_path.test.js index 54a764802..b83bfea19 100644 --- a/test/scenario/lido_happy_path.test.js +++ b/test/scenario/lido_happy_path.test.js @@ -89,13 +89,15 @@ contract('Lido: happy path', (addresses) => { // Total fee is 10% const totalFeePoints = 0.1 * 10000 - it('voting sets fee and its distribution', async () => { + it.skip('voting sets fee and its distribution', async () => { // Fee and distribution were set - // assert.equals(await pool.getFee({ from: nobody }), totalFeePoints, 'total fee') - // const distribution = await pool.getFeeDistribution({ from: nobody }) - // console.log('distribution', distribution) - // assert.equals(distribution.treasuryFeeBasisPoints, treasuryFeePoints, 'treasury fee') - // assert.equals(distribution.operatorsFeeBasisPoints, nodeOperatorsFeePoints, 'node operators fee') + assert.equals(await pool.getFee({ from: nobody }), totalFeePoints, 'total fee') + const distribution = await pool.getFeeDistribution({ from: nobody }) + console.log('distribution', distribution) + const treasuryFeePoints = 0 // TODO + const nodeOperatorsFeePoints = 0 // TODO + assert.equals(distribution.treasuryFeeBasisPoints, treasuryFeePoints, 'treasury fee') + assert.equals(distribution.operatorsFeeBasisPoints, nodeOperatorsFeePoints, 'node operators fee') }) it('voting sets withdrawal credentials', async () => { From 1260dd3d2ae899d47f02be78af95ada329efd71f Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 6 Mar 2023 20:09:04 +0200 Subject: [PATCH 165/236] feat: remove extrema handling --- contracts/0.8.9/WithdrawalQueueBase.sol | 245 ++++-------------------- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 4 files changed, 43 insertions(+), 208 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 80f753d9f..a1da71691 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -6,7 +6,6 @@ pragma solidity 0.8.9; import "@openzeppelin/contracts-v4.4/utils/structs/EnumerableSet.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; -import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; import {Math} from "./lib/Math.sol"; import {MemUtils} from "../common/lib/MemUtils.sol"; @@ -18,7 +17,6 @@ import {MemUtils} from "../common/lib/MemUtils.sol"; abstract contract WithdrawalQueueBase { using EnumerableSet for EnumerableSet.UintSet; using UnstructuredStorage for bytes32; - using UnstructuredRefStorage for bytes32; /// @notice precision base for share rate and discounting factor values in the contract uint256 internal constant E27_PRECISION_BASE = 1e27; @@ -46,10 +44,6 @@ abstract contract WithdrawalQueueBase { bytes32 internal constant LOCKED_ETHER_AMOUNT_POSITION = keccak256("lido.WithdrawalQueue.lockedEtherAmount"); /// @dev withdrawal requests mapped to the owners bytes32 internal constant REQUEST_BY_OWNER_POSITION = keccak256("lido.WithdrawalQueue.requestsByOwner"); - /// @dev list of extremum requests for shareRate(request_id) function - bytes32 internal constant EXTREMA_POSITION = keccak256("lido.WithdrawalQueue.extrema"); - /// @dev last extreum index that was already checked for finalization - bytes32 internal constant LAST_CHECKED_EXTREMUM_POSITION = keccak256("lido.WithdrawalQueue.lastCheckedExtremum"); /// @dev timestamp of the last oracle report bytes32 internal constant LAST_REPORT_TIMESTAMP_POSITION = keccak256("lido.WithdrawalQueue.lastReportTimestamp"); @@ -213,55 +207,40 @@ abstract contract WithdrawalQueueBase { { if (_state.finished || _state.ethBudget == 0) revert InvalidState(); - uint256 batchesLength; + uint256 lastRequestId = getLastRequestId(); + uint256 requestId; uint256 prevShareRate; + uint256 batchesLength; if (_state.batches.length == 0) { requestId = getLastFinalizedRequestId() + 1; // we'll store batches as a array where [MAX_BATCHES_LENGTH] element is the array's length _state.batches = new uint256[](MAX_BATCHES_LENGTH + 1); } else { batchesLength = _state.batches[MAX_BATCHES_LENGTH]; - requestId = _state.batches[batchesLength] + 1; - prevShareRate = _calcShareRate(_state.batches[batchesLength], _maxShareRate); - } - - uint256 lastRequestId = getLastRequestId(); + uint256 lastHandledRequestId = _state.batches[batchesLength - 1]; + (prevShareRate,,) = _calcBatch(_getQueue()[lastHandledRequestId - 1], _getQueue()[lastHandledRequestId]); - uint256 firstUncheckedExtremum = _getLastCheckedExtremum() + 1; - uint256 extremaCounter; + requestId = lastHandledRequestId + 1; + } while (requestId < requestId + MAX_REQUESTS_PER_CALL) { - // end of the queue break - if (requestId > lastRequestId) break; - - if ( - firstUncheckedExtremum + extremaCounter < _getExtrema().length && - requestId == _getExtrema()[firstUncheckedExtremum + extremaCounter] - ) { - // max extrema counter break - // we can't allow that batches covers unbounded number of extrema - // it'll require an unbounded loop to check them onchain - unchecked { ++extremaCounter; } - if (extremaCounter > MAX_BATCHES_LENGTH) break; - } + if (requestId > lastRequestId) break; // end of the queue break WithdrawalRequest memory request = _getQueue()[requestId]; // max timestamp break if (request.timestamp > _maxTimestamp) break; WithdrawalRequest memory prevRequest = _getQueue()[requestId - 1]; - uint256 ethToFinalize = request.cumulativeStETH - prevRequest.cumulativeStETH; - uint256 shareRequested = request.cumulativeShares - prevRequest.cumulativeShares; - uint256 requestShareRate = ethToFinalize * E27_PRECISION_BASE / shareRequested; + (uint256 requestShareRate, uint256 ethToFinalize, uint256 shares) = _calcBatch(prevRequest, request); if (requestShareRate > _maxShareRate) { - ethToFinalize = shareRequested * _maxShareRate / E27_PRECISION_BASE; + ethToFinalize = (shares * _maxShareRate) / E27_PRECISION_BASE; } - // budget break - if (ethToFinalize > _state.ethBudget) break; + if (ethToFinalize > _state.ethBudget) break; // budget break + _state.ethBudget -= ethToFinalize; if (batchesLength != 0 && ( @@ -271,6 +250,8 @@ abstract contract WithdrawalQueueBase { )) { _state.batches[batchesLength - 1] = requestId; } else { + if (batchesLength == MAX_BATCHES_LENGTH) break; // gas limit break + _state.batches[batchesLength] = requestId; batchesLength = ++_state.batches[MAX_BATCHES_LENGTH]; } @@ -294,101 +275,42 @@ abstract contract WithdrawalQueueBase { /// @return sharesToBurn amount of shares that belongs tho finalizable requests function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate) external + view returns (uint256 ethToLock, uint256 sharesToBurn) { if (_maxShareRate == 0) revert ZeroShareRate(); if (_batches.length == 0) revert EmptyBatches(); - uint256 lastIdInBatch = _batches[_batches.length - 1]; - if (lastIdInBatch > getLastRequestId()) revert InvalidRequestId(lastIdInBatch); + if (_batches[0] <= getLastFinalizedRequestId()) revert InvalidRequestId(_batches[0]); + if (_batches[_batches.length - 1] > getLastRequestId()) revert InvalidRequestId(_batches[_batches.length - 1]); - uint256 firstIdInBatch = _batches[0]; - if (firstIdInBatch <= getLastFinalizedRequestId()) revert InvalidRequestId(firstIdInBatch); + WithdrawalRequest memory prevBatchEnd = _getQueue()[getLastFinalizedRequestId()]; + uint256 prevBatchShareRate; - _setLastCheckedExtremum(_checkFinalizationBatchesIntegrity(_batches, _maxShareRate)); - - uint256 preBatchStartId = getLastFinalizedRequestId(); uint256 batchIndex; - do { - WithdrawalRequest memory batchStart = _getQueue()[preBatchStartId]; WithdrawalRequest memory batchEnd = _getQueue()[_batches[batchIndex]]; - uint256 shares = batchEnd.cumulativeShares - batchStart.cumulativeShares; - uint256 eth = batchEnd.cumulativeStETH - batchStart.cumulativeStETH; + (uint256 batchShareRate, uint256 stETH, uint256 shares) = _calcBatch(prevBatchEnd, batchEnd); + + if (batchIndex > 0) { + // - if shareRate(batch[i]) is below _maxShareRate => shareRate(batch[i+1]) is above and vice versa + if (batchShareRate <= _maxShareRate && prevBatchShareRate <= _maxShareRate) revert InvalidBatch(batchIndex); + if (batchShareRate > _maxShareRate && prevBatchShareRate > _maxShareRate) revert InvalidBatch(batchIndex); + } - uint256 batchShareRate = (eth * E27_PRECISION_BASE) / shares; - // todo: check equality if (batchShareRate > _maxShareRate) { ethToLock += shares * _maxShareRate / E27_PRECISION_BASE; } else { - ethToLock += eth; + ethToLock += stETH; } - sharesToBurn += shares; - preBatchStartId = _batches[batchIndex]; + prevBatchShareRate = batchShareRate; + prevBatchEnd = batchEnd; unchecked{ ++batchIndex; } } while (batchIndex < _batches.length); } - /// @dev checks batches integrity across extrema list and `_maxShareRate` value and reverts if something is wrong - /// Invariants checked - /// - if shareRate(batch[i]) is below _maxShareRate => shareRate(batch[i+1]) is above and vice versa - /// - if batch includes an extremum: - /// shareRate(extremum) is above the _maxShareRate if shareRate(batch) is above it - /// shareRate(extremum) is below the _maxShareRate if shareRate(batch) is below it - function _checkFinalizationBatchesIntegrity(uint256[] memory _batches, uint256 _maxShareRate) - internal - view - returns (uint256 lastCheckedExtremum) - { - uint256 batchIndex = 0; - uint256 batchPreStartId = getLastFinalizedRequestId(); - uint256 batchEndId = _batches[batchIndex]; - - uint256 extremumIndex = _getLastCheckedExtremum(); - uint256 extremumLength = _getExtrema().length; - uint256 extremumId = _getExtrema()[extremumIndex]; - - uint256 batchShareRate= _calcShareRate( - _getQueue()[batchPreStartId], - _getQueue()[batchEndId], - SHARE_RATE_UNLIMITED - ); - - while (batchIndex < _batches.length - 1) { - if (extremumId <= batchEndId && extremumIndex < extremumLength - 1) { - if (extremumId > batchPreStartId) { - // check extremum - uint256 extremumShareRate = _calcShareRate(extremumId, SHARE_RATE_UNLIMITED); - - if (extremumShareRate > _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatch(batchIndex); - if (extremumShareRate <= _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatch(batchIndex); - } - unchecked { ++extremumIndex; } - } else { - // check crossing point - uint256 nextBatchShareRate = _calcShareRate( - _getQueue()[batchEndId], - _getQueue()[_batches[batchIndex + 1]], - SHARE_RATE_UNLIMITED - ); - // avg batch rate before crossing point and after crossing point - // can't be both below `_maxShareRate` - if (batchShareRate <= _maxShareRate && nextBatchShareRate <= _maxShareRate) revert InvalidBatch(batchIndex); - - // avg batch rate before crossing point and after crossing point - // can't be both above `_maxShareRate` - if (batchShareRate > _maxShareRate && nextBatchShareRate > _maxShareRate) revert InvalidBatch(batchIndex); - - batchShareRate = nextBatchShareRate; - batchPreStartId = batchEndId; - unchecked { ++batchIndex; } - } - } - - return extremumIndex; - } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` /// Emits WithdrawalBatchFinalized event. @@ -460,63 +382,9 @@ abstract contract WithdrawalQueueBase { _getQueue()[requestId] = newRequest; assert(_getRequestsByOwner()[_owner].add(requestId)); - _populateExtrema(lastRequest, newRequest, requestId); - emit WithdrawalRequested(requestId, msg.sender, _owner, _amountOfStETH, _amountOfShares); } - /// @dev storing extrema of shareRate(requestId) function using three points: - /// newRequestId, prevRequestId and last known extremum id - /// - first request is always included as an extremum - /// - last request is not added by default to avoid storage write on each request - /// but speaking strictly last request is also an extremum - /// - if a lot of requests in a row have the same shareRate, the last one - /// will become an exremum as shareRate changes - function _populateExtrema( - WithdrawalRequest memory prevRequest, - WithdrawalRequest memory newRequest, - uint256 newRequestId - ) internal { - // shortcut for the same shareRate batches - // requests is guaranteed to be the same shareRate if they belong to - // the same oracle report period - if (prevRequest.reportTimestamp == newRequest.reportTimestamp) return; - - uint256[] storage extrema = _getExtrema(); - if (extrema.length == 1) { - extrema.push(newRequestId); // first request is always an extremum - return; - } - - uint256 newRequestShareRate = _calcShareRate(prevRequest, newRequest, SHARE_RATE_UNLIMITED); - uint256 prevRequestShareRate = _calcShareRate(newRequestId - 1, SHARE_RATE_UNLIMITED); - - // we can get a new extremum only when shareRate changes - // there can't be rounding jitter because we skipped on the same report requests in the beginning - if (newRequestShareRate == prevRequestShareRate) return; - - uint256 lastExtremumId = extrema[extrema.length - 1]; - WithdrawalRequest memory lastExtremumRequest = _getQueue()[lastExtremumId]; - - uint256 lastExtremumShareRate = _calcShareRate(lastExtremumId, lastExtremumRequest); - - bool wasGrowing = lastExtremumShareRate < prevRequestShareRate; - // | * - // |• • - // +-------> - if (wasGrowing && prevRequestShareRate > newRequestShareRate) { - extrema.push(newRequestId - 1); - return; - } - // |• • - // | * - // +-------> - if (!wasGrowing && prevRequestShareRate < newRequestShareRate) { - extrema.push(newRequestId - 1); - return; - } - } - /// @notice Returns status of the withdrawal request with `_requestId` id function _getStatus(uint256 _requestId) internal view returns (WithdrawalRequestStatus memory status) { if (_requestId == 0 || _requestId > getLastRequestId()) revert InvalidRequestId(_requestId); @@ -636,15 +504,13 @@ abstract contract WithdrawalQueueBase { } WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; + (uint256 batchShareRate, uint256 stETH, uint256 shares) = _calcBatch(prevRequest, _request); - uint256 ethRequested = _request.cumulativeStETH - prevRequest.cumulativeStETH; - uint256 shareRequested = _request.cumulativeShares - prevRequest.cumulativeShares; - - if (ethRequested * E27_PRECISION_BASE / shareRequested <= checkpoint.maxShareRate) { - return ethRequested; + if (batchShareRate <= checkpoint.maxShareRate) { + return stETH; } - return shareRequested * checkpoint.maxShareRate / E27_PRECISION_BASE; + return shares * checkpoint.maxShareRate / E27_PRECISION_BASE; } // quazi-constructor @@ -654,7 +520,6 @@ abstract contract WithdrawalQueueBase { // 0-index is reserved as 'not_found' response in the interface everywhere _getQueue()[0] = WithdrawalRequest(0, 0, address(0), uint40(block.timestamp), true, 0); _getCheckpoints()[getLastCheckpointIndex()] = Checkpoint(0, 0); - _getExtrema().push(0); } function _sendValue(address _recipient, uint256 _amount) internal { @@ -665,33 +530,15 @@ abstract contract WithdrawalQueueBase { if (!success) revert CantSendValueRecipientMayHaveReverted(); } - /// calculate avg share rate for the batch of (_preStartRequest, _endRequest] - function _calcShareRate( + /// @dev calculate batch stats for the batch of `(_preStartRequest, _endRequest]` + function _calcBatch( WithdrawalRequest memory _preStartRequest, - WithdrawalRequest memory _endRequest, - uint256 _maxShareRate - ) internal pure returns (uint256 shareRate) { - uint256 ethRequested = _endRequest.cumulativeStETH - _preStartRequest.cumulativeStETH; - uint256 shareRequested = _endRequest.cumulativeShares - _preStartRequest.cumulativeShares; - - return Math.min(ethRequested * E27_PRECISION_BASE / shareRequested, _maxShareRate); - } - - function _calcShareRate(uint256 _requestId, uint256 _maxShareRate) internal view returns (uint256) { - WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; - WithdrawalRequest memory lastRequest = _getQueue()[_requestId]; - - return _calcShareRate(prevRequest, lastRequest, _maxShareRate); - } - - function _calcShareRate(uint256 _requestId, WithdrawalRequest memory request) - internal - view - returns (uint256) - { - WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; + WithdrawalRequest memory _endRequest + ) internal pure returns (uint256 shareRate, uint256 stETH, uint256 shares) { + stETH = _endRequest.cumulativeStETH - _preStartRequest.cumulativeStETH; + shares = _endRequest.cumulativeShares - _preStartRequest.cumulativeShares; - return _calcShareRate(prevRequest, request, SHARE_RATE_UNLIMITED); + shareRate = stETH * E27_PRECISION_BASE / shares; } // @@ -722,14 +569,6 @@ abstract contract WithdrawalQueueBase { } } - function _getExtrema() internal pure returns (uint256[] storage) { - return EXTREMA_POSITION.storageUint256Array(); - } - - function _getLastCheckedExtremum() internal view returns (uint256) { - return LAST_CHECKED_EXTREMUM_POSITION.getStorageUint256(); - } - function _getLastReportTimestamp() internal view returns (uint256) { return LAST_REPORT_TIMESTAMP_POSITION.getStorageUint256(); } @@ -750,10 +589,6 @@ abstract contract WithdrawalQueueBase { LOCKED_ETHER_AMOUNT_POSITION.setStorageUint256(_lockedEtherAmount); } - function _setLastCheckedExtremum(uint256 _lastCheckedExtremum) internal { - LAST_CHECKED_EXTREMUM_POSITION.setStorageUint256(_lastCheckedExtremum); - } - function _setLastReportTimestamp(uint256 _lastReportTimestamp) internal { LAST_REPORT_TIMESTAMP_POSITION.setStorageUint256(_lastReportTimestamp); } diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 6daa81adc..d6edf91d9 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index cc531288e..74c901e63 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 7482c3a82..b6807e970 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file From d7d88cd94dc2879d5ca05f877e9890ba98a1b592 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 7 Mar 2023 01:34:20 +0300 Subject: [PATCH 166/236] test: happy path `handleOracleReport`+withdrawals --- test/0.4.24/lido-handle-oracle-report.test.js | 70 +++++++++++++++++-- test/helpers/factories.js | 2 + 2 files changed, 65 insertions(+), 7 deletions(-) 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 338424d75..eeef472ab 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -13,7 +13,7 @@ const { limitRebase, } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') -const { EvmSnapshot, setBalance } = require('../helpers/blockchain') +const { EvmSnapshot, setBalance, advanceChainTime, getCurrentBlockTimestamp } = require('../helpers/blockchain') const { ZERO_ADDRESS, INITIAL_HOLDER } = require('../helpers/constants') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') @@ -25,11 +25,11 @@ const ORACLE_REPORT_LIMITS_BOILERPLATE = { churnValidatorsPerDayLimit: 255, oneOffCLBalanceDecreaseBPLimit: 100, annualBalanceIncreaseBPLimit: 10000, - simulatedShareRateDeviationBPLimit: 10000, + simulatedShareRateDeviationBPLimit: 1, maxValidatorExitRequestsPerReport: 10000, maxAccountingExtraDataListItemsCount: 10000, maxNodeOperatorsPerExtraDataItemCount: 10000, - requestTimestampMargin: 0, + requestTimestampMargin: 24, maxPositiveTokenRebase: 1000000000, } @@ -41,7 +41,7 @@ const DEFAULT_LIDO_ORACLE_REPORT = { withdrawalVaultBalance: ETH(0), // uint256, wei elRewardsVaultBalance: ETH(0), // uint256, wei sharesRequestedToBurn: StETH(0), // uint256, wad - withdrawalFinalizationBatches: [], // uint256[], indexes + lastFinalizableWithdrawalRequestId: 0, // uint256, index simulatedShareRate: shareRate(0), // uint256, 10e27 } @@ -108,7 +108,7 @@ const checkEvents = async ({ } contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anotherStranger, depositor, operator]) => { - let deployed, snapshot, lido, treasury, voting, oracle, burner + let deployed, snapshot, lido, treasury, voting, oracle, burner, withdrawalQueue let curatedModule, oracleReportSanityChecker, elRewardsVault let withdrawalVault let strangerBalanceBefore, @@ -154,6 +154,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot oracleReportSanityChecker = deployed.oracleReportSanityChecker withdrawalVault = deployed.withdrawalVault.address elRewardsVault = deployed.elRewardsVault.address + withdrawalQueue = deployed.withdrawalQueue assert.equals(await lido.balanceOf(INITIAL_HOLDER), StETH(1)) await lido.submit(ZERO_ADDRESS, { from: stranger, value: ETH(30) }) @@ -1960,8 +1961,63 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot assert.equals(elRewards, ETH(0.4)) }) - it.skip('withdrawal finalization works after dry-run call', async () => { - // TODO + it('withdrawal finalization works after dry-run call', async () => { + await setBalance(elRewardsVault, ETH(0.5)) + await setBalance(withdrawalVault, ETH(0.5)) + + assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), toBN(0)) + await withdrawalQueue.resume({ from: appManager }) + assert.isFalse(await withdrawalQueue.isPaused()) + + await lido.approve(withdrawalQueue.address, StETH(1), { from: stranger }) + await withdrawalQueue.requestWithdrawals([StETH(1)], stranger, { from: stranger }) + assert.equals(await withdrawalQueue.unfinalizedStETH(), StETH(1)) + assert.equals(await withdrawalQueue.unfinalizedRequestNumber(), 1) + + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + churnValidatorsPerDayLimit: 100, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + + await advanceChainTime(30) + + const [postTotalPooledEther, postTotalShares, ,] = await lido.handleOracleReport.call( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.5), + withdrawalVaultBalance: ETH(0.5), + }), + { from: oracle, gasPrice: 1 } + ) + + await advanceChainTime(30) + + const simulatedShareRate = postTotalPooledEther.mul(toBN(shareRate(1))).div(postTotalShares) + + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + reportTimestamp: await getCurrentBlockTimestamp(), + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.5), + withdrawalVaultBalance: ETH(0.5), + lastFinalizableWithdrawalRequestId: 1, + simulatedShareRate, + }), + { from: oracle, gasPrice: 1 } + ) + + assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), toBN(1)) + await withdrawalQueue.claimWithdrawal(1, { from: stranger }) }) it.skip('check simulated share rate correctness when limit is higher due to withdrawals', async () => { diff --git a/test/helpers/factories.js b/test/helpers/factories.js index f8e35b3cd..3f5d2ed2f 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -267,6 +267,8 @@ async function withdrawalQueueFactory({ appManager, oracle, pool }) { const BUNKER_MODE_REPORT_ROLE = await withdrawalQueue.BUNKER_MODE_REPORT_ROLE() await withdrawalQueue.grantRole(BUNKER_MODE_REPORT_ROLE, oracle.address, { from: appManager.address }) + const FINALIZE_ROLE = await withdrawalQueue.FINALIZE_ROLE() + await withdrawalQueue.grantRole(FINALIZE_ROLE, pool.address, { from: appManager.address }) await grantRoles({ by: appManager.address, From 10c72e83917f6a0399beac172fb4494071d70028 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 7 Mar 2023 14:48:25 +0700 Subject: [PATCH 167/236] chore: pull nft tests from diff branch --- test/0.8.9/withdrawal-queue-nft.test.js | 278 +++++++++++++++++-- test/0.8.9/withdrawal-request-nft.test.js | 323 ---------------------- 2 files changed, 259 insertions(+), 342 deletions(-) delete mode 100644 test/0.8.9/withdrawal-request-nft.test.js diff --git a/test/0.8.9/withdrawal-queue-nft.test.js b/test/0.8.9/withdrawal-queue-nft.test.js index 41ece8414..12059870f 100644 --- a/test/0.8.9/withdrawal-queue-nft.test.js +++ b/test/0.8.9/withdrawal-queue-nft.test.js @@ -1,9 +1,11 @@ -const { contract, ethers, web3 } = require('hardhat') +const { contract, ethers, web3, artifacts } = require('hardhat') const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const { ETH, StETH, shareRate, shares } = require('../helpers/utils') const { assert } = require('../helpers/assert') -const { impersonate, EvmSnapshot, setBalance } = require('../helpers/blockchain') +const { EvmSnapshot, setBalance } = require('../helpers/blockchain') + +const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock') const { deployWithdrawalQueue, @@ -12,8 +14,8 @@ const { NFT_DESCRIPTOR_BASE_URI, } = require('./withdrawal-queue-deploy.test') -contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) => { - let withdrawalQueue, steth, nftDescriptor +contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, recipient]) => { + let withdrawalQueue, steth, nftDescriptor, erc721ReceiverMock const manageTokenUriRoleKeccak156 = web3.utils.keccak256('MANAGE_TOKEN_URI_ROLE') const snapshot = new EvmSnapshot(ethers.provider) @@ -30,6 +32,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) steth = deployed.steth withdrawalQueue = deployed.withdrawalQueue nftDescriptor = deployed.nftDescriptor + erc721ReceiverMock = await ERC721ReceiverMock.new({ from: owner }) await steth.setTotalPooledEther(ETH(600)) // we need 1 ETH additionally to pay gas on finalization because coverage ingnores gasPrice=0 @@ -38,7 +41,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) await withdrawalQueue.grantRole(manageTokenUriRoleKeccak156, tokenUriManager, { from: daoAgent }) - await impersonate(ethers.provider, steth.address) await snapshot.make() }) @@ -150,8 +152,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 1) - const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 0) @@ -163,6 +165,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) }) context('ownerOf', () => { + it('should revert when token id is 0', async () => { + await assert.reverts(withdrawalQueue.ownerOf(0), `InvalidRequestId(0)`) + }) + it('should revert with not existing', async () => { await assert.reverts(withdrawalQueue.ownerOf(1), 'InvalidRequestId(1)') }) @@ -175,14 +181,45 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) assert.equals(await withdrawalQueue.ownerOf(1), user) - const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) await assert.reverts(withdrawalQueue.ownerOf(1), 'RequestAlreadyClaimed(1)') }) }) + context('approve()', async () => { + let tokenId1 + beforeEach(async () => { + await snapshot.rollback() + const requestIds = await withdrawalQueue.requestWithdrawals.call([ETH(25), ETH(25)], user, { from: user }) + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + tokenId1 = requestIds[0] + }) + + it('reverts with message "ApprovalToOwner()" when approval for owner address', async () => { + await assert.reverts(withdrawalQueue.approve(user, tokenId1, { from: user }), 'ApprovalToOwner()') + }) + + it('reverts with message "NotOwnerOrApprovedForAll()" when called noy by owner', async () => { + await assert.reverts( + withdrawalQueue.approve(recipient, tokenId1, { from: stranger }), + `NotOwnerOrApprovedForAll("${stranger}")` + ) + }) + + it('sets approval for address and transfer by approved', async () => { + const tx = await withdrawalQueue.approve(recipient, tokenId1, { from: user }) + assert.equal(await withdrawalQueue.getApproved(tokenId1), recipient) + + assert.emits(tx, 'Approval', { owner: user, approved: recipient, tokenId: tokenId1 }) + + await withdrawalQueue.transferFrom(user, recipient, tokenId1, { from: recipient }) + assert.equals(await withdrawalQueue.ownerOf(tokenId1), recipient) + }) + }) + context('getApproved', () => { it('should revert with invalid request id', async () => { await assert.reverts(withdrawalQueue.getApproved(1), 'InvalidRequestId(1)') @@ -200,6 +237,35 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) }) }) + context('setApprovalForAll()', async () => { + let tokenId1, tokenId2 + beforeEach(async () => { + await snapshot.rollback() + const requestIds = await withdrawalQueue.requestWithdrawals.call([ETH(25), ETH(25)], user, { + from: user, + }) + tokenId1 = requestIds[0] + tokenId2 = requestIds[1] + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + }) + + it('reverts with message "ApproveToCaller()" when owner equal to operator', async () => { + await assert.reverts(withdrawalQueue.setApprovalForAll(user, true, { from: user }), 'ApproveToCaller()') + }) + + it('approvalForAll allows transfer', async () => { + const tx = await withdrawalQueue.setApprovalForAll(recipient, true, { from: user }) + assert.emits(tx, 'ApprovalForAll', { owner: user, operator: recipient, approved: true }) + assert.isTrue(await withdrawalQueue.isApprovedForAll(user, recipient)) + + await withdrawalQueue.transferFrom(user, recipient, tokenId1, { from: recipient }) + await withdrawalQueue.transferFrom(user, recipient, tokenId2, { from: recipient }) + + assert.equals(await withdrawalQueue.ownerOf(tokenId1), recipient) + assert.equals(await withdrawalQueue.ownerOf(tokenId2), recipient) + }) + }) + context('isApprovedForAll', () => { it('should return false for not approved', async () => { assert.isFalse(await withdrawalQueue.isApprovedForAll(user, stranger)) @@ -211,6 +277,180 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) }) }) + context('safeTransferFrom(address,address,uint256)', async () => { + let requestIds + beforeEach(async () => { + requestIds = await withdrawalQueue.requestWithdrawals.call([ETH(25), ETH(25)], user, { + from: user, + }) + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + }) + + it('reverts with message "NotOwnerOrApproved()" when approvalNotSet and not owner', async () => { + await assert.reverts( + withdrawalQueue.safeTransferFrom(user, recipient, requestIds[0], { + from: stranger, + }), + `NotOwnerOrApproved("${stranger}")` + ) + }) + + it('transfers if called by owner', async () => { + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + await withdrawalQueue.safeTransferFrom(user, recipient, requestIds[0], { + from: user, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + }) + + it('transfers if token approval set', async () => { + await withdrawalQueue.approve(recipient, requestIds[0], { from: user }) + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + await withdrawalQueue.safeTransferFrom(user, recipient, requestIds[0], { + from: recipient, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + }) + + it('transfers if operator approval set', async () => { + await withdrawalQueue.setApprovalForAll(recipient, true, { from: user }) + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[1]), recipient) + await withdrawalQueue.safeTransferFrom(user, recipient, requestIds[0], { + from: recipient, + }) + await withdrawalQueue.safeTransferFrom(user, recipient, requestIds[1], { + from: recipient, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + assert.equal(await withdrawalQueue.ownerOf(requestIds[1]), recipient) + }) + + it('reverts with message "TransferToNonIERC721Receiver()" when transfer to contract that not implements IERC721Receiver interface', async () => { + await assert.reverts( + withdrawalQueue.safeTransferFrom(user, steth.address, requestIds[0], { + from: user, + }), + `TransferToNonIERC721Receiver("${steth.address}")` + ) + }) + + it('reverts with propagated error message when recipient contract implements ERC721Receiver and reverts on onERC721Received call', async () => { + await erc721ReceiverMock.setDoesAcceptTokens(false, { from: owner }) + await assert.reverts( + withdrawalQueue.safeTransferFrom(user, erc721ReceiverMock.address, requestIds[0], { + from: user, + }), + 'ERC721_NOT_ACCEPT_TOKENS' + ) + }) + + it("doesn't revert when recipient contract implements ERC721Receiver interface and accepts tokens", async () => { + await erc721ReceiverMock.setDoesAcceptTokens(true, { from: owner }) + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[0]), erc721ReceiverMock.address) + await withdrawalQueue.safeTransferFrom(user, erc721ReceiverMock.address, requestIds[0], { + from: user, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), erc721ReceiverMock.address) + }) + }) + + describe('transferFrom()', async () => { + let requestIds + + beforeEach(async () => { + requestIds = await withdrawalQueue.requestWithdrawals.call([ETH(25), ETH(25)], user, { + from: user, + }) + await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) + }) + + it('reverts with message "NotOwnerOrApproved()" when approvalNotSet and not owner', async () => { + await assert.reverts( + withdrawalQueue.transferFrom(user, recipient, requestIds[0], { from: stranger }), + `NotOwnerOrApproved("${stranger}")` + ) + }) + + it('reverts when transfer to the same address', async () => { + await assert.reverts( + withdrawalQueue.transferFrom(user, user, requestIds[0], { + from: user, + }), + 'TransferToThemselves()' + ) + }) + + it('reverts with error "RequestAlreadyClaimed()" when called on claimed request', async () => { + const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) + + await withdrawalQueue.methods['claimWithdrawal(uint256)'](requestIds[0], { + from: user, + }) + + await assert.reverts( + withdrawalQueue.transferFrom(user, recipient, requestIds[0], { + from: user, + }), + `RequestAlreadyClaimed(${requestIds[0]})` + ) + }) + + it('transfers if called by owner', async () => { + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + await withdrawalQueue.transferFrom(user, recipient, requestIds[0], { + from: user, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + }) + + it('transfers if token approval set', async () => { + await withdrawalQueue.approve(recipient, requestIds[0], { from: user }) + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + await withdrawalQueue.transferFrom(user, recipient, requestIds[0], { + from: recipient, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + }) + + it('transfers if operator approval set', async () => { + await withdrawalQueue.setApprovalForAll(recipient, true, { from: user }) + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + assert.notEqual(await withdrawalQueue.ownerOf(requestIds[1]), recipient) + await withdrawalQueue.transferFrom(user, recipient, requestIds[0], { + from: recipient, + }) + await withdrawalQueue.transferFrom(user, recipient, requestIds[1], { + from: recipient, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + assert.equal(await withdrawalQueue.ownerOf(requestIds[1]), recipient) + }) + + it('can claim request after transfer', async () => { + await withdrawalQueue.transferFrom(user, recipient, requestIds[0], { + from: user, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) + + const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) + + await withdrawalQueue.methods['claimWithdrawal(uint256)'](requestIds[0], { + from: recipient, + }) + }) + + it("doesn't reverts when transfer to contract that not implements IERC721Receiver interface", async () => { + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), user) + await withdrawalQueue.transferFrom(user, steth.address, requestIds[0], { + from: user, + }) + assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), steth.address) + }) + }) + context('mint', async () => { it('should mint', async () => { await withdrawalQueue.requestWithdrawals([ETH(25), ETH(25)], user, { from: user }) @@ -261,8 +501,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(1), user) assert.equals(await withdrawalQueue.ownerOf(2), user) - const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 1) @@ -277,8 +517,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(1), user) assert.equals(await withdrawalQueue.ownerOf(2), user) - const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) - await withdrawalQueue.finalize(1, shareRate(1), { from: daoAgent, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: stranger }), `NotOwner("${stranger}", "${user}")`) @@ -299,8 +539,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(1), user) assert.equals(await withdrawalQueue.ownerOf(2), user) - const batch = await withdrawalQueue.finalizationBatch(2, shareRate(1)) - await withdrawalQueue.finalize(2, shareRate(1), { from: daoAgent, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 1) @@ -324,8 +564,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(2), user) assert.equals(await withdrawalQueue.ownerOf(1), stranger) - const batch = await withdrawalQueue.finalizationBatch(2, shareRate(1)) - await withdrawalQueue.finalize(2, shareRate(1), { from: daoAgent, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(2, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 0) @@ -375,8 +615,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager]) assert.equals(await withdrawalQueue.ownerOf(2), user) assert.equals(await withdrawalQueue.ownerOf(3), stranger) - const batch = await withdrawalQueue.finalizationBatch(3, shareRate(1)) - await withdrawalQueue.finalize(3, shareRate(1), { from: daoAgent, value: batch.ethToLock }) + const batch = await withdrawalQueue.prefinalize.call([3], shareRate(1)) + await withdrawalQueue.finalize([3], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) await withdrawalQueue.claimWithdrawal(3, { from: stranger }) diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js deleted file mode 100644 index 2135ab006..000000000 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ /dev/null @@ -1,323 +0,0 @@ -const { ZERO_ADDRESS } = require('@aragon/contract-helpers-test') -const { contract, artifacts, ethers } = require('hardhat') -const { assert } = require('../helpers/assert') - -const { EvmSnapshot, setBalance } = require('../helpers/blockchain') -const { shares, ETH, shareRate } = require('../helpers/utils') -const withdrawals = require('../helpers/withdrawals') - -const StETH = artifacts.require('StETHMock') -const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock') - -contract('WithdrawalNFT', (addresses) => { - const [deployer, stEthHolder, nftHolderStETH, recipient, stranger] = addresses - let withdrawalQueueERC721, stETH, erc721ReceiverMock - let nftHolderStETHTokenIds, nonExistedTokenId - const snapshot = new EvmSnapshot(ethers.provider) - - before(async () => { - stETH = await StETH.new({ value: ETH(1), from: deployer }) - await setBalance(stETH.address, ETH(100)) - - erc721ReceiverMock = await ERC721ReceiverMock.new({ from: deployer }) - withdrawalQueueERC721 = (await withdrawals.deploy(deployer, stETH.address, 'Lido TEST Request', 'unstEsT')).queue - await withdrawalQueueERC721.initialize(deployer) - await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.RESUME_ROLE(), deployer) - await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.FINALIZE_ROLE(), deployer) - await withdrawalQueueERC721.resume({ from: deployer }) - - await stETH.setTotalPooledEther(ETH(101)) - await stETH.mintShares(stEthHolder, shares(100)) - - await stETH.approve(withdrawalQueueERC721.address, ETH(50), { from: stEthHolder }) - - await withdrawalQueueERC721.requestWithdrawals([ETH(25), ETH(25)], nftHolderStETH, { from: stEthHolder }) - nftHolderStETHTokenIds = [1, 2] - nonExistedTokenId = 4 - await snapshot.make() - }) - - afterEach(async () => { - await snapshot.rollback() - }) - - describe('ERC721Metadata', () => { - it('Initial properties', async () => { - assert.equals(await withdrawalQueueERC721.symbol(), 'unstEsT') - assert.equals(await withdrawalQueueERC721.name(), 'Lido TEST Request') - }) - }) - - describe('supportsInterface()', () => { - it('returns true for IERC165 interface id (0x01ffc9a7)', async () => { - assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x01ffc9a7')) - }) - it('returns true for IERC721 interface id (0x80ac58cd)', async () => { - assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x80ac58cd')) - }) - it('returns true for IERC721Metadata interface id (0x5b5e139f)', async () => { - assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x5b5e139f')) - }) - it('returns true for AccessControlEnumerable interface id (0x5a05180f)', async () => { - assert.isTrue(await withdrawalQueueERC721.supportsInterface('0x5a05180f')) - }) - it('returns false for unsupported e interface id (0xffffffff)', async () => { - assert.isFalse(await withdrawalQueueERC721.supportsInterface('0xffffffff')) - }) - it('returns false for unsupported e interface id (0xdeadbeaf)', async () => { - assert.isFalse(await withdrawalQueueERC721.supportsInterface('0xdeadbeaf')) - }) - }) - - describe('balanceOf()', () => { - it('return 0 when user has not withdrawal requests', async () => { - assert.equals(await withdrawalQueueERC721.balanceOf(recipient), 0) - }) - - it('return correct withdrawal requests count', async () => { - assert.equals(await withdrawalQueueERC721.balanceOf(nftHolderStETH), 2) - }) - - it('reverts for zero address', async () => { - await assert.reverts(withdrawalQueueERC721.balanceOf(ZERO_ADDRESS), `InvalidOwnerAddress("${ZERO_ADDRESS}")`) - }) - }) - - describe('ownerOf()', () => { - it('reverts with error InvalidRequestId() when token id is 0', async () => { - await assert.reverts(withdrawalQueueERC721.ownerOf(0), `InvalidRequestId(0)`) - }) - - it('reverts with error InvalidRequestId() when called with non existed token id', async () => { - await assert.reverts(withdrawalQueueERC721.ownerOf(nonExistedTokenId), `InvalidRequestId(${nonExistedTokenId})`) - }) - - it('reverts correct owner', async () => { - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), nftHolderStETH) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[1]), nftHolderStETH) - }) - }) - - describe('approve()', async () => { - it('reverts with message "ApprovalToOwner()" when approval for owner address', async () => { - await assert.reverts( - withdrawalQueueERC721.approve(nftHolderStETH, nftHolderStETHTokenIds[0], { from: nftHolderStETH }), - 'ApprovalToOwner()' - ) - }) - - it('reverts with message "NotOwnerOrApprovedForAll()" when called noy by owner', async () => { - await assert.reverts( - withdrawalQueueERC721.approve(recipient, nftHolderStETHTokenIds[0], { from: stranger }), - `NotOwnerOrApprovedForAll("${stranger}")` - ) - }) - - it('sets approval for address', async () => { - await withdrawalQueueERC721.approve(recipient, nftHolderStETHTokenIds[0], { from: nftHolderStETH }) - assert.equal(await withdrawalQueueERC721.getApproved(nftHolderStETHTokenIds[0]), recipient) - }) - }) - - describe('getApproved()', async () => { - it('reverts with message "InvalidRequestId()" when called with non existed token id', async () => { - await assert.reverts( - withdrawalQueueERC721.getApproved(nonExistedTokenId), - `InvalidRequestId(${nonExistedTokenId})` - ) - }) - }) - - describe('setApprovalForAll()', async () => { - it('reverts with message "ApproveToCaller()" when owner equal to operator', async () => { - await assert.reverts( - withdrawalQueueERC721.setApprovalForAll(nftHolderStETH, true, { from: nftHolderStETH }), - 'ApproveToCaller()' - ) - }) - }) - - describe('safeTransferFrom(address,address,uint256)', async () => { - it('reverts with message "NotOwnerOrApproved()" when approvalNotSet and not owner', async () => { - await assert.reverts( - withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: stranger, - }), - `NotOwnerOrApproved("${stranger}")` - ) - }) - - it('transfers if called by owner', async () => { - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - await withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - }) - - it('transfers if token approval set', async () => { - await withdrawalQueueERC721.approve(recipient, nftHolderStETHTokenIds[0], { from: nftHolderStETH }) - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - await withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: recipient, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - }) - - it('transfers if operator approval set', async () => { - await withdrawalQueueERC721.setApprovalForAll(recipient, true, { from: nftHolderStETH }) - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[1]), recipient) - await withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: recipient, - }) - await withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[1], { - from: recipient, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[1]), recipient) - }) - - it('reverts with message "TransferToNonIERC721Receiver()" when transfer to contract that not implements IERC721Receiver interface', async () => { - await assert.reverts( - withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, stETH.address, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }), - `TransferToNonIERC721Receiver("${stETH.address}")` - ) - }) - - it('reverts with propagated error message when recipient contract implements ERC721Receiver and reverts on onERC721Received call', async () => { - await erc721ReceiverMock.setDoesAcceptTokens(false, { from: deployer }) - await assert.reverts( - withdrawalQueueERC721.safeTransferFrom(nftHolderStETH, erc721ReceiverMock.address, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }), - 'ERC721_NOT_ACCEPT_TOKENS' - ) - }) - - it("doesn't revert when recipient contract implements ERC721Receiver interface and accepts tokens", async () => { - await erc721ReceiverMock.setDoesAcceptTokens(true, { from: deployer }) - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), erc721ReceiverMock.address) - await withdrawalQueueERC721.safeTransferFrom( - nftHolderStETH, - erc721ReceiverMock.address, - nftHolderStETHTokenIds[0], - { - from: nftHolderStETH, - } - ) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), erc721ReceiverMock.address) - }) - }) - - describe('transferFrom()', async () => { - it('reverts with message "NotOwnerOrApproved()" when approvalNotSet and not owner', async () => { - await assert.reverts( - withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { from: stranger }), - `NotOwnerOrApproved("${stranger}")` - ) - }) - - it('reverts when transfer to the same address', async () => { - await assert.reverts( - withdrawalQueueERC721.transferFrom(nftHolderStETH, nftHolderStETH, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }), - 'TransferToThemselves()' - ) - }) - - it('reverts with error "RequestAlreadyClaimed()" when called on claimed request', async () => { - const batch = await withdrawalQueueERC721.finalizationBatch(2, shareRate(1)) - await withdrawalQueueERC721.finalize(2, shareRate(1), { from: deployer, value: batch.ethToLock }) - const ownerETHBefore = await ethers.provider.getBalance(nftHolderStETH) - const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }) - const ownerETHAfter = await ethers.provider.getBalance(nftHolderStETH) - // adhoc fix for solidity-coverage that ignores gasPrice = 0 - assert.almostEqual(ownerETHAfter, ownerETHBefore.add(ETH(25)), tx.receipt.gasUsed) - - await assert.reverts( - withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }), - `RequestAlreadyClaimed(${nftHolderStETHTokenIds[0]})` - ) - }) - - it('transfers if called by owner', async () => { - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - await withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - }) - - it('transfers if token approval set', async () => { - await withdrawalQueueERC721.approve(recipient, nftHolderStETHTokenIds[0], { from: nftHolderStETH }) - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - await withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: recipient, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - }) - - it('transfers if operator approval set', async () => { - await withdrawalQueueERC721.setApprovalForAll(recipient, true, { from: nftHolderStETH }) - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - assert.notEqual(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[1]), recipient) - await withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: recipient, - }) - await withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[1], { - from: recipient, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[1]), recipient) - }) - - it('can claim request after transfer', async () => { - await withdrawalQueueERC721.transferFrom(nftHolderStETH, recipient, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), recipient) - - const batch = await withdrawalQueueERC721.finalizationBatch(2, shareRate(1)) - await withdrawalQueueERC721.finalize(2, shareRate(1), { from: deployer, value: batch.ethToLock }) - - const recipientETHBefore = await ethers.provider.getBalance(recipient) - const tx = await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { - from: recipient, - }) - const recipientETHAfter = await ethers.provider.getBalance(recipient) - // adhoc fix for solidity-coverage that ignores gasPrice = 0 - assert.almostEqual(recipientETHAfter, recipientETHBefore.add(ETH(25)), tx.receipt.gasUsed) - }) - - it("doesn't reverts when transfer to contract that not implements IERC721Receiver interface", async () => { - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), nftHolderStETH) - await withdrawalQueueERC721.transferFrom(nftHolderStETH, stETH.address, nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }) - assert.equal(await withdrawalQueueERC721.ownerOf(nftHolderStETHTokenIds[0]), stETH.address) - }) - }) - - describe('Burn', () => { - it('balanceOf decreases after claim', async () => { - const balanceBefore = await withdrawalQueueERC721.balanceOf(nftHolderStETH) - - const batch = await withdrawalQueueERC721.finalizationBatch(2, shareRate(1)) - await withdrawalQueueERC721.finalize(2, shareRate(1), { from: deployer, value: batch.ethToLock }) - - await withdrawalQueueERC721.methods['claimWithdrawal(uint256)'](nftHolderStETHTokenIds[0], { - from: nftHolderStETH, - }) - - assert.equals(balanceBefore - (await withdrawalQueueERC721.balanceOf(nftHolderStETH)), 1) - }) - }) -}) From 43e571d0770a8ab90d34bf863ccade9b44a048a6 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 7 Mar 2023 15:38:39 +0700 Subject: [PATCH 168/236] fix: nft tests --- test/0.8.9/withdrawal-queue-nft.test.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/test/0.8.9/withdrawal-queue-nft.test.js b/test/0.8.9/withdrawal-queue-nft.test.js index 12059870f..d09dde20b 100644 --- a/test/0.8.9/withdrawal-queue-nft.test.js +++ b/test/0.8.9/withdrawal-queue-nft.test.js @@ -151,8 +151,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, it('should return 0 after claim', async () => { await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) assert.equals(await withdrawalQueue.balanceOf(user), 1) - - const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([1], shareRate(1)) await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) @@ -181,7 +180,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, await withdrawalQueue.requestWithdrawals([ETH(25)], user, { from: user }) assert.equals(await withdrawalQueue.ownerOf(1), user) - const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([1], shareRate(1)) await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) @@ -382,7 +381,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, }) it('reverts with error "RequestAlreadyClaimed()" when called on claimed request', async () => { - const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([2], shareRate(1)) await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.methods['claimWithdrawal(uint256)'](requestIds[0], { @@ -434,7 +433,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, }) assert.equal(await withdrawalQueue.ownerOf(requestIds[0]), recipient) - const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([2], shareRate(1)) await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.methods['claimWithdrawal(uint256)'](requestIds[0], { @@ -501,7 +500,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, assert.equals(await withdrawalQueue.ownerOf(1), user) assert.equals(await withdrawalQueue.ownerOf(2), user) - const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([1], shareRate(1)) await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) @@ -517,7 +516,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, assert.equals(await withdrawalQueue.ownerOf(1), user) assert.equals(await withdrawalQueue.ownerOf(2), user) - const batch = await withdrawalQueue.prefinalize.call([1], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([1], shareRate(1)) await withdrawalQueue.finalize([1], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await assert.reverts(withdrawalQueue.claimWithdrawal(1, { from: stranger }), `NotOwner("${stranger}", "${user}")`) @@ -539,7 +538,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, assert.equals(await withdrawalQueue.ownerOf(1), user) assert.equals(await withdrawalQueue.ownerOf(2), user) - const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([2], shareRate(1)) await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) @@ -564,7 +563,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, assert.equals(await withdrawalQueue.ownerOf(2), user) assert.equals(await withdrawalQueue.ownerOf(1), stranger) - const batch = await withdrawalQueue.prefinalize.call([2], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([2], shareRate(1)) await withdrawalQueue.finalize([2], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(2, { from: user }) @@ -615,7 +614,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, tokenUriManager, assert.equals(await withdrawalQueue.ownerOf(2), user) assert.equals(await withdrawalQueue.ownerOf(3), stranger) - const batch = await withdrawalQueue.prefinalize.call([3], shareRate(1)) + const batch = await withdrawalQueue.finalizationBatch([3], shareRate(1)) await withdrawalQueue.finalize([3], shareRate(1), { from: daoAgent, value: batch.ethToLock }) await withdrawalQueue.claimWithdrawal(1, { from: user }) await withdrawalQueue.claimWithdrawal(3, { from: stranger }) From e3f1319384a86b6062570036ca922a7d1b905d3f Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 7 Mar 2023 11:47:52 +0200 Subject: [PATCH 169/236] =?UTF-8?q?=F0=9F=93=9A:=20more=20docs=20for=20wq?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 37 +++++++++++++++++-------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index a1da71691..b593a1f42 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -149,20 +149,33 @@ abstract contract WithdrawalQueueBase { } // - // FINALIZATION + // FINALIZATION FLOW // // Process when protocol is fixing the withdrawal request value and lock the required amount of ETH. - // Locked ETH can be claimed by the owner of the request - // Finalization is a part of the oracle report - // Steps: + // The value of a request after finalization can be: + // - nominal (when the amount of eth locked for this request are equal to the request's stETH) + // - discounted (when the amount of eth will be lower, because the protocol share rate dropped + // before request is finalized, so it will be equal to `request's shares` * `protocol share rate`) + // The parameters that are required for finalization are: + // - current share rate of the protocol + // - id of the last request that can be finalized + // - the amount of eth that must be locked for these requests + // To calculate the eth amount we'll need to know which requests int the queue will be finalized as nominal + // and which as discounted and the exact value of the discount. It's impossible to calculate without the unbounded + // loop over the unfinalized part of the queue. So, we need to extract a part of the algorithm off-chain, bring the + // result with oracle report and check it later and check the resukt later. + // So, we came to this solution: // Off-chain - // 1. Oracle daemon precalculates finalization batches' boundaries using `calculateFinalizationBatches()` - // On-chain - // 2. AccountingOracle contract invokes `onOracleReport()` handler to update last report timestamp for the queue - // 3. Lido contract, during the report handling, calculates the value of finalization batch in eth and shares - // and checks its correctness using `prefinalize()` - // 4. Lido contract finalize the batch of requests passing the required ether along with `finalize()` method - // + // 1. Oracle iterates over the queue off-chain and calculate the id of the latest finalizable request + // in the queue. Then it splits all the requests that will be finalized into batches the way, + // that requests in a batch are all nominal or all discounted. + // And passes them in the report as the array of the ending ids of these batches. So it can be reconstructed like + // `[lastFinalizedRequestId+1, batches[0]], [batches[0]+1, batches[1]] ... [batches[n-2], batches[n-1]]` + // 2. Contract checks the validity of the batches on-chain and calculate the amount of eth required to + // finalize them. It can be done without unbounded loop using partial sums that are calculated on request enqueueing. + // 3. Contract marks the request's as finalized and locks the eth for claiming. It also, + // set's the discount checkpoint for these request's if required that will be applied on claim for each request's + // individually depending on request's share rate. /// @notice transient state that is used to pass intemediate results between several `calculateFinalizationBatches` // invokations @@ -530,7 +543,7 @@ abstract contract WithdrawalQueueBase { if (!success) revert CantSendValueRecipientMayHaveReverted(); } - /// @dev calculate batch stats for the batch of `(_preStartRequest, _endRequest]` + /// @dev calculate batch stats (shareRate, stETH and shares) for the batch of `(_preStartRequest, _endRequest]` function _calcBatch( WithdrawalRequest memory _preStartRequest, WithdrawalRequest memory _endRequest From 70a73cec34f3c2147eaf725c388d2104f1123e55 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 7 Mar 2023 13:10:24 +0200 Subject: [PATCH 170/236] =?UTF-8?q?=F0=9F=93=9A:=20add=20doc=20for=201=20w?= =?UTF-8?q?ei=20reounding=20error=20case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index b593a1f42..9875e4657 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -257,6 +257,10 @@ abstract contract WithdrawalQueueBase { _state.ethBudget -= ethToFinalize; if (batchesLength != 0 && ( + // share rate of requests in the same batch can differ by 1-2 wei because of the rounding error + // (issue: https://github.com/lidofinance/lido-dao/issues/442 ) + // so we're counting requests that are placed during the same report day + // as equal even if their actual share rate are different prevRequest.reportTimestamp == request.reportTimestamp || prevShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || prevShareRate > _maxShareRate && requestShareRate > _maxShareRate From 20d9a68c15ca380a4e929dd519171039d6ca399c Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 7 Mar 2023 14:14:55 +0300 Subject: [PATCH 171/236] feat: tighten simulated share rate sanity check Don't allow any margin for the upper-bound case. I.e., the simulated share rate MUST be <= the actual one. --- .../OracleReportSanityChecker.sol | 21 +++++++++++----- lib/abi/OracleReportSanityChecker.json | 2 +- .../oracle-report-sanity-checker.test.js | 24 ++++++++++++++----- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol index 0f3e37c55..f4b40ac52 100644 --- a/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol +++ b/contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol @@ -627,16 +627,23 @@ contract OracleReportSanityChecker is AccessControlEnumerable { if (actualShareRate == 0) { // can't finalize anything if the actual share rate is zero - revert IncorrectSimulatedShareRate(MAX_BASIS_POINTS); + revert ActualShareRateIsZero(); } - uint256 simulatedShareDiff = Math256.abs( - SafeCast.toInt256(_simulatedShareRate) - SafeCast.toInt256(actualShareRate) - ); + if (_simulatedShareRate > actualShareRate) { + // the simulated share rate can't be higher than the actual one + // invariant: rounding only can lower the simulated share rate + revert TooHighSimulatedShareRate(_simulatedShareRate, actualShareRate); + } + + uint256 simulatedShareDiff = actualShareRate - _simulatedShareRate; uint256 simulatedShareDeviation = (MAX_BASIS_POINTS * simulatedShareDiff) / actualShareRate; if (simulatedShareDeviation > _limitsList.simulatedShareRateDeviationBPLimit) { - revert IncorrectSimulatedShareRate(simulatedShareDeviation); + // the simulated share rate can be lower than the actual one due to rounding + // e.g., new user-submitted ether & minted `stETH` + // between an oracle reference slot and an actual accounting report delivery + revert TooLowSimulatedShareRate(_simulatedShareRate, actualShareRate); } } @@ -713,7 +720,9 @@ contract OracleReportSanityChecker is AccessControlEnumerable { error IncorrectNumberOfExitRequestsPerReport(uint256 maxRequestsCount); error IncorrectExitedValidators(uint256 churnLimit); error IncorrectRequestFinalization(uint256 requestCreationBlock); - error IncorrectSimulatedShareRate(uint256 simulatedShareDeviation); + error ActualShareRateIsZero(); + error TooHighSimulatedShareRate(uint256 simulatedShareRate, uint256 actualShareRate); + error TooLowSimulatedShareRate(uint256 simulatedShareRate, uint256 actualShareRate); error MaxAccountingExtraDataItemsCountExceeded(uint256 maxItemsCount, uint256 receivedItemsCount); error ExitedValidatorsLimitExceeded(uint256 limitPerDay, uint256 exitedPerDay); error TooManyNodeOpsPerExtraDataItem(uint256 itemIndex, uint256 nodeOpsCount); diff --git a/lib/abi/OracleReportSanityChecker.json b/lib/abi/OracleReportSanityChecker.json index db7f6a9b8..e92dbaba8 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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"actualSharesToBurn","type":"uint256"}],"name":"IncorrectSharesRequestedToBurn","type":"error"},{"inputs":[{"internalType":"uint256","name":"simulatedShareDeviation","type":"uint256"}],"name":"IncorrectSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"maxNodeOperatorsPerExtraDataItemCountManagers","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":[],"name":"ActualShareRateIsZero","type":"error"},{"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":"value","type":"uint256"},{"internalType":"uint256","name":"maxAllowedValue","type":"uint256"}],"name":"IncorrectLimitValue","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":"actualSharesToBurn","type":"uint256"}],"name":"IncorrectSharesRequestedToBurn","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":[{"internalType":"uint256","name":"simulatedShareRate","type":"uint256"},{"internalType":"uint256","name":"actualShareRate","type":"uint256"}],"name":"TooHighSimulatedShareRate","type":"error"},{"inputs":[],"name":"TooHighTokenRebaseLimit","type":"error"},{"inputs":[{"internalType":"uint256","name":"simulatedShareRate","type":"uint256"},{"internalType":"uint256","name":"actualShareRate","type":"uint256"}],"name":"TooLowSimulatedShareRate","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":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"MaxNodeOperatorsPerExtraDataItemCountSet","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":"simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"SimulatedShareRateDeviationBPLimitSet","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_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_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":"_sharesRequestedToBurn","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":"_sharesBurntDueToWithdrawals","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_maxNodeOperatorsPerExtraDataItemCount","type":"uint256"}],"name":"setMaxNodeOperatorsPerExtraDataItemCount","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":"simulatedShareRateDeviationBPLimit","type":"uint256"},{"internalType":"uint256","name":"maxValidatorExitRequestsPerReport","type":"uint256"},{"internalType":"uint256","name":"maxAccountingExtraDataListItemsCount","type":"uint256"},{"internalType":"uint256","name":"maxNodeOperatorsPerExtraDataItemCount","type":"uint256"},{"internalType":"uint256","name":"requestTimestampMargin","type":"uint256"},{"internalType":"uint256","name":"maxPositiveTokenRebase","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":"_simulatedShareRateDeviationBPLimit","type":"uint256"}],"name":"setSimulatedShareRateDeviationBPLimit","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":"_sharesRequestedToBurn","type":"uint256"},{"internalType":"uint256","name":"_etherToLockForWithdrawals","type":"uint256"},{"internalType":"uint256","name":"_newSharesToBurnForWithdrawals","type":"uint256"}],"name":"smoothenTokenRebase","outputs":[{"internalType":"uint256","name":"withdrawals","type":"uint256"},{"internalType":"uint256","name":"elRewards","type":"uint256"},{"internalType":"uint256","name":"simulatedSharesToBurn","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","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 0d724094d..a3ef5b8d5 100644 --- a/test/0.8.9/oracle-report-sanity-checker.test.js +++ b/test/0.8.9/oracle-report-sanity-checker.test.js @@ -285,10 +285,9 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa simulatedShareRate: (BigInt(2) * 10n ** 27n).toString(), } - it('reverts with error IncorrectSimulatedShareRate() when reported and onchain share rate differs', async () => { + it('reverts with error TooHighSimulatedShareRate() when reported and onchain share rate differs', async () => { const simulatedShareRate = BigInt(ETH(2.1)) * 10n ** 9n const actualShareRate = BigInt(2) * 10n ** 27n - const deviation = (100_00n * (simulatedShareRate - actualShareRate)) / actualShareRate await assert.revertsWithCustomError( oracleReportSanityChecker.checkSimulatedShareRate( ...Object.values({ @@ -296,12 +295,25 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa simulatedShareRate: simulatedShareRate.toString(), }) ), - `IncorrectSimulatedShareRate(${deviation.toString()})` + `TooHighSimulatedShareRate(${simulatedShareRate.toString()}, ${actualShareRate.toString()})` ) }) - it('reverts with error IncorrectSimulatedShareRate() when actual share rate is zero', async () => { - const deviation = 100_00n + it('reverts with error TooLowSimulatedShareRate() when reported and onchain share rate differs', async () => { + const simulatedShareRate = BigInt(ETH(1.9)) * 10n ** 9n + const actualShareRate = BigInt(2) * 10n ** 27n + await assert.revertsWithCustomError( + oracleReportSanityChecker.checkSimulatedShareRate( + ...Object.values({ + ...correctSimulatedShareRate, + simulatedShareRate: simulatedShareRate.toString(), + }) + ), + `TooLowSimulatedShareRate(${simulatedShareRate.toString()}, ${actualShareRate.toString()})` + ) + }) + + it('reverts with error ActualShareRateIsZero() when actual share rate is zero', async () => { await assert.revertsWithCustomError( oracleReportSanityChecker.checkSimulatedShareRate( ...Object.values({ @@ -310,7 +322,7 @@ contract('OracleReportSanityChecker', ([deployer, admin, withdrawalVault, elRewa postTotalPooledEther: ETH(0), }) ), - `IncorrectSimulatedShareRate(${deviation.toString()})` + `ActualShareRateIsZero()` ) }) From 63fdc138a4a57c09f75e2d79b226b1c758c98722 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 7 Mar 2023 13:16:52 +0200 Subject: [PATCH 172/236] fix: forever loop in batch calculation --- contracts/0.8.9/WithdrawalQueueBase.sol | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 9875e4657..ac3269069 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -222,12 +222,12 @@ abstract contract WithdrawalQueueBase { uint256 lastRequestId = getLastRequestId(); - uint256 requestId; + uint256 start; uint256 prevShareRate; uint256 batchesLength; if (_state.batches.length == 0) { - requestId = getLastFinalizedRequestId() + 1; + start = getLastFinalizedRequestId() + 1; // we'll store batches as a array where [MAX_BATCHES_LENGTH] element is the array's length _state.batches = new uint256[](MAX_BATCHES_LENGTH + 1); } else { @@ -235,10 +235,11 @@ abstract contract WithdrawalQueueBase { uint256 lastHandledRequestId = _state.batches[batchesLength - 1]; (prevShareRate,,) = _calcBatch(_getQueue()[lastHandledRequestId - 1], _getQueue()[lastHandledRequestId]); - requestId = lastHandledRequestId + 1; + start = lastHandledRequestId + 1; } - while (requestId < requestId + MAX_REQUESTS_PER_CALL) { + uint256 requestId = start; + while (requestId < start + MAX_REQUESTS_PER_CALL) { if (requestId > lastRequestId) break; // end of the queue break WithdrawalRequest memory request = _getQueue()[requestId]; @@ -277,7 +278,7 @@ abstract contract WithdrawalQueueBase { unchecked{ ++requestId; } } - _state.finished = requestId < requestId + MAX_REQUESTS_PER_CALL || requestId == lastRequestId + 1; + _state.finished = requestId < start + MAX_REQUESTS_PER_CALL || requestId == lastRequestId + 1; if (_state.finished) { MemUtils.trimUint256Array(_state.batches, _state.batches.length - batchesLength); From 1b3e1d220bd7db65d8f890899e0abbe85881684c Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 7 Mar 2023 14:19:12 +0300 Subject: [PATCH 173/236] test: add wrong simulated share test attempts --- test/0.4.24/lido-handle-oracle-report.test.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) 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 eeef472ab..32b5c1328 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -2000,6 +2000,45 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot await advanceChainTime(30) const simulatedShareRate = postTotalPooledEther.mul(toBN(shareRate(1))).div(postTotalShares) + const tooLowSimulatedShareRate = simulatedShareRate.mul(toBN(3)).div(toBN(4)) + + await assert.reverts( + lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + reportTimestamp: await getCurrentBlockTimestamp(), + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.5), + withdrawalVaultBalance: ETH(0.5), + lastFinalizableWithdrawalRequestId: 1, + simulatedShareRate: tooLowSimulatedShareRate, + }), + { from: oracle, gasPrice: 1 } + ), + `TooLowSimulatedShareRate(${tooLowSimulatedShareRate.toString()}, ${simulatedShareRate.toString()})` + ) + + const tooHighSimulatedShareRate = simulatedShareRate.mul(toBN(3)).div(toBN(2)) + + await assert.reverts( + lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + reportTimestamp: await getCurrentBlockTimestamp(), + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.5), + withdrawalVaultBalance: ETH(0.5), + lastFinalizableWithdrawalRequestId: 1, + simulatedShareRate: tooHighSimulatedShareRate, + }), + { from: oracle, gasPrice: 1 } + ), + `TooHighSimulatedShareRate(${tooHighSimulatedShareRate.toString()}, ${simulatedShareRate.toString()})` + ) await lido.handleOracleReport( ...Object.values({ From 01717fb365062b6ce16cfca7385bf41595b50f5f Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 7 Mar 2023 19:15:18 +0700 Subject: [PATCH 174/236] fix: fix some tests --- test/0.8.9/withdrawal-queue.test.js | 56 ++++++++++++++++++----------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 796d64d59..9bf324ad7 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -1,5 +1,5 @@ const { contract, ethers, web3 } = require('hardhat') -const { bn, getEventArgument, ZERO_ADDRESS, ZERO_BYTES32 } = require('@aragon/contract-helpers-test') +const { bn, getEventArgument, ZERO_ADDRESS } = require('@aragon/contract-helpers-test') const { ETH, StETH, shareRate, shares } = require('../helpers/utils') const { assert } = require('../helpers/assert') @@ -69,11 +69,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.pause(100000000, { from: daoAgent }) assert(await withdrawalQueue.isPaused()) await assert.reverts(withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }), 'ResumedExpected()') - const stubPermit = [0, 0, ZERO_BYTES32, ZERO_BYTES32, ZERO_BYTES32] - await assert.reverts( - withdrawalQueue.requestWithdrawalsWithPermit([ETH(1)], owner, stubPermit, { from: user }), - 'ResumedExpected()' - ) await assert.reverts(withdrawalQueue.finalize(1, 0, { from: owner }), 'ResumedExpected()') }) @@ -430,10 +425,9 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('works', async () => { - await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: ETH(1) }) - - assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(1)) + const batch = await withdrawalQueue.finalizationBatch(1, shareRate(300)) + await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: batch.ethToLock }) + assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), batch.ethToLock) }) it('reverts if last hint checkpoint is ahead of requestId', async () => { @@ -578,14 +572,17 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.setTotalPooledEther(ETH(22)) await steth.mintShares(user, shares(21)) await steth.approve(withdrawalQueue.address, StETH(21), { from: user }) - assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 0) - await withdrawalQueue.finalize(1, shareRate(300), { from: steth.address, value: amount }) - + const batch = await withdrawalQueue.finalizationBatch(1, shareRate(1)) + await withdrawalQueue.finalize(1, shareRate(1), { from: steth.address, value: batch.ethToLock }) for (let i = 1; i <= 20; i++) { assert.equals(await withdrawalQueue.getLastCheckpointIndex(), i) await withdrawalQueue.requestWithdrawals([StETH(1)], ZERO_ADDRESS, { from: user }) - await withdrawalQueue.finalize(i + 1, { from: steth.address, value: bn(ETH(1)).sub(bn(i * 1000)) }) + const batch = await withdrawalQueue.finalizationBatch(i + 1, shareRate(i + 1)) + await withdrawalQueue.finalize(i + 1, shareRate(i + 1), { + from: steth.address, + value: batch.ethToLock, + }) } assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 21) @@ -607,6 +604,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, let requestIds beforeEach(async () => { + await snapshot.rollback() await withdrawalQueue.requestWithdrawals(requestsAmounts, user, { from: user }) requestIds = await withdrawalQueue.getWithdrawalRequests(user, { from: user }) }) @@ -614,7 +612,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('direct', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: total }) + const batch = await withdrawalQueue.finalizationBatch(id, shareRate(300)) + withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: batch.ethToLock }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -655,8 +654,12 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const totalDistributedEth = bn(0) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] - await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(1 / (index + 1)) }) - totalDistributedEth.iadd(bn(ETH(1 / (index + 1)))) + const batch = await withdrawalQueue.finalizationBatch(requestId, shareRate(300 / (index + 1))) + await withdrawalQueue.finalize(requestId, shareRate(300 / (index + 1)), { + from: steth.address, + value: batch.ethToLock, + }) + totalDistributedEth.iadd(bn(batch.ethToLock)) } const id = await withdrawalQueue.getLastRequestId() withdrawalQueue.finalize(id, { from: steth.address, value: total }) @@ -675,14 +678,22 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const requestIds = await withdrawalQueue.getWithdrawalRequests(user, { from: user }) const id = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: finalizedWEI }) + await withdrawalQueue.finalize(id, shareRate(1), { from: steth.address, value: finalizedWEI }) const hints = await withdrawalQueue.findCheckpointHints( requestIds, 1, await withdrawalQueue.getLastCheckpointIndex() ) - const claimableEth = await withdrawalQueue.getClaimableEther(requestIds, hints) + + // this causes division by zero + const claimableEth = await withdrawalQueue.getClaimableEther(requestIds, hints).catch((e) => { + throw new Error( + // hack to fix error objects with bigInit causing `can't serialise bigInt` with wrong trace + JSON.parse(JSON.stringify(e, (_, value) => (typeof value === 'bigint' ? value.toString() : value))) + ) + }) + const totalClaimable = claimableEth.reduce((s, i) => s.iadd(i) && s, bn(0)) assert.equals(totalClaimable, finalizedWEI, `Total Claimable doesn't add up to finalized amount`) @@ -876,11 +887,16 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const discountedPrices = Array(numOfRequests) .fill() .map((_, i) => ETH(i)) + const sharesPerRequest = await steth.getSharesByPooledEth(ETH(20)) + const discountShareRates = discountedPrices.map((p) => shareRate(+p / +sharesPerRequest)) beforeEach(async () => { await withdrawalQueue.requestWithdrawals(requests, owner, { from: user }) for (let i = 1; i <= numOfRequests; i++) { - await withdrawalQueue.finalize(i, { from: steth.address, value: discountedPrices[i] }) + await withdrawalQueue.finalize(i, discountShareRates[i - 1], { + from: steth.address, + value: discountedPrices[i - 1], + }) } assert.equals(await withdrawalQueue.getLastCheckpointIndex(), numOfRequests) assert.equals( From 5f24bd8de96c279cbc4f13d14cf597b1b59d5a3f Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 7 Mar 2023 19:35:59 +0700 Subject: [PATCH 175/236] fix: add assert for claim amount --- test/0.8.9/withdrawal-queue.test.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 9bf324ad7..68d4ee9cf 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -616,10 +616,11 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: batch.ethToLock }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] - await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + const tx = await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + assert.emits(tx, 'WithdrawalClaimed', { requestId, owner: user, receiver: user, amountOfETH: ETH(1) }) } const balanceAfter = bn(await ethers.provider.getBalance(user)) - assert.equals(balanceBefore.add(bn(total)), balanceAfter) + assert.equals(balanceAfter, balanceBefore.add(bn(total))) }) it('reverse', async () => { @@ -629,7 +630,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, for (let index = requestIds.length - 1; index >= 0; index--) { const requestId = requestIds[index] - await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + const tx = await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + assert.emits(tx, 'WithdrawalClaimed', { requestId, owner: user, receiver: user, amountOfETH: ETH(1) }) } const balanceAfter = bn(await ethers.provider.getBalance(user)) assert.equals(balanceBefore.add(bn(total)), balanceAfter) @@ -643,7 +645,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, for (let index = 0; index < randomIds.length; index++) { const requestId = randomIds[index] - await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + const tx = await withdrawalQueue.claimWithdrawal(requestId, { from: user }) + assert.emits(tx, 'WithdrawalClaimed', { requestId, owner: user, receiver: user, amountOfETH: ETH(1) }) } const balanceAfter = bn(await ethers.provider.getBalance(user)) assert.equals(balanceBefore.add(bn(total)), balanceAfter) From c398d489f31066c492cc28e24bfd090f551a4866 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 7 Mar 2023 19:36:35 +0700 Subject: [PATCH 176/236] fix: order in assert --- test/0.8.9/withdrawal-queue.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 68d4ee9cf..27ce1f849 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -634,7 +634,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.emits(tx, 'WithdrawalClaimed', { requestId, owner: user, receiver: user, amountOfETH: ETH(1) }) } const balanceAfter = bn(await ethers.provider.getBalance(user)) - assert.equals(balanceBefore.add(bn(total)), balanceAfter) + assert.equals(balanceAfter, balanceBefore.add(bn(total))) }) it('random', async () => { @@ -649,7 +649,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert.emits(tx, 'WithdrawalClaimed', { requestId, owner: user, receiver: user, amountOfETH: ETH(1) }) } const balanceAfter = bn(await ethers.provider.getBalance(user)) - assert.equals(balanceBefore.add(bn(total)), balanceAfter) + assert.equals(balanceAfter, balanceBefore.add(bn(total))) }) it('different rates', async () => { @@ -671,7 +671,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.claimWithdrawal(requestId, { from: user }) } const balanceAfter = bn(await ethers.provider.getBalance(user)) - assert.equals(balanceBefore.add(totalDistributedEth), balanceAfter) + assert.equals(balanceAfter, balanceBefore.add(totalDistributedEth)) }) }) From 54e8022bb48209bc0132dbd1317787f115ba7ec4 Mon Sep 17 00:00:00 2001 From: Alexandr Tarelkin Date: Tue, 7 Mar 2023 15:42:25 +0300 Subject: [PATCH 177/236] tests: wq eth distribution --- contracts/0.8.9/WithdrawalQueueBase.sol | 2 +- package.json | 1 + test/0.8.9/withdrawal-queue-deploy.test.js | 26 +- ...drawal-queue-requests-finalization.test.js | 367 ++++++++++++++++++ yarn.lock | 8 + 5 files changed, 400 insertions(+), 4 deletions(-) create mode 100644 test/0.8.9/withdrawal-queue-requests-finalization.test.js diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index ac3269069..fbc6a279f 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -288,7 +288,7 @@ abstract contract WithdrawalQueueBase { } /// @notice Checks the finalization batches, calculates required ether and the amount of shares to burn and /// @param _batches finalization batches calculated offchain using `calculateFinalizationBatches` - /// @param _maxShareRate max possible share rate that will be used for request finalization + /// @param _maxShareRate max possible share rate that will be used for request finalization with 1e27 precision /// @return ethToLock amount of ether that should be sent with `finalize()` method later /// @return sharesToBurn amount of shares that belongs tho finalizable requests function prefinalize(uint256[] calldata _batches, uint256 _maxShareRate) diff --git a/package.json b/package.json index b70bc98b8..1d389849e 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,7 @@ "@aragon/os": "^4.4.0", "@openzeppelin/contracts": "3.4.0", "@openzeppelin/contracts-v4.4": "npm:@openzeppelin/contracts@4.4.1", + "mocha-param": "^2.0.1", "openzeppelin-solidity": "2.0.0" }, "overrides": { diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index b8c31e4a1..a75b007fc 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -1,7 +1,7 @@ const { artifacts, contract } = require('hardhat') -const { ZERO_ADDRESS } = require('../helpers/constants') +const { ZERO_ADDRESS, MAX_UINT256 } = require('../helpers/constants') -const { ETH } = require('../helpers/utils') +const { ETH, toBN } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') const { assert } = require('../helpers/assert') @@ -29,7 +29,12 @@ async function deployWithdrawalQueue({ const eip712StETH = await EIP712StETH.new(steth.address, { from: stethOwner }) await steth.initializeEIP712StETH(eip712StETH.address) - const { queue: withdrawalQueue } = await withdrawals.deploy(queueAdmin, steth.address, queueName, symbol) + const { queue: withdrawalQueue, impl: withdrawalQueueImplementation } = await withdrawals.deploy( + queueAdmin, + steth.address, + queueName, + symbol + ) const initTx = await withdrawalQueue.initialize(queueAdmin) @@ -51,6 +56,7 @@ async function deployWithdrawalQueue({ steth, withdrawalQueue, nftDescriptor, + withdrawalQueueImplementation, } } @@ -146,6 +152,20 @@ contract( 'ZeroMetadata()' ) }) + + it('implementation is petrified', async () => { + const { withdrawalQueueImplementation } = await deployWithdrawalQueue({ + stethOwner, + queueAdmin, + queuePauser, + queueResumer, + doResume: false, + }) + + assert.equals(await withdrawalQueueImplementation.getContractVersion(), toBN(MAX_UINT256)) + + await assert.reverts(withdrawalQueueImplementation.initialize(queueAdmin), 'NonZeroContractVersionOnInit()') + }) }) } ) diff --git a/test/0.8.9/withdrawal-queue-requests-finalization.test.js b/test/0.8.9/withdrawal-queue-requests-finalization.test.js new file mode 100644 index 000000000..a382ba48f --- /dev/null +++ b/test/0.8.9/withdrawal-queue-requests-finalization.test.js @@ -0,0 +1,367 @@ +const { contract, ethers } = require('hardhat') +const { itParam } = require('mocha-param') + +const { StETH, shareRate, e18, e27, toBN } = require('../helpers/utils') +const { assert } = require('../helpers/assert') +const { MAX_UINT256 } = require('../helpers/constants') +const { EvmSnapshot } = require('../helpers/blockchain') + +const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') + +contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, oracle, anotherUser]) => { + let withdrawalQueue, steth + + const snapshot = new EvmSnapshot(ethers.provider) + + let rebaseCounter = 0 + const setShareRate = async (rate) => { + const totalShares = await steth.getTotalShares() + await withdrawalQueue.onOracleReport(false, rebaseCounter, ++rebaseCounter, { from: daoAgent }) + await steth.setTotalPooledEther(totalShares.mul(toBN(e18(rate))).div(toBN(e18(1)))) + } + + const finalizeRequests = async ({ finalizationShareRate, maxTimeStamp, budget, expectedBatches }) => { + const calculatedBatches = await withdrawalQueue.calculateFinalizationBatches(finalizationShareRate, maxTimeStamp, [ + budget, + false, + [], + ]) + + assert.isTrue(calculatedBatches.finished) + assert.equalsDelta(calculatedBatches.ethBudget, 0, 2) + assert.equals(calculatedBatches.batches, expectedBatches) + + const batch = await withdrawalQueue.prefinalize.call(calculatedBatches.batches, finalizationShareRate) + + assert.equalsDelta(batch.ethToLock, budget, 2) + + await withdrawalQueue.finalize(calculatedBatches.batches, finalizationShareRate, { + from: daoAgent, + value: batch.ethToLock, + }) + + return { batch } + } + + before('Deploy', async () => { + const deployed = await deployWithdrawalQueue({ + stethOwner: owner, + queueAdmin: daoAgent, + queuePauser: daoAgent, + queueResumer: daoAgent, + queueFinalizer: daoAgent, + queueOracle: daoAgent, + }) + + steth = deployed.steth + withdrawalQueue = deployed.withdrawalQueue + + await steth.mintShares(user, e18(10)) + await steth.approve(withdrawalQueue.address, StETH(10), { from: user }) + await steth.mintShares(anotherUser, e18(10)) + await steth.approve(withdrawalQueue.address, StETH(10), { from: anotherUser }) + + await setShareRate(1) + await snapshot.make() + }) + + afterEach(async () => { + await snapshot.rollback() + }) + + context('1 request', () => { + itParam('same rate ', [0.25, 0.5, 1], async (postFinalizationRate) => { + const finalizationShareRate = shareRate(1) + const userRequestAmount = e18(1) + + await withdrawalQueue.requestWithdrawals([userRequestAmount], user, { from: user }) + assert.equals(await withdrawalQueue.unfinalizedStETH(), userRequestAmount) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + + await finalizeRequests({ + finalizationShareRate, + maxTimeStamp: MAX_UINT256, + budget: userRequestAmount, + expectedBatches: [1], + }) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), 0) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + + await setShareRate(postFinalizationRate) + + const userBalanceBefore = await ethers.provider.getBalance(user) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + assert.equals(await ethers.provider.getBalance(user), userBalanceBefore.add(userRequestAmount)) + + assert.equals(await ethers.provider.getBalance(withdrawalQueue.address), 0) + }) + + itParam('finalization rate is lower', [0.25, 0.5, 1, 2], async (postFinalizationRate) => { + const finalizationShareRate = shareRate(0.5) + const userRequestAmount = e18(1) + const budget = toBN(userRequestAmount).div(toBN(2)).toString() + + await withdrawalQueue.requestWithdrawals([userRequestAmount], user, { from: user }) + assert.equals(await withdrawalQueue.unfinalizedStETH(), userRequestAmount) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + + await setShareRate(0.5) + + await finalizeRequests({ + finalizationShareRate, + maxTimeStamp: MAX_UINT256, + budget, + expectedBatches: [1], + }) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), 0) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + + await setShareRate(postFinalizationRate) + + const userBalanceBefore = await ethers.provider.getBalance(user) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + assert.equals(await ethers.provider.getBalance(user), userBalanceBefore.add(e18(0.5))) + + assert.equals(await ethers.provider.getBalance(withdrawalQueue.address), 0) + }) + + itParam('finalization rate is higher', [0.25, 0.5, 1, 2, 4], async (postFinalizationRate) => { + const finalizationShareRate = shareRate(2) + const userRequestAmount = e18(1) + + await withdrawalQueue.requestWithdrawals([userRequestAmount], user, { from: user }) + assert.equals(await withdrawalQueue.unfinalizedStETH(), userRequestAmount) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + + await setShareRate(2) + + await finalizeRequests({ + finalizationShareRate, + maxTimeStamp: MAX_UINT256, + budget: userRequestAmount, + expectedBatches: [1], + }) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), 0) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + + await setShareRate(postFinalizationRate) + + const userBalanceBefore = await ethers.provider.getBalance(user) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + assert.equals(await ethers.provider.getBalance(user), userBalanceBefore.add(e18(1))) + + assert.equals(await ethers.provider.getBalance(withdrawalQueue.address), 0) + }) + }) + + context('2 users, 1 batch', () => { + ;[0.7].forEach(async (firstRequestRate) => { + ;[0.4, 0.7, 1].forEach(async (secondRequestRate) => { + ;[firstRequestRate, secondRequestRate, secondRequestRate - 0.1, secondRequestRate + 0.1].forEach( + async (finalizationRate) => { + ;[ + firstRequestRate, + firstRequestRate - 0.1, + firstRequestRate + 0.1, + secondRequestRate, + finalizationRate, + finalizationRate - 0.1, + finalizationRate + 0.1, + ].forEach(async (postFinalizationRate) => { + it(`rates: first request = ${firstRequestRate}, second request = ${secondRequestRate}, finalization = ${finalizationRate}, claim = ${postFinalizationRate}`, async () => { + await setShareRate(firstRequestRate) + const userRequestAmount = e18(1) + await withdrawalQueue.requestWithdrawals([userRequestAmount], user, { from: user }) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), userRequestAmount) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.balanceOf(anotherUser), 0) + + await setShareRate(secondRequestRate) + const anotherUserRequestAmount = e18(2) + await withdrawalQueue.requestWithdrawals([anotherUserRequestAmount], anotherUser, { from: anotherUser }) + + const userExpectedEthAmount = + finalizationRate >= firstRequestRate + ? toBN(userRequestAmount) + : toBN(userRequestAmount) + .mul(toBN(e27(finalizationRate))) + .div(toBN(e27(firstRequestRate))) + + const anotherUserExpectedEthAmount = + finalizationRate >= secondRequestRate + ? toBN(anotherUserRequestAmount) + : toBN(anotherUserRequestAmount) + .mul(toBN(e27(finalizationRate))) + .div(toBN(e27(secondRequestRate))) + + const totalRequestedAmount = userExpectedEthAmount.add(anotherUserExpectedEthAmount) + + const stETHRequested = toBN(userRequestAmount).add(toBN(anotherUserRequestAmount)) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), stETHRequested) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.balanceOf(anotherUser), 1) + + await setShareRate(finalizationRate) + + let expectedBatches = + (firstRequestRate <= finalizationRate && secondRequestRate <= finalizationRate) || + (firstRequestRate > finalizationRate && secondRequestRate > finalizationRate) + ? [2] + : [1, 2] + + // handling math accuracy + if (firstRequestRate === finalizationRate && secondRequestRate > finalizationRate) { + expectedBatches = [2] + } else if (firstRequestRate === finalizationRate && secondRequestRate < finalizationRate) { + expectedBatches = [1, 2] + } + + await finalizeRequests({ + finalizationShareRate: shareRate(finalizationRate), + maxTimeStamp: MAX_UINT256, + budget: totalRequestedAmount, + expectedBatches, + }) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), 0) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.balanceOf(anotherUser), 1) + + await setShareRate(postFinalizationRate) + + const userBalanceBefore = await ethers.provider.getBalance(user) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + assert.equalsDelta( + await ethers.provider.getBalance(user), + toBN(userBalanceBefore).add(userExpectedEthAmount), + 1 + ) + + const anotherUserBalanceBefore = await ethers.provider.getBalance(anotherUser) + await withdrawalQueue.claimWithdrawal(2, { from: anotherUser }) + assert.equalsDelta( + await ethers.provider.getBalance(anotherUser), + toBN(anotherUserBalanceBefore).add(anotherUserExpectedEthAmount), + 1 + ) + + assert.equalsDelta(await ethers.provider.getBalance(withdrawalQueue.address), 0, 2) + }) + }) + } + ) + }) + }) + }) + + context('2 users, 2 batch', () => { + ;[0.7].forEach(async (firstRequestRate) => { + ;[0.4, 0.7, 1].forEach(async (secondRequestRate) => { + ;[firstRequestRate, secondRequestRate, secondRequestRate - 0.1, secondRequestRate + 0.1].forEach( + async (firstFinalizationRate) => { + ;[firstRequestRate, secondRequestRate, secondRequestRate - 0.1, secondRequestRate + 0.1].forEach( + async (secondFinalizationRate) => { + ;[ + firstRequestRate, + firstRequestRate - 0.1, + firstRequestRate + 0.1, + secondRequestRate, + firstFinalizationRate, + firstFinalizationRate - 0.1, + firstFinalizationRate + 0.1, + secondFinalizationRate, + ].forEach(async (postFinalizationRate) => { + it(`rates: first request = ${firstRequestRate}, second request = ${secondRequestRate}, secondFinalizationRate = ${secondFinalizationRate}, firstFinalization = ${firstFinalizationRate}, claim = ${postFinalizationRate}`, async () => { + await setShareRate(firstRequestRate) + const userRequestAmount = e18(1) + await withdrawalQueue.requestWithdrawals([userRequestAmount], user, { from: user }) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), userRequestAmount) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.balanceOf(anotherUser), 0) + + await setShareRate(secondRequestRate) + const anotherUserRequestAmount = e18(2) + await withdrawalQueue.requestWithdrawals([anotherUserRequestAmount], anotherUser, { + from: anotherUser, + }) + + assert.equals( + await withdrawalQueue.unfinalizedStETH(), + toBN(userRequestAmount).add(toBN(anotherUserRequestAmount)) + ) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.balanceOf(anotherUser), 1) + + const userExpectedEthAmount = + firstFinalizationRate >= firstRequestRate + ? toBN(userRequestAmount) + : toBN(userRequestAmount) + .mul(toBN(e27(firstFinalizationRate))) + .div(toBN(e27(firstRequestRate))) + + const anotherUserExpectedEthAmount = + secondFinalizationRate >= secondRequestRate + ? toBN(anotherUserRequestAmount) + : toBN(anotherUserRequestAmount) + .mul(toBN(e27(secondFinalizationRate))) + .div(toBN(e27(secondRequestRate))) + + const stETHRequested = toBN(userRequestAmount).add(toBN(anotherUserRequestAmount)) + + assert.equals(await withdrawalQueue.unfinalizedStETH(), stETHRequested) + assert.equals(await withdrawalQueue.balanceOf(user), 1) + assert.equals(await withdrawalQueue.balanceOf(anotherUser), 1) + + await setShareRate(firstFinalizationRate) + + await finalizeRequests({ + finalizationShareRate: shareRate(firstFinalizationRate), + maxTimeStamp: MAX_UINT256, + budget: userExpectedEthAmount, + expectedBatches: [1], + }) + + await setShareRate(secondFinalizationRate) + + await finalizeRequests({ + finalizationShareRate: shareRate(secondFinalizationRate), + maxTimeStamp: MAX_UINT256, + budget: anotherUserExpectedEthAmount, + expectedBatches: [2], + }) + + await setShareRate(postFinalizationRate) + + const userBalanceBefore = await ethers.provider.getBalance(user) + await withdrawalQueue.claimWithdrawal(1, { from: user }) + assert.equalsDelta( + await ethers.provider.getBalance(user), + toBN(userBalanceBefore).add(userExpectedEthAmount), + 1 + ) + + const anotherUserBalanceBefore = await ethers.provider.getBalance(anotherUser) + await withdrawalQueue.claimWithdrawal(2, { from: anotherUser }) + assert.equalsDelta( + await ethers.provider.getBalance(anotherUser), + toBN(anotherUserBalanceBefore).add(anotherUserExpectedEthAmount), + 1 + ) + + assert.equalsDelta(await ethers.provider.getBalance(withdrawalQueue.address), 0, 2) + }) + }) + } + ) + } + ) + }) + }) + }) +}) diff --git a/yarn.lock b/yarn.lock index 3101a03f7..e2cbe9895 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3751,6 +3751,7 @@ __metadata: lerna: ^3.22.1 lint-staged: ">=10" minimatch: ^6.2.0 + mocha-param: ^2.0.1 node-gyp: ^8.4.1 openzeppelin-solidity: 2.0.0 prettier: ^2.8.4 @@ -19574,6 +19575,13 @@ fsevents@~2.3.2: languageName: node linkType: hard +"mocha-param@npm:^2.0.1": + version: 2.0.1 + resolution: "mocha-param@npm:2.0.1" + checksum: a4dee1c32fdee27c6fd83c13a41a01148e2d5f2fd7440a29fc8d817027afde11ded3017556a2492485f611d64d738065c5e5d2cb5a49891d97872c2a9433724f + languageName: node + linkType: hard + "mocha@npm:7.1.2": version: 7.1.2 resolution: "mocha@npm:7.1.2" From 56675bf940d9546e12716ae5715da31a5cd24c7c Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 7 Mar 2023 19:47:12 +0700 Subject: [PATCH 178/236] fix: claim tests --- test/0.8.9/withdrawal-queue.test.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 27ce1f849..ed64d4160 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -601,6 +601,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const requestCount = 5 const requestsAmounts = Array(requestCount).fill(StETH(1)) const total = StETH(requestCount) + const normalizedShareRate = shareRate(+total / +(await steth.getSharesByPooledEth(total))) let requestIds beforeEach(async () => { @@ -612,8 +613,9 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('direct', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - const batch = await withdrawalQueue.finalizationBatch(id, shareRate(300)) - withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: batch.ethToLock }) + const batch = await withdrawalQueue.finalizationBatch(id, normalizedShareRate) + assert.equals(total, batch.ethToLock) + withdrawalQueue.finalize(id, normalizedShareRate, { from: steth.address, value: batch.ethToLock }) for (let index = 0; index < requestIds.length; index++) { const requestId = requestIds[index] const tx = await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -626,8 +628,9 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('reverse', async () => { const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: total }) - + const batch = await withdrawalQueue.finalizationBatch(id, normalizedShareRate) + assert.equals(total, batch.ethToLock) + withdrawalQueue.finalize(id, normalizedShareRate, { from: steth.address, value: batch.ethToLock }) for (let index = requestIds.length - 1; index >= 0; index--) { const requestId = requestIds[index] const tx = await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -641,8 +644,9 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const randomIds = [...requestIds].sort(() => 0.5 - Math.random()) const balanceBefore = bn(await ethers.provider.getBalance(user)) const id = await withdrawalQueue.getLastRequestId() - withdrawalQueue.finalize(id, shareRate(300), { from: steth.address, value: total }) - + const batch = await withdrawalQueue.finalizationBatch(id, normalizedShareRate) + assert.equals(total, batch.ethToLock) + withdrawalQueue.finalize(id, normalizedShareRate, { from: steth.address, value: batch.ethToLock }) for (let index = 0; index < randomIds.length; index++) { const requestId = randomIds[index] const tx = await withdrawalQueue.claimWithdrawal(requestId, { from: user }) @@ -675,7 +679,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) - context('claim fuzzing', () => { + context.skip('claim fuzzing', () => { const fuzzClaim = async (perRequestWEI, requestCount, finalizedWEI) => { await withdrawalQueue.requestWithdrawals(Array(requestCount).fill(perRequestWEI), user, { from: user }) const requestIds = await withdrawalQueue.getWithdrawalRequests(user, { from: user }) @@ -723,11 +727,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await steth.mintSteth(user, { from: stranger, value: total }) await fuzzClaim(MAX_STETH_WITHDRAWAL_AMOUNT.toString(10), 10, 10) }) - - // problematic test - it.skip('distribute&claim 0.1wei per 100*100WEI requests', async () => { - await fuzzClaim(100, 100, 10) - }) }) context('findLastFinalizableRequestIdByTimestamp()', async () => { From afbb4df9bb6374608b00f721b468e961d6ed3377 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 7 Mar 2023 15:56:20 +0300 Subject: [PATCH 179/236] test: add test for simulated share rate with limit --- test/0.4.24/lido-handle-oracle-report.test.js | 116 +++++++++++++++++- 1 file changed, 113 insertions(+), 3 deletions(-) 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 32b5c1328..563c0d389 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -13,7 +13,13 @@ const { limitRebase, } = require('../helpers/utils') const { deployProtocol } = require('../helpers/protocol') -const { EvmSnapshot, setBalance, advanceChainTime, getCurrentBlockTimestamp } = require('../helpers/blockchain') +const { + EvmSnapshot, + setBalance, + advanceChainTime, + getCurrentBlockTimestamp, + getBalance, +} = require('../helpers/blockchain') const { ZERO_ADDRESS, INITIAL_HOLDER } = require('../helpers/constants') const { setupNodeOperatorsRegistry } = require('../helpers/staking-modules') @@ -2059,8 +2065,112 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot await withdrawalQueue.claimWithdrawal(1, { from: stranger }) }) - it.skip('check simulated share rate correctness when limit is higher due to withdrawals', async () => { - // TODO + it('check simulated share rate correctness when limit is higher due to withdrawals', async () => { + // Execution layer rewards and withdrawal vault balance to report + // NB: both don't exceed daily rebase by themselves + await setBalance(elRewardsVault, ETH(0.25)) + await setBalance(withdrawalVault, ETH(0.5)) + + // Bob decides to burn stETH amount corresponding to ETH(1) + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1) }) + const sharesRequestedToBurn = await lido.sharesOf(bob) + await lido.approve(burner.address, await lido.balanceOf(bob), { from: bob }) + await burner.requestBurnShares(bob, sharesRequestedToBurn, { from: voting }) + + // Check that we haven't finalized anything yet + assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), toBN(0)) + await withdrawalQueue.resume({ from: appManager }) + assert.isFalse(await withdrawalQueue.isPaused()) + + // Stranger decides to withdraw his stETH(1) + await lido.approve(withdrawalQueue.address, StETH(1), { from: stranger }) + await withdrawalQueue.requestWithdrawals([StETH(1)], stranger, { from: stranger }) + assert.equals(await withdrawalQueue.unfinalizedStETH(), StETH(1)) + assert.equals(await withdrawalQueue.unfinalizedRequestNumber(), 1) + + // Setting daily positive rebase as 1% + await oracleReportSanityChecker.setOracleReportLimits( + { + ...ORACLE_REPORT_LIMITS_BOILERPLATE, + churnValidatorsPerDayLimit: 100, + maxPositiveTokenRebase: 10000000, + }, + { from: voting, gasPrice: 1 } + ) + + await advanceChainTime(30) + + // Performing dry-run to estimate simulated share rate + const [postTotalPooledEther, postTotalShares, withdrawals, elRewards] = await lido.handleOracleReport.call( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.25), + withdrawalVaultBalance: ETH(0.5), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + // Ensuring that vaults don't hit the positive rebase limit + assert.equals(await getBalance(elRewardsVault), elRewards) + assert.equals(await getBalance(withdrawalVault), withdrawals) + const simulatedShareRate = postTotalPooledEther.mul(toBN(shareRate(1))).div(postTotalShares) + + await advanceChainTime(30) + + // Bob decides to stake in between reference slot and real report submission + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(1.137) }) + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(0.17) }) + await lido.submit(ZERO_ADDRESS, { from: bob, value: ETH(0.839) }) + + // Sending the real report with finalization attempts + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + reportTimestamp: await getCurrentBlockTimestamp(), + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0.25), + withdrawalVaultBalance: ETH(0.5), + sharesRequestedToBurn: sharesRequestedToBurn.toString(), + lastFinalizableWithdrawalRequestId: 1, + simulatedShareRate: simulatedShareRate.toString(), + }), + { from: oracle, gasPrice: 1 } + ) + // Checking that both vaults are withdrawn + assert.equals(await getBalance(elRewardsVault), toBN(0)) + assert.equals(await getBalance(withdrawalVault), toBN(0)) + // But have excess shares to burn later + let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() + assert.isTrue(sharesRequestedToBurn.gt(coverShares.add(nonCoverShares))) + assert.isTrue(coverShares.add(nonCoverShares).gt(toBN(0))) + + // Checking that finalization of the previously placed withdrawal request completed + assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), toBN(1)) + await withdrawalQueue.claimWithdrawal(1, { from: stranger }) + + // Reporting once again allowing shares to be burnt completely + await lido.handleOracleReport( + ...Object.values({ + ...DEFAULT_LIDO_ORACLE_REPORT, + reportTimestamp: await getCurrentBlockTimestamp(), + timeElapsed: ONE_DAY, + clValidators: 3, + postCLBalance: ETH(96.1), + elRewardsVaultBalance: ETH(0), + withdrawalVaultBalance: ETH(0), + sharesRequestedToBurn: coverShares.add(nonCoverShares).toString(), + }), + { from: oracle, gasPrice: 1 } + ) + // Checking that no shares to burn remain + ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) + assert.equals(coverShares, toBN(0)) + assert.equals(nonCoverShares, toBN(0)) }) }) }) From 361555355a28102ed5a58c600d9c36bccf4e1937 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 7 Mar 2023 14:55:48 +0200 Subject: [PATCH 180/236] =?UTF-8?q?=F0=9F=93=9A:=20better=20docs=20for=20w?= =?UTF-8?q?q?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 29 ++++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index fbc6a279f..f9fa9cddb 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -10,7 +10,7 @@ import {Math} from "./lib/Math.sol"; import {MemUtils} from "../common/lib/MemUtils.sol"; /// @title Queue to store and manage WithdrawalRequests. -/// @dev Use an optimizations to store discounts heavily inspired +/// @dev Use an optimizations to store max share rates for finalized requests heavily inspired /// by Aragon MiniMe token https://github.com/aragon/aragon-minime/blob/master/contracts/MiniMeToken.sol /// /// @author folkyatina @@ -250,6 +250,7 @@ abstract contract WithdrawalQueueBase { (uint256 requestShareRate, uint256 ethToFinalize, uint256 shares) = _calcBatch(prevRequest, request); if (requestShareRate > _maxShareRate) { + // discounted ethToFinalize = (shares * _maxShareRate) / E27_PRECISION_BASE; } @@ -263,14 +264,16 @@ abstract contract WithdrawalQueueBase { // so we're counting requests that are placed during the same report day // as equal even if their actual share rate are different prevRequest.reportTimestamp == request.reportTimestamp || + // both requests are below or prevShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || + // both are above the line prevShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { _state.batches[batchesLength - 1] = requestId; } else { - if (batchesLength == MAX_BATCHES_LENGTH) break; // gas limit break + // to be able to check batches on-chain we need it to have fixed max length - _state.batches[batchesLength] = requestId; + // create a new batch batchesLength = ++_state.batches[MAX_BATCHES_LENGTH]; } @@ -313,13 +316,15 @@ abstract contract WithdrawalQueueBase { if (batchIndex > 0) { // - if shareRate(batch[i]) is below _maxShareRate => shareRate(batch[i+1]) is above and vice versa - if (batchShareRate <= _maxShareRate && prevBatchShareRate <= _maxShareRate) revert InvalidBatch(batchIndex); - if (batchShareRate > _maxShareRate && prevBatchShareRate > _maxShareRate) revert InvalidBatch(batchIndex); + // so, we can't have two batches in a row that is below... + // .. or above the line } if (batchShareRate > _maxShareRate) { + // discounted ethToLock += shares * _maxShareRate / E27_PRECISION_BASE; } else { + // nominal ethToLock += stETH; } sharesToBurn += shares; @@ -332,6 +337,8 @@ abstract contract WithdrawalQueueBase { /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` /// Emits WithdrawalBatchFinalized event. + /// Checks that: + /// - _amountOfETH is less or equal to the nominal value of all requests to be finalized function _finalize(uint256[] memory _batches, uint256 _amountOfETH, uint256 _maxShareRate) internal { uint256 nextFinalizedRequestId = _batches[_batches.length - 1]; if (nextFinalizedRequestId > getLastRequestId()) revert InvalidRequestId(nextFinalizedRequestId); @@ -345,8 +352,13 @@ abstract contract WithdrawalQueueBase { uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); + // if `_maxShareRate` is effectively above all of finalizing requests' share rates + // we can effectively say that there is no limit because all the request + // will be fullfilled by their nominal value uint256 maxShareRate = SHARE_RATE_UNLIMITED; // if we have a crossing point or avg batch share rate is more than `_maxShareRate` + // then there are some requests that will be discounted and we should store + // `_maxShareRate` to apply this discount on claim if (_batches.length > 1 || stETHToFinalize > _amountOfETH) { maxShareRate = _maxShareRate; } @@ -354,6 +366,8 @@ abstract contract WithdrawalQueueBase { uint256 lastCheckpointIndex = getLastCheckpointIndex(); Checkpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; + // In the most common scenario (no slashings) maxShareRate will be SHARE_RATE_UNLIMITED all the time + // and we'll save gas on report and integrations will save gas on hint calculations if (maxShareRate != lastCheckpoint.maxShareRate) { // add a new discount if it differs from the previous _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstUnfinalizedRequestId, maxShareRate); @@ -489,7 +503,9 @@ abstract contract WithdrawalQueueBase { assert(_getRequestsByOwner()[request.owner].remove(_requestId)); uint256 ethWithDiscount = _calculateClaimableEther(request, _requestId, _hint); - + // because of the stETH rounding issue + // (issue: https://github.com/lidofinance/lido-dao/issues/442 ) + // some dust (1-2 wei per request) will be accumulated upon claiming _setLockedEtherAmount(getLockedEtherAmount() - ethWithDiscount); _sendValue(payable(_recipient), ethWithDiscount); @@ -509,6 +525,7 @@ abstract contract WithdrawalQueueBase { if (_hint > lastCheckpointIndex) revert InvalidHint(_hint); Checkpoint memory checkpoint = _getCheckpoints()[_hint]; + // Reverts if requestId is not in range [checkpoint[hint], checkpoint[hint+1]) // ______(>______ // ^ hint if (_requestId < checkpoint.fromRequestId) revert InvalidHint(_hint); From 20603d555485fd1405d7a857818251aac3929622 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 7 Mar 2023 14:58:57 +0200 Subject: [PATCH 181/236] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F:=20wq=20refactori?= =?UTF-8?q?ng=20to=20improve=20readability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 75 +++++++++++++------------ 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index f9fa9cddb..b59d733f3 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -233,20 +233,18 @@ abstract contract WithdrawalQueueBase { } else { batchesLength = _state.batches[MAX_BATCHES_LENGTH]; uint256 lastHandledRequestId = _state.batches[batchesLength - 1]; - (prevShareRate,,) = _calcBatch(_getQueue()[lastHandledRequestId - 1], _getQueue()[lastHandledRequestId]); start = lastHandledRequestId + 1; + (prevShareRate,,) = _calcBatch(_getQueue()[lastHandledRequestId - 1], _getQueue()[lastHandledRequestId]); } - uint256 requestId = start; - while (requestId < start + MAX_REQUESTS_PER_CALL) { - if (requestId > lastRequestId) break; // end of the queue break + uint256 currentId = start; + WithdrawalRequest memory prevRequest = _getQueue()[currentId - 1]; + while (currentId <= lastRequestId && currentId < start + MAX_REQUESTS_PER_CALL) { + WithdrawalRequest memory request = _getQueue()[currentId]; - WithdrawalRequest memory request = _getQueue()[requestId]; - // max timestamp break - if (request.timestamp > _maxTimestamp) break; + if (request.timestamp > _maxTimestamp) break; // max timestamp break - WithdrawalRequest memory prevRequest = _getQueue()[requestId - 1]; (uint256 requestShareRate, uint256 ethToFinalize, uint256 shares) = _calcBatch(prevRequest, request); if (requestShareRate > _maxShareRate) { @@ -255,7 +253,6 @@ abstract contract WithdrawalQueueBase { } if (ethToFinalize > _state.ethBudget) break; // budget break - _state.ethBudget -= ethToFinalize; if (batchesLength != 0 && ( @@ -269,19 +266,22 @@ abstract contract WithdrawalQueueBase { // both are above the line prevShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { - _state.batches[batchesLength - 1] = requestId; + _state.batches[batchesLength - 1] = currentId; // extend the last batch } else { // to be able to check batches on-chain we need it to have fixed max length + if (batchesLength == MAX_BATCHES_LENGTH) break; // create a new batch + _state.batches[batchesLength] = currentId; batchesLength = ++_state.batches[MAX_BATCHES_LENGTH]; } prevShareRate = requestShareRate; - unchecked{ ++requestId; } + prevRequest = request; + unchecked{ ++currentId; } } - _state.finished = requestId < start + MAX_REQUESTS_PER_CALL || requestId == lastRequestId + 1; + _state.finished = currentId < start + MAX_REQUESTS_PER_CALL || currentId == lastRequestId + 1; if (_state.finished) { MemUtils.trimUint256Array(_state.batches, _state.batches.length - batchesLength); @@ -305,19 +305,24 @@ abstract contract WithdrawalQueueBase { if (_batches[0] <= getLastFinalizedRequestId()) revert InvalidRequestId(_batches[0]); if (_batches[_batches.length - 1] > getLastRequestId()) revert InvalidRequestId(_batches[_batches.length - 1]); - WithdrawalRequest memory prevBatchEnd = _getQueue()[getLastFinalizedRequestId()]; + uint256 currentBatchIndex; + uint256 prevBatchEndRequestId = getLastFinalizedRequestId(); + WithdrawalRequest memory prevBatchEnd = _getQueue()[prevBatchEndRequestId]; uint256 prevBatchShareRate; + while (currentBatchIndex < _batches.length) { + uint256 batchEndRequestId = _batches[currentBatchIndex]; + if (batchEndRequestId <= prevBatchEndRequestId) revert InvalidBatch(currentBatchIndex); - uint256 batchIndex; - do { - WithdrawalRequest memory batchEnd = _getQueue()[_batches[batchIndex]]; + WithdrawalRequest memory batchEnd = _getQueue()[batchEndRequestId]; (uint256 batchShareRate, uint256 stETH, uint256 shares) = _calcBatch(prevBatchEnd, batchEnd); - if (batchIndex > 0) { + if (currentBatchIndex > 0) { // - if shareRate(batch[i]) is below _maxShareRate => shareRate(batch[i+1]) is above and vice versa // so, we can't have two batches in a row that is below... + if (prevBatchShareRate <= _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatch(currentBatchIndex); // .. or above the line + if (prevBatchShareRate > _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatch(currentBatchIndex); } if (batchShareRate > _maxShareRate) { @@ -330,9 +335,10 @@ abstract contract WithdrawalQueueBase { sharesToBurn += shares; prevBatchShareRate = batchShareRate; + prevBatchEndRequestId = batchEndRequestId; prevBatchEnd = batchEnd; - unchecked{ ++batchIndex; } - } while (batchIndex < _batches.length); + unchecked{ ++currentBatchIndex; } + } } /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` @@ -340,14 +346,14 @@ abstract contract WithdrawalQueueBase { /// Checks that: /// - _amountOfETH is less or equal to the nominal value of all requests to be finalized function _finalize(uint256[] memory _batches, uint256 _amountOfETH, uint256 _maxShareRate) internal { - uint256 nextFinalizedRequestId = _batches[_batches.length - 1]; - if (nextFinalizedRequestId > getLastRequestId()) revert InvalidRequestId(nextFinalizedRequestId); + if (_batches.length == 0) revert EmptyBatches(); + uint256 lastRequestIdToBeFinalized = _batches[_batches.length - 1]; + if (lastRequestIdToBeFinalized > getLastRequestId()) revert InvalidRequestId(lastRequestIdToBeFinalized); uint256 lastFinalizedRequestId = getLastFinalizedRequestId(); - uint256 firstUnfinalizedRequestId = lastFinalizedRequestId + 1; - if (nextFinalizedRequestId <= lastFinalizedRequestId) revert InvalidRequestId(nextFinalizedRequestId); + if (lastRequestIdToBeFinalized <= lastFinalizedRequestId) revert InvalidRequestId(lastRequestIdToBeFinalized); WithdrawalRequest memory lastFinalizedRequest = _getQueue()[lastFinalizedRequestId]; - WithdrawalRequest memory requestToFinalize = _getQueue()[nextFinalizedRequestId]; + WithdrawalRequest memory requestToFinalize = _getQueue()[lastRequestIdToBeFinalized]; uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); @@ -363,6 +369,7 @@ abstract contract WithdrawalQueueBase { maxShareRate = _maxShareRate; } + uint256 firstRequestIdToFinalize = lastFinalizedRequestId + 1; uint256 lastCheckpointIndex = getLastCheckpointIndex(); Checkpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; @@ -370,16 +377,16 @@ abstract contract WithdrawalQueueBase { // and we'll save gas on report and integrations will save gas on hint calculations if (maxShareRate != lastCheckpoint.maxShareRate) { // add a new discount if it differs from the previous - _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstUnfinalizedRequestId, maxShareRate); + _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstRequestIdToFinalize, maxShareRate); _setLastCheckpointIndex(lastCheckpointIndex + 1); } _setLockedEtherAmount(getLockedEtherAmount() + _amountOfETH); - _setLastFinalizedRequestId(nextFinalizedRequestId); + _setLastFinalizedRequestId(lastRequestIdToBeFinalized); emit WithdrawalBatchFinalized( - firstUnfinalizedRequestId, - nextFinalizedRequestId, + firstRequestIdToFinalize, + lastRequestIdToBeFinalized, _amountOfETH, requestToFinalize.cumulativeShares - lastFinalizedRequest.cumulativeShares, block.timestamp @@ -533,19 +540,17 @@ abstract contract WithdrawalQueueBase { // ______(>______(>________ // hint hint+1 ^ Checkpoint memory nextCheckpoint = _getCheckpoints()[_hint + 1]; - if (nextCheckpoint.fromRequestId <= _requestId) { - revert InvalidHint(_hint); - } + if (nextCheckpoint.fromRequestId <= _requestId) revert InvalidHint(_hint); } WithdrawalRequest memory prevRequest = _getQueue()[_requestId - 1]; - (uint256 batchShareRate, uint256 stETH, uint256 shares) = _calcBatch(prevRequest, _request); + (uint256 batchShareRate, uint256 eth, uint256 shares) = _calcBatch(prevRequest, _request); - if (batchShareRate <= checkpoint.maxShareRate) { - return stETH; + if (batchShareRate > checkpoint.maxShareRate) { + eth = shares * checkpoint.maxShareRate / E27_PRECISION_BASE; } - return shares * checkpoint.maxShareRate / E27_PRECISION_BASE; + return eth; } // quazi-constructor From 4c494ca6c2cd192961c9fbd3823d3f66379c9213 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Tue, 7 Mar 2023 15:36:10 +0200 Subject: [PATCH 182/236] fix: remove unused UnstructuredRefStorage method --- contracts/0.8.9/lib/UnstructuredRefStorage.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/contracts/0.8.9/lib/UnstructuredRefStorage.sol b/contracts/0.8.9/lib/UnstructuredRefStorage.sol index 0814c0430..322e9e51c 100644 --- a/contracts/0.8.9/lib/UnstructuredRefStorage.sol +++ b/contracts/0.8.9/lib/UnstructuredRefStorage.sol @@ -4,12 +4,6 @@ pragma solidity 0.8.9; library UnstructuredRefStorage { - function storageUint256Array(bytes32 _position) internal pure returns ( - uint256[] storage result - ) { - assembly { result.slot := _position } - } - function storageAddressArray(bytes32 _position) internal pure returns ( address[] storage result ) { From 7a773ac79fc586529e5c1ee8b866d0169fbaa843 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Tue, 7 Mar 2023 17:08:30 +0200 Subject: [PATCH 183/236] withdrawal queue: add integration/gas test (WIP) --- .../test_helpers/AccountingOracleMock.sol | 35 +-- .../0.8.9/test_helpers/StakingModuleMock.sol | 7 +- test/helpers/debug.js | 21 ++ test/helpers/factories.js | 31 ++- test/helpers/oracle.js | 124 ++++++---- test/helpers/reportData.js | 28 +-- ...ido-wq-acct-oracle-integration-gas.test.js | 223 ++++++++++++++++++ 7 files changed, 374 insertions(+), 95 deletions(-) create mode 100644 test/helpers/debug.js create mode 100644 test/scenario/lido-wq-acct-oracle-integration-gas.test.js diff --git a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol index d3ef4f356..93dc8ef6c 100644 --- a/contracts/0.8.9/test_helpers/AccountingOracleMock.sol +++ b/contracts/0.8.9/test_helpers/AccountingOracleMock.sol @@ -7,23 +7,6 @@ pragma solidity 0.8.9; import {AccountingOracle, ILido} from "../oracle/AccountingOracle.sol"; -// TODO: remove and use ILido -interface ILidoTemporary { - function handleOracleReport( - // CL values - uint256 _clValidators, - uint256 _clBalance, - // EL values - uint256 _withdrawalVaultBalance, - uint256 _elRewardsVaultBalance, - uint256 _sharesRequestedToBurn, - // decision - uint256 _requestIdToFinalizeUpTo, - uint256 _finalizationShareRate - ) external returns (uint256, uint256); -} - - contract AccountingOracleMock { address public immutable LIDO; uint256 public immutable SECONDS_PER_SLOT; @@ -39,24 +22,12 @@ contract AccountingOracleMock { AccountingOracle.ReportData calldata data, uint256 /* contractVersion */ ) external { - // TODO: remove the line below - // solhint-disable-next-line uint256 slotsElapsed = data.refSlot - _lastRefSlot; _lastRefSlot = data.refSlot; - // TODO: update to use the actual signature - // ILido(LIDO).handleOracleReport( - // slotsElapsed * SECONDS_PER_SLOT, - // data.numValidators, - // data.clBalanceGwei * 1e9, - // data.withdrawalVaultBalance, - // data.elRewardsVaultBalance, - // data.lastFinalizableWithdrawalRequestId, - // data.simulatedShareRate, - // data.isBunkerMode - // ); - - ILidoTemporary(LIDO).handleOracleReport( + ILido(LIDO).handleOracleReport( + data.refSlot * SECONDS_PER_SLOT, + slotsElapsed * SECONDS_PER_SLOT, data.numValidators, data.clBalanceGwei * 1e9, data.withdrawalVaultBalance, diff --git a/contracts/0.8.9/test_helpers/StakingModuleMock.sol b/contracts/0.8.9/test_helpers/StakingModuleMock.sol index 00d1227ad..6e6f3cf84 100644 --- a/contracts/0.8.9/test_helpers/StakingModuleMock.sol +++ b/contracts/0.8.9/test_helpers/StakingModuleMock.sol @@ -109,13 +109,16 @@ contract StakingModuleMock is IStakingModule { _availableValidatorsCount = _activeValidatorsCount; } - function obtainDepositData(uint256 _depositsCount, bytes calldata _calldata) + function obtainDepositData(uint256 _depositsCount, bytes calldata) external returns ( bytes memory publicKeys, bytes memory signatures ) - {} + { + publicKeys = new bytes(48 * _depositsCount); + signatures = new bytes(96 * _depositsCount); + } function setTotalExitedValidatorsCount(uint256 newExitedValidatorsCount) external { _exitedValidatorsCount = newExitedValidatorsCount; diff --git a/test/helpers/debug.js b/test/helpers/debug.js new file mode 100644 index 000000000..b351e1e2a --- /dev/null +++ b/test/helpers/debug.js @@ -0,0 +1,21 @@ +const { BN } = require('bn.js') + +// transforms all object entries +const transformEntries = (obj, tr) => + Object.fromEntries( + Object.entries(obj) + .map(tr) + .filter((x) => x !== undefined) + ) + +// converts all object BN keys to strings, drops numeric keys and the __length__ key +const processNamedTuple = (obj) => + transformEntries(obj, ([k, v]) => { + return /^(\d+|__length__)$/.test(k) ? undefined : [k, BN.isBN(v) ? v.toString() : v] + }) + +const printEvents = (tx) => { + console.log(tx.receipt.logs.map(({ event, args }) => ({ event, args: processNamedTuple(args) }))) +} + +module.exports = { transformEntries, processNamedTuple, printEvents } diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 3f5d2ed2f..a00e79e5e 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -133,12 +133,6 @@ async function hashConsensusFactory({ voting, oracle, signers, legacyOracle, dep await consensus.addMember(signers[3].address, 2, { from: voting.address }) await consensus.addMember(signers[4].address, 2, { from: voting.address }) - await oracle.initialize(voting.address, consensus.address, CONSENSUS_VERSION) - - await oracle.grantRole(await oracle.MANAGE_CONSENSUS_CONTRACT_ROLE(), voting.address, { from: voting.address }) - await oracle.grantRole(await oracle.MANAGE_CONSENSUS_VERSION_ROLE(), voting.address, { from: voting.address }) - await oracle.grantRole(await oracle.SUBMIT_DATA_ROLE(), voting.address, { from: voting.address }) - return consensus } @@ -172,6 +166,7 @@ async function hashConsensusTimeTravellableFactory({ await consensus.addMember(signers[2].address, 1, { from: voting.address }) await consensus.addMember(signers[3].address, 2, { from: voting.address }) await consensus.addMember(signers[4].address, 2, { from: voting.address }) + await consensus.setTime(deployParams.genesisTime + initialEpoch * SLOTS_PER_EPOCH * SECONDS_PER_SLOT) return consensus @@ -327,7 +322,23 @@ async function oracleReportSanityCheckerFactory({ lidoLocator, voting, appManage deployParams.oracleReportSanityChecker.managersRoster ) - await checker.grantRole(await checker.ALL_LIMITS_MANAGER_ROLE(), voting.address, { from: appManager.address }) + await grantRoles({ + by: appManager.address, + on: checker, + to: voting.address, + roles: [ + 'ALL_LIMITS_MANAGER_ROLE', + 'CHURN_VALIDATORS_PER_DAY_LIMIT_MANGER_ROLE', + 'ONE_OFF_CL_BALANCE_DECREASE_LIMIT_MANAGER_ROLE', + 'ANNUAL_BALANCE_INCREASE_LIMIT_MANAGER_ROLE', + 'SHARE_RATE_DEVIATION_LIMIT_MANAGER_ROLE', + 'MAX_VALIDATOR_EXIT_REQUESTS_PER_REPORT_ROLE', + 'MAX_ACCOUNTING_EXTRA_DATA_LIST_ITEMS_COUNT_ROLE', + 'MAX_NODE_OPERATORS_PER_EXTRA_DATA_ITEM_COUNT_ROLE', + 'REQUEST_TIMESTAMP_MARGIN_MANAGER_ROLE', + 'MAX_POSITIVE_TOKEN_REBASE_MANAGER_ROLE', + ], + }) return checker } @@ -355,11 +366,17 @@ async function postSetup({ appManager, voting, deployParams, + oracle, legacyOracle, consensusContract, }) { await pool.initialize(lidoLocator.address, eip712StETH.address, { value: ETH(1) }) + await oracle.initialize(voting.address, consensusContract.address, CONSENSUS_VERSION) + await oracle.grantRole(await oracle.MANAGE_CONSENSUS_CONTRACT_ROLE(), voting.address, { from: voting.address }) + await oracle.grantRole(await oracle.MANAGE_CONSENSUS_VERSION_ROLE(), voting.address, { from: voting.address }) + await oracle.grantRole(await oracle.SUBMIT_DATA_ROLE(), voting.address, { from: voting.address }) + await legacyOracle.initialize(lidoLocator.address, consensusContract.address) await depositContract.reset() diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index dbdb52598..85c36b2dc 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -2,24 +2,25 @@ const { web3 } = require('hardhat') const { CONSENSUS_VERSION, ZERO_BYTES32 } = require('./constants') const { assert } = require('./assert') +const { toBN } = require('./utils') function getReportDataItems(r) { return [ - r.consensusVersion, - +r.refSlot, - r.numValidators, - r.clBalanceGwei, - r.stakingModuleIdsWithNewlyExitedValidators, - r.numExitedValidatorsByStakingModule, - r.withdrawalVaultBalance, - r.elRewardsVaultBalance, - r.requestedToBurnShares, - r.lastWithdrawalRequestIdToFinalize, - r.finalizationShareRate, + String(r.consensusVersion), + String(r.refSlot), + String(r.numValidators), + String(r.clBalanceGwei), + r.stakingModuleIdsWithNewlyExitedValidators.map(String), + r.numExitedValidatorsByStakingModule.map(String), + String(r.withdrawalVaultBalance), + String(r.elRewardsVaultBalance), + String(r.sharesRequestedToBurn), + String(r.lastFinalizableWithdrawalRequestId), + String(r.simulatedShareRate), r.isBunkerMode, - r.extraDataFormat, - r.extraDataHash, - r.extraDataItemsCount, + String(r.extraDataFormat), + String(r.extraDataHash), + String(r.extraDataItemsCount), ] } @@ -34,6 +35,39 @@ function calcReportDataHash(reportItems) { return web3.utils.keccak256(data) } +const DEFAULT_REPORT_FIELDS = { + consensusVersion: 1, + refSlot: 0, + numValidators: 0, + clBalanceGwei: 0, + stakingModuleIdsWithNewlyExitedValidators: [], + numExitedValidatorsByStakingModule: [], + withdrawalVaultBalance: 0, + elRewardsVaultBalance: 0, + sharesRequestedToBurn: 0, + lastFinalizableWithdrawalRequestId: 0, + simulatedShareRate: 0, + isBunkerMode: false, + extraDataFormat: 0, + extraDataHash: ZERO_BYTES32, + extraDataItemsCount: 0, +} + +const E9 = toBN(10).pow(toBN(9)) + +async function prepareOracleReport({ clBalance, ...restFields }) { + const fields = { + ...DEFAULT_REPORT_FIELDS, + ...restFields, + clBalanceGwei: toBN(clBalance).div(E9), + } + + const items = getReportDataItems(fields) + const hash = calcReportDataHash(items) + + return { fields, items, hash } +} + async function triggerConsensusOnHash(hash, consensus) { const members = await consensus.getMembers() const { refSlot } = await consensus.getCurrentFrame() @@ -42,38 +76,48 @@ async function triggerConsensusOnHash(hash, consensus) { assert.equal((await consensus.getConsensusState()).consensusReport, hash) } -async function pushOracleReport(consensus, oracle, numValidators, clBalance, elRewards) { +async function reportOracle(consensus, oracle, reportFields) { const { refSlot } = await consensus.getCurrentFrame() - const reportFields = { - consensusVersion: 1, - refSlot, - numValidators, - clBalanceGwei: clBalance / 1e9, - stakingModuleIdsWithNewlyExitedValidators: [], - numExitedValidatorsByStakingModule: [], - withdrawalVaultBalance: 0, - elRewardsVaultBalance: elRewards || 0, - requestedToBurnShares: 0, - lastWithdrawalRequestIdToFinalize: 0, - finalizationShareRate: 0, - isBunkerMode: false, - extraDataFormat: 0, - extraDataHash: ZERO_BYTES32, - extraDataItemsCount: 0, - } - const reportItems = getReportDataItems(reportFields) - const reportHash = calcReportDataHash(reportItems) + const report = await prepareOracleReport({ ...reportFields, refSlot }) - const members = await consensus.getMembers() + // non-empty extra data is not supported here yet + assert.equals(report.fields.extraDataFormat, 0) + assert.equals(report.fields.extraDataHash, ZERO_BYTES32) + assert.equals(report.fields.extraDataItemsCount, 0) - await triggerConsensusOnHash(reportHash, consensus) + const members = await consensus.getMembers() + await triggerConsensusOnHash(report.hash, consensus) const oracleVersion = await oracle.getContractVersion() - - const submitDataTx = await oracle.submitReportData(reportItems, oracleVersion, { from: members.addresses[0] }) + const submitDataTx = await oracle.submitReportData(report.items, oracleVersion, { from: members.addresses[0] }) const submitExtraDataTx = await oracle.submitReportExtraDataEmpty({ from: members.addresses[0] }) - return { submitDataTx, submitExtraDataTx } + return { report, submitDataTx, submitExtraDataTx } } -module.exports = { getReportDataItems, calcReportDataHash, pushOracleReport } +// FIXME: kept for compat, remove after refactoring tests +function pushOracleReport(consensus, oracle, numValidators, clBalance, elRewards) { + return reportOracle(consensus, oracle, { numValidators, clBalance, elRewards }) +} + +async function getSecondsPerFrame(consensus) { + const [chainConfig, frameConfig] = await Promise.all([consensus.getChainConfig(), consensus.getFrameConfig()]) + return +chainConfig.secondsPerSlot * +chainConfig.slotsPerEpoch * +frameConfig.epochsPerFrame +} + +async function getSlotTimestamp(slot, consensus) { + const chainConfig = await consensus.getChainConfig() + return +chainConfig.genesisTime + +chainConfig.secondsPerSlot * slot +} + +module.exports = { + DEFAULT_REPORT_FIELDS, + getReportDataItems, + calcReportDataHash, + prepareOracleReport, + triggerConsensusOnHash, + reportOracle, + pushOracleReport, + getSecondsPerFrame, + getSlotTimestamp, +} diff --git a/test/helpers/reportData.js b/test/helpers/reportData.js index 963656bca..dae8f47bf 100644 --- a/test/helpers/reportData.js +++ b/test/helpers/reportData.js @@ -20,21 +20,21 @@ function calcAccountingReportDataHash(reportItems) { } function getAccountingReportDataItems(r) { return [ - r.consensusVersion, - +r.refSlot, - r.numValidators, - r.clBalanceGwei, - r.stakingModuleIdsWithNewlyExitedValidators, - r.numExitedValidatorsByStakingModule, - r.withdrawalVaultBalance, - r.elRewardsVaultBalance, - r.sharesRequestedToBurn, - r.lastFinalizableWithdrawalRequestId, - r.simulatedShareRate, + String(r.consensusVersion), + String(r.refSlot), + String(r.numValidators), + String(r.clBalanceGwei), + r.stakingModuleIdsWithNewlyExitedValidators.map(String), + r.numExitedValidatorsByStakingModule.map(String), + String(r.withdrawalVaultBalance), + String(r.elRewardsVaultBalance), + String(r.sharesRequestedToBurn), + String(r.lastFinalizableWithdrawalRequestId), + String(r.simulatedShareRate), r.isBunkerMode, - r.extraDataFormat, - r.extraDataHash, - r.extraDataItemsCount, + String(r.extraDataFormat), + String(r.extraDataHash), + String(r.extraDataItemsCount), ] } diff --git a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js new file mode 100644 index 000000000..7efdd24e1 --- /dev/null +++ b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js @@ -0,0 +1,223 @@ +const { contract, artifacts } = require('hardhat') +const { BN } = require('bn.js') +const { assert } = require('../helpers/assert') +const { ZERO_ADDRESS } = require('../helpers/constants') +const { toBN, e9, e18, e27 } = require('../helpers/utils') +const { deployProtocol } = require('../helpers/protocol') +const { reportOracle, getSecondsPerFrame, getSlotTimestamp } = require('../helpers/oracle') +const { advanceChainTime } = require('../helpers/blockchain') +// const { processNamedTuple } = require('../helpers/debug') + +const StakingModuleMock = artifacts.require('StakingModuleMock') + +function piecewiseModN({ values, pointsPerValue, x }) { + const iValue = Math.floor(x / pointsPerValue) + const leftValue = values[iValue % values.length] + const rightValue = values[(iValue + 1) % values.length] + return leftValue + ((rightValue - leftValue) * (x % pointsPerValue)) / pointsPerValue +} + +contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, user, user2]) => { + const test = (numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema) => { + let lido, router, wQueue, oracle, consensus, voting, stakingModule, stakingModuleId + let secondsPerFrame + + before('deploy contracts', async () => { + const deployed = await deployProtocol({ + stakingModulesFactory: async () => { + stakingModule = await StakingModuleMock.new() + return [ + { + module: stakingModule, + name: 'module1', + targetShares: 10000, + moduleFee: 500, + treasuryFee: 500, + }, + ] + }, + depositSecurityModuleFactory: async () => { + return { address: depositor } + }, + }) + + lido = deployed.pool + router = deployed.stakingRouter + wQueue = deployed.withdrawalQueue + oracle = deployed.oracle + consensus = deployed.consensusContract + voting = deployed.voting.address + + secondsPerFrame = await getSecondsPerFrame(consensus) + stakingModuleId = +(await router.getStakingModuleIds())[0] + + const withdrawalCredentials = '0x'.padEnd(66, '1234') + await router.setWithdrawalCredentials(withdrawalCredentials, { from: voting }) + + await deployed.oracleReportSanityChecker.setAnnualBalanceIncreaseBPLimit(10000, { from: voting }) + + await wQueue.resume({ from: deployed.appManager.address }) + }) + + const advanceTimeToNextFrame = async () => { + await advanceChainTime(secondsPerFrame) + } + + const calcCLBalanceIncreaseForShareRateBP = async (shareRateBP) => { + const totalShares = await lido.getTotalShares() + const newTotalEth = toBN(shareRateBP).mul(toBN(totalShares)).divn(10000) + return newTotalEth.sub(toBN(await lido.getTotalPooledEther())) + } + + const rebaseToShareRateBP = async (shareRateBP) => { + const stat = await lido.getBeaconStat() + const ethDiff = await calcCLBalanceIncreaseForShareRateBP(shareRateBP) + const newCLBalance = toBN(stat.beaconBalance).add(ethDiff) + + await advanceTimeToNextFrame() + + const { submitDataTx } = await reportOracle(consensus, oracle, { + numValidators: stat.beaconValidators, + clBalance: newCLBalance, + }) + + return submitDataTx + } + + let userBalance + + it(`a user submits ETH to the protocol`, async () => { + const ethToSubmit = toBN(e18(320)).sub(await lido.getTotalPooledEther()) + await lido.submit(ZERO_ADDRESS, { from: user, value: ethToSubmit }) + + userBalance = await lido.balanceOf(user) + await lido.approve(wQueue.address, userBalance, { from: user }) + }) + + it(`ether gets deposited to the CL`, async () => { + await stakingModule.setAvailableKeysCount(10) + await lido.deposit(10, stakingModuleId, '0x0', { from: depositor }) + assert.equals(await lido.getBufferedEther(), 0) + + let stat = await lido.getBeaconStat() + assert.equals(stat.depositedValidators, 10) + + const clBalance = toBN(stat.depositedValidators).mul(toBN(e18(32))) + + await advanceTimeToNextFrame() + + await reportOracle(consensus, oracle, { + numValidators: stat.depositedValidators, + clBalance, + }) + + stat = await lido.getBeaconStat() + assert.equals(stat.beaconValidators, 10) + assert.equals(stat.beaconBalance, clBalance) + }) + + const totalRequests = numRebases * withdrawalRequestsPerRebase + const shareRatesBP = [10010, 10020] + let shareRateBP + + for (let i = 0; i < numRebases; ++i) { + shareRateBP = Math.floor( + piecewiseModN({ + values: shareRatesBP, + pointsPerValue: rebasesPerShareRateExtrema, + x: i, + }) + ) + + context(`rebase ${i}, share rate: ${shareRateBP / 10000}`, () => { + before(async () => { + await rebaseToShareRateBP(shareRateBP) + assert.equals(await lido.getPooledEthByShares(10000), shareRateBP) + }) + + it(`adding ${withdrawalRequestsPerRebase} requests`, async () => { + const requestSize = toBN(userBalance).divn(totalRequests) + const amounts = new Array(withdrawalRequestsPerRebase).fill(requestSize) + await wQueue.requestWithdrawals(amounts, user, { from: user }) + }) + + if (i === numRebases - 1) { + it(`users submit enough ETH to buffer to fullfill all withdrawals`, async () => { + // twice as much ETH will be enough in all scenarios + await lido.submit(ZERO_ADDRESS, { from: user2, value: toBN(userBalance).muln(2) }) + }) + } + }) + } + + const finalShareRateBP = Math.floor((shareRatesBP[0] + shareRatesBP[1]) / 2) + const finalShareRate27 = e27(finalShareRateBP / 10000) + + context(`share rate: ${finalShareRateBP / 10000}`, () => { + let oracleReportFields, ethAvailForWithdrawals + + it(`calculating available ETH`, async () => { + const { refSlot } = await consensus.getCurrentFrame() + + const stat = await lido.getBeaconStat() + const ethDiff = await calcCLBalanceIncreaseForShareRateBP(finalShareRateBP) + const newCLBalance = toBN(stat.beaconBalance).add(ethDiff) + + oracleReportFields = { + refSlot, + numValidators: stat.beaconValidators, + clBalance: newCLBalance, + withdrawalVaultBalance: 0, + elRewardsVaultBalance: 0, + sharesRequestedToBurn: 0, + lastFinalizableRequestId: 0, + } + + const timestamp = await getSlotTimestamp(+refSlot, consensus) + const secondsElapsed = secondsPerFrame + + const [totalEth, totalShares, withdrawals, elRewards] = await lido.handleOracleReport.call( + timestamp, + secondsElapsed, + oracleReportFields.numValidators, + oracleReportFields.clBalance, + oracleReportFields.withdrawalVaultBalance, + oracleReportFields.elRewardsVaultBalance, + oracleReportFields.sharesRequestedToBurn, + 0, // lastFinalizableRequestId + 0, // simulatedShareRate + { from: oracle.address } + ) + + assert.equals(withdrawals, 0) + assert.equals(elRewards, 0) + + const shareRateE27 = toBN(e27(totalEth)).div(toBN(totalShares)) + const oneWeiE27 = e9(1) + + assert.isClose(shareRateE27, finalShareRate27, oneWeiE27) + + const unfinalizedStETH = await wQueue.unfinalizedStETH() + const bufferedEth = await lido.getBufferedEther() + + ethAvailForWithdrawals = BN.min(toBN(unfinalizedStETH), toBN(bufferedEth)) + .add(toBN(withdrawals)) + .add(toBN(elRewards)) + + console.log(`ethAvailForWithdrawals: ${ethAvailForWithdrawals.div(toBN(10).pow(toBN(18)))}`) + }) + + it.skip('TODO: oracle report') + }) + } + + context('handleOracleReport gas consumption', () => { + const testWithParams = (numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema) => { + const desc = + `rebases: ${numRebases}, requests per rebase: ${withdrawalRequestsPerRebase}, ` + + `rebases per extrema: ${rebasesPerShareRateExtrema}` + context(desc, () => test(numRebases, withdrawalRequestsPerRebase, rebasesPerShareRateExtrema)) + } + testWithParams(2, 1, 1) + }) +}) From b891e3255c5b93b6b9587e7f5ccd362ceeaf01c9 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Tue, 7 Mar 2023 19:38:58 +0300 Subject: [PATCH 184/236] test: more tests for withdrawal finalization --- test/0.4.24/lido-handle-oracle-report.test.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) 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 563c0d389..3f437d921 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -2113,6 +2113,15 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }), { from: oracle, gasPrice: 1 } ) + const { elBalanceUpdate } = limitRebase( + toBN(10000000), + ETH(101), + ETH(101), + ETH(0.1), + ETH(0.5 + 0.25), + sharesRequestedToBurn + ) + assert.equals(withdrawals.add(elRewards), elBalanceUpdate) // Ensuring that vaults don't hit the positive rebase limit assert.equals(await getBalance(elRewardsVault), elRewards) assert.equals(await getBalance(withdrawalVault), withdrawals) @@ -2141,6 +2150,8 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }), { from: oracle, gasPrice: 1 } ) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) + // Checking that both vaults are withdrawn assert.equals(await getBalance(elRewardsVault), toBN(0)) assert.equals(await getBalance(withdrawalVault), toBN(0)) @@ -2148,10 +2159,18 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot let { coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn() assert.isTrue(sharesRequestedToBurn.gt(coverShares.add(nonCoverShares))) assert.isTrue(coverShares.add(nonCoverShares).gt(toBN(0))) + // Check total pooled ether + const totalPooledEtherAfterFinalization = await lido.getTotalPooledEther() + // Add Bob's recently staked funds, deduct finalized with 1:1 stranger's StETH(1) + assert.equals(totalPooledEtherAfterFinalization, postTotalPooledEther.add(toBN(ETH(1.137 + 0.17 + 0.839 - 1)))) // Checking that finalization of the previously placed withdrawal request completed assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), toBN(1)) + const strangerBalanceBeforeClaim = await getBalance(stranger) await withdrawalQueue.claimWithdrawal(1, { from: stranger }) + const strangerBalanceAfterClaim = await getBalance(stranger) + // Happy-path: user receive ETH corresponding to the requested StETH amount + assert.equals(strangerBalanceAfterClaim - strangerBalanceBeforeClaim, StETH(1)) // Reporting once again allowing shares to be burnt completely await lido.handleOracleReport( @@ -2167,6 +2186,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot }), { from: oracle, gasPrice: 1 } ) + await checkStat({ depositedValidators: 3, beaconValidators: 3, beaconBalance: ETH(96.1) }) // Checking that no shares to burn remain ;({ coverShares, nonCoverShares } = await burner.getSharesRequestedToBurn()) assert.equals(coverShares, toBN(0)) From 1c0cc433c3f80daeefba01feddd01908a4b0dabc Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Tue, 7 Mar 2023 22:01:40 +0400 Subject: [PATCH 185/236] Handle reverts in reportRewardsMinted method --- contracts/0.8.9/StakingRouter.sol | 9 +++++- lib/abi/StakingRouter.json | 2 +- .../staking-router/staking-router.test.js | 29 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index dfcfa7e26..8105427d4 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -27,6 +27,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version event WithdrawalCredentialsSet(bytes32 withdrawalCredentials, address setBy); event WithdrawalsCredentialsChangeFailed(uint256 indexed stakingModuleId, bytes lowLevelRevertData); event ExitedAndStuckValidatorsCountsUpdateFailed(uint256 indexed stakingModuleId, bytes lowLevelRevertData); + event RewardsMintedReportFailed(uint256 indexed stakingModuleId, bytes lowLevelRevertData); /// Emitted when the StakingRouter received ETH event StakingRouterETHDeposited(uint256 indexed stakingModuleId, uint256 amount); @@ -268,7 +269,13 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version for (uint256 i = 0; i < _stakingModuleIds.length; ) { address moduleAddr = _getStakingModuleById(_stakingModuleIds[i]).stakingModuleAddress; - IStakingModule(moduleAddr).onRewardsMinted(_totalShares[i]); + try IStakingModule(moduleAddr).onRewardsMinted(_totalShares[i]) {} + catch (bytes memory lowLevelRevertData) { + emit RewardsMintedReportFailed( + _stakingModuleIds[i], + lowLevelRevertData + ); + } unchecked { ++i; } } } diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index 4157002c5..f3d81f580 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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"RewardsMintedReportFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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.8.9/staking-router/staking-router.test.js b/test/0.8.9/staking-router/staking-router.test.js index 7c3a99d1e..af6e90eb2 100644 --- a/test/0.8.9/staking-router/staking-router.test.js +++ b/test/0.8.9/staking-router/staking-router.test.js @@ -911,6 +911,35 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equal(+module2lastcall.callCount, 1) assert.equal(+module2lastcall.totalShares, 400) }) + + it('handles reverted staking modules correctly', async () => { + const stakingModuleWithBug = await StakingModuleStub.new() + // staking module will revert with message "UNHANDLED_ERROR" + await StakingModuleStub.stub(stakingModuleWithBug, 'onRewardsMinted', { + revert: { reason: 'UNHANDLED_ERROR' }, + }) + await router.addStakingModule('Staking Module With Bug', stakingModuleWithBug.address, 100, 1000, 2000, { + from: admin, + }) + const stakingModuleWithBugId = await router.getStakingModulesCount() + + const stakingModuleIds = [1, 2, stakingModuleWithBugId] + const totalShares = [300, 400, 500] + await router.grantRole(await router.REPORT_REWARDS_MINTED_ROLE(), admin, { from: admin }) + const tx = await router.reportRewardsMinted(stakingModuleIds, totalShares, { from: admin }) + + const errorMethodId = '0x08c379a0' + const errorMessageEncoded = [ + '0000000000000000000000000000000000000000000000000000000000000020', + '000000000000000000000000000000000000000000000000000000000000000f', + '554e48414e444c45445f4552524f520000000000000000000000000000000000', + ] + + assert.emits(tx, 'RewardsMintedReportFailed', { + stakingModuleId: stakingModuleWithBugId, + lowLevelRevertData: [errorMethodId, ...errorMessageEncoded].join(''), + }) + }) }) describe('updateRefundedValidatorsCount()', async () => { From 275fab55441b2dd2b64d8c68862c9badde4e4972 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Tue, 7 Mar 2023 22:02:45 +0400 Subject: [PATCH 186/236] Update work with state in the GenericStub --- contracts/0.8.9/test_helpers/GenericStub.sol | 109 +++++++++++++----- test/0.4.24/lido-deposit-scenarios.test.js | 50 ++++---- .../staking-router-keys-reporting.test.js | 2 +- test/helpers/stubs/generic.stub.js | 22 +++- test/helpers/stubs/staking-module.stub.js | 6 +- 5 files changed, 127 insertions(+), 62 deletions(-) diff --git a/contracts/0.8.9/test_helpers/GenericStub.sol b/contracts/0.8.9/test_helpers/GenericStub.sol index 7e854967b..2450113a8 100644 --- a/contracts/0.8.9/test_helpers/GenericStub.sol +++ b/contracts/0.8.9/test_helpers/GenericStub.sol @@ -69,31 +69,38 @@ contract GenericStub { } function GenericStub__addStub(MethodStub memory _stub) external { - StubState storage currentState = _getState(_currentStateIndexOneBased - 1); - currentState.stubs.push(); + GenericStub__addStub(_currentStateIndexOneBased - 1, _stub); + } + + function GenericStub__addStub(uint256 _stateIndex, MethodStub memory _stub) public { + StubState storage state = _getState(_stateIndex); + state.stubs.push(); bytes32 stubId = keccak256(_stub.input); - uint256 newStubIndex = currentState.stubs.length - 1; - currentState.stubs[newStubIndex].input = _stub.input; - currentState.stubs[newStubIndex].output = _stub.output; - currentState.stubs[newStubIndex].forwardETH = _stub.forwardETH; - currentState.stubs[newStubIndex].isRevert = _stub.isRevert; - currentState.stubs[newStubIndex].nextStateIndexOneBased = _stub.nextStateIndexOneBased; - - for(uint256 i = 0; i < _stub.logs.length; ++i) { - currentState.stubs[newStubIndex].logs.push(_stub.logs[i]); + uint256 newStubIndex = state.stubs.length - 1; + state.stubs[newStubIndex].input = _stub.input; + state.stubs[newStubIndex].output = _stub.output; + state.stubs[newStubIndex].forwardETH = _stub.forwardETH; + state.stubs[newStubIndex].isRevert = _stub.isRevert; + state.stubs[newStubIndex].nextStateIndexOneBased = _stub + .nextStateIndexOneBased; + + for (uint256 i = 0; i < _stub.logs.length; ++i) { + state.stubs[newStubIndex].logs.push(_stub.logs[i]); } - currentState.indicesByIdOneBased[stubId] = newStubIndex + 1; + state.indicesByIdOneBased[stubId] = newStubIndex + 1; } function GenericStub__addState() external { _states.push(); - _currentStateIndexOneBased = _states.length; } function GenericStub__setState(uint256 _stateIndex) external { require(_stateIndex != 0, "INVALID_INDEX"); if (_stateIndex > _states.length) { - revert GenericStub__StateIndexOutOfBounds(_stateIndex, _states.length); + revert GenericStub__StateIndexOutOfBounds( + _stateIndex, + _states.length + ); } _currentStateIndexOneBased = _stateIndex; } @@ -109,9 +116,20 @@ contract GenericStub { _currentStateIndexOneBased = stub.nextStateIndexOneBased; } if (stub.isRevert) { - assembly { revert(add(output, 32), outputLength) } + assembly { + revert(add(output, 32), outputLength) + } + } + // emit GenericStub__called( + // msg.sender, + // bytes4(msg.data[:4]), + // msg.data[4:], + // msg.value, + // block.number + // ); + assembly { + return(add(output, 32), outputLength) } - assembly { return(add(output, 32), outputLength) } } function _logEvents(Log[] memory _logs) internal { @@ -123,45 +141,67 @@ contract GenericStub { bytes memory data = _logs[i].data; uint256 dataLength = data.length; if (_logs[i].logType == LogType.LOG0) { - assembly { log0(add(data, 32), dataLength) } + assembly { + log0(add(data, 32), dataLength) + } } else if (_logs[i].logType == LogType.LOG1) { - assembly { log1(add(data, 32), dataLength, t1) } + assembly { + log1(add(data, 32), dataLength, t1) + } } else if (_logs[i].logType == LogType.LOG2) { - assembly { log2(add(data, 32), dataLength, t1, t2) } + assembly { + log2(add(data, 32), dataLength, t1, t2) + } } else if (_logs[i].logType == LogType.LOG3) { - assembly { log3(add(data, 32), dataLength, t1, t2, t3) } + assembly { + log3(add(data, 32), dataLength, t1, t2, t3) + } } else if (_logs[i].logType == LogType.LOG4) { - assembly { log4(add(data, 32), dataLength, t1, t2, t3, t4) } + assembly { + log4(add(data, 32), dataLength, t1, t2, t3, t4) + } } } } function _forwardETH(ForwardETH memory _ethForward) internal { if (_ethForward.value == 0) return; - new ETHForwarder{value: _ethForward.value}(_ethForward.recipient); + new ETHForwarder{ value: _ethForward.value }(_ethForward.recipient); emit GenericStub__ethSent(_ethForward.recipient, _ethForward.value); } function _getMethodStub() internal view returns (MethodStub memory) { - StubState storage currentState = _getState(_currentStateIndexOneBased - 1); + StubState storage currentState = _getState( + _currentStateIndexOneBased - 1 + ); bytes32 methodStubId = keccak256(msg.data); bytes32 methodStubWildcardId = keccak256(msg.data[:4]); - uint256 methodStubIndex = currentState.indicesByIdOneBased[methodStubId]; - uint256 methodStubWildcardIndex = currentState.indicesByIdOneBased[methodStubWildcardId]; + uint256 methodStubIndex = currentState.indicesByIdOneBased[ + methodStubId + ]; + uint256 methodStubWildcardIndex = currentState.indicesByIdOneBased[ + methodStubWildcardId + ]; if (methodStubIndex == 0 && methodStubWildcardIndex == 0) { revert GenericStub__MethodStubIsNotDefined(msg.data); } - return methodStubIndex != 0 - ? currentState.stubs[methodStubIndex - 1] - : currentState.stubs[methodStubWildcardIndex - 1]; + return + methodStubIndex != 0 + ? currentState.stubs[methodStubIndex - 1] + : currentState.stubs[methodStubWildcardIndex - 1]; } - function _getState(uint256 _stateIndex) internal view returns (StubState storage) { + function _getState( + uint256 _stateIndex + ) internal view returns (StubState storage) { if (_stateIndex >= _states.length) { - revert GenericStub__StateIndexOutOfBounds(_stateIndex, _states.length); + revert GenericStub__StateIndexOutOfBounds( + _stateIndex, + _states.length + ); } return _states[_stateIndex]; } @@ -169,6 +209,15 @@ contract GenericStub { // solhint-disable-next-line event GenericStub__ethSent(address recipient, uint256 value); + // solhint-disable-next-line + event GenericStub__called( + address caller, + bytes4 methodId, + bytes callData, + uint256 value, + uint256 blockNumber + ); + error GenericStub__StateIndexOutOfBounds(uint256 index, uint256 length); error GenericStub__MethodStubIsNotDefined(bytes callData); error GenericStub__ETHSendFailed(address recipient, uint256 value); diff --git a/test/0.4.24/lido-deposit-scenarios.test.js b/test/0.4.24/lido-deposit-scenarios.test.js index c794e56d3..3cb12ed8f 100644 --- a/test/0.4.24/lido-deposit-scenarios.test.js +++ b/test/0.4.24/lido-deposit-scenarios.test.js @@ -59,14 +59,14 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await setBalance(lido, initialLidoETHBalance + unaccountedLidoETHBalance) assert.equal(await getBalance(lido), initialLidoETHBalance + unaccountedLidoETHBalance) - const availableValidatorsCount = 2 + const depositableValidatorsCount = 2 await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { totalExitedValidators: 5, totalDepositedValidators: 16, - availableValidatorsCount, + depositableValidatorsCount, }) - const depositDataLength = availableValidatorsCount + const depositDataLength = depositableValidatorsCount await StakingModuleStub.stubObtainDepositData(stakingModuleStub, { return: { depositDataLength }, }) @@ -80,7 +80,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }) assert.equals(await getBalance(stakingRouter), initialStakingRouterBalance) - const depositedEther = wei`32 ether` * wei.min(maxDepositsCount, availableValidatorsCount) + const depositedEther = wei`32 ether` * wei.min(maxDepositsCount, depositableValidatorsCount) assert.equals( await getBalance(lido), initialLidoETHBalance + unaccountedLidoETHBalance + submitAmount - depositedEther @@ -93,14 +93,14 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await setBalance(stakingRouter, initialStakingRouterBalance) assert.equals(await getBalance(stakingRouter), initialStakingRouterBalance) - const availableValidatorsCount = 2 + const depositableValidatorsCount = 2 await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { totalExitedValidators: 5, totalDepositedValidators: 16, - availableValidatorsCount, + depositableValidatorsCount, }) - const depositDataLength = availableValidatorsCount + 2 + const depositDataLength = depositableValidatorsCount + 2 await StakingModuleStub.stubObtainDepositData(stakingModuleStub, { return: { depositDataLength }, }) @@ -116,7 +116,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await assert.reverts( lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), 'InvalidPublicKeysBatchLength', - [PUBKEY_LENGTH * depositDataLength, PUBKEY_LENGTH * availableValidatorsCount] + [PUBKEY_LENGTH * depositDataLength, PUBKEY_LENGTH * depositableValidatorsCount] ) }) @@ -125,19 +125,19 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await setBalance(stakingRouter, initialStakingRouterBalance) assert.equals(await getBalance(stakingRouter), initialStakingRouterBalance) - const availableValidatorsCount = 2 + const depositableValidatorsCount = 2 await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { totalExitedValidators: 5, totalDepositedValidators: 16, - availableValidatorsCount, + depositableValidatorsCount, }) - const depositDataLength = availableValidatorsCount + 2 + const depositDataLength = depositableValidatorsCount + 2 const depositData = new FakeValidatorKeys(depositDataLength) await StakingModuleStub.stubObtainDepositData(stakingModuleStub, { return: { publicKeysBatch: depositData.slice()[0], // two extra signatures returned - signaturesBatch: depositData.slice(0, availableValidatorsCount)[1], + signaturesBatch: depositData.slice(0, depositableValidatorsCount)[1], }, }) @@ -152,7 +152,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await assert.reverts( lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), 'InvalidPublicKeysBatchLength', - [PUBKEY_LENGTH * depositDataLength, PUBKEY_LENGTH * availableValidatorsCount] + [PUBKEY_LENGTH * depositDataLength, PUBKEY_LENGTH * depositableValidatorsCount] ) }) @@ -161,18 +161,18 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await setBalance(stakingRouter, initialStakingRouterBalance) assert.equals(await getBalance(stakingRouter), initialStakingRouterBalance) - const availableValidatorsCount = 2 + const depositableValidatorsCount = 2 await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { totalExitedValidators: 5, totalDepositedValidators: 16, - availableValidatorsCount, + depositableValidatorsCount, }) - const depositDataLength = availableValidatorsCount + 2 + const depositDataLength = depositableValidatorsCount + 2 const depositData = new FakeValidatorKeys(depositDataLength) await StakingModuleStub.stubObtainDepositData(stakingModuleStub, { return: { - publicKeysBatch: depositData.slice(0, availableValidatorsCount)[0], + publicKeysBatch: depositData.slice(0, depositableValidatorsCount)[0], signaturesBatch: depositData.slice()[1], // two extra signatures returned }, }) @@ -188,7 +188,7 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { await assert.reverts( lido.deposit(maxDepositsCount, STAKING_MODULE_ID, DEPOSIT_CALLDATA, { from: depositor }), 'InvalidSignaturesBatchLength', - [SIGNATURE_LENGTH * depositDataLength, SIGNATURE_LENGTH * availableValidatorsCount] + [SIGNATURE_LENGTH * depositDataLength, SIGNATURE_LENGTH * depositableValidatorsCount] ) }) @@ -204,14 +204,14 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { assert.equal(await getBalance(lido), initialLidoETHBalance + submitAmount) - const availableValidatorsCount = 2 + const depositableValidatorsCount = 2 await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { totalExitedValidators: 5, totalDepositedValidators: 16, - availableValidatorsCount, + depositableValidatorsCount, }) - const depositDataLength = availableValidatorsCount + const depositDataLength = depositableValidatorsCount await StakingModuleStub.stubObtainDepositData(stakingModuleStub, { return: { depositDataLength }, }) @@ -226,11 +226,11 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { assert.equal(await getBalance(lido), initialLidoETHBalance + submitAmount) - const availableValidatorsCount = 2 + const depositableValidatorsCount = 2 await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { totalExitedValidators: 5, totalDepositedValidators: 16, - availableValidatorsCount, + depositableValidatorsCount, }) await StakingModuleStub.stub(stakingModuleStub, 'obtainDepositData', { @@ -248,11 +248,11 @@ contract('Lido deposit scenarios', ([staker, depositor]) => { const submitAmount = wei`100 ether` await lido.submit(ZERO_ADDRESS, { from: staker, value: wei.str(submitAmount) }) - const availableValidatorsCount = 2 + const depositableValidatorsCount = 2 await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleStub, { totalExitedValidators: 5, totalDepositedValidators: 16, - availableValidatorsCount, + depositableValidatorsCount, }) const stakingModuleStateBefore = await stakingRouter.getStakingModule(STAKING_MODULE_ID) diff --git a/test/0.8.9/staking-router/staking-router-keys-reporting.test.js b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js index 58b155471..7f7a825f4 100644 --- a/test/0.8.9/staking-router/staking-router-keys-reporting.test.js +++ b/test/0.8.9/staking-router/staking-router-keys-reporting.test.js @@ -488,7 +488,7 @@ contract('StakingRouter', ([deployer, lido, admin, stranger]) => { await StakingModuleStub.stubGetStakingModuleSummary(stakingModuleWithBug, { totalExitedValidators: 0, totalDepositedValidators: 0, - availableValidatorsCount: 0, + depositableValidatorsCount: 0, }) await router.addStakingModule('Staking Module With Bug', stakingModuleWithBug.address, 100, 1000, 2000, { from: admin, diff --git a/test/helpers/stubs/generic.stub.js b/test/helpers/stubs/generic.stub.js index c89294cba..df48b8d40 100644 --- a/test/helpers/stubs/generic.stub.js +++ b/test/helpers/stubs/generic.stub.js @@ -38,6 +38,9 @@ class GenericStub { * @param {string} methodName name of the method to stub * * @param {object} config stubbed method params + * @param {object} state describes the state were stub declared and next transition + * @param {number} state.current index of the state where stub will be added + * @param {number} state.next index of the state which will be activated after the stub called * @param {TypedTuple} [config.input] the input value to trigger the stub * @param {TypedTuple} [config.return] the output value to return or revert from stub * @param {object} [config.revert] the revert info when stub must finish with error @@ -47,7 +50,6 @@ class GenericStub { * @param {object} [config.forwardETH] amount and recipient where to send ETH * @param {string} config.forwardETH.recipient recipient address of the ETH * @param {object} config.forwardETH.value amount of ETH to send - * @param {number} [config.nextState] one based state index to set after stub call * @param {object[]} [config.emit] events to emit when stub called * @param {string} config.emit.name name of the event to emit * @param {object} [config.emit.args] arguments of the event @@ -67,8 +69,13 @@ class GenericStub { const [methodAbi] = methodAbis const configParser = new GenericStubConfigParser() - const parsedConfig = configParser.parse(methodAbi.signature, config) - await stubInstance.GenericStub__addStub(Object.values(parsedConfig)) + const { currentState, ...parsedConfig } = configParser.parse(methodAbi.signature, config) + + if (currentState === undefined) { + await stubInstance.GenericStub__addStub(Object.values(parsedConfig)) + } else { + await stubInstance.GenericStub__addStub(currentState, Object.values(parsedConfig)) + } } } @@ -84,6 +91,7 @@ class GenericStubConfigParser { logs: this._parseLogs(config), forwardETH: this._parseForwardETH(config), isRevert: this._parseIsRevert(config), + currentState: this._parseCurrentState(config), nextState: this._parseNextState(config), } } @@ -152,7 +160,13 @@ class GenericStubConfigParser { } _parseNextState(config) { - return config.nextState || 0 + if (!config.state || !config.state.next) return 0 + return config.state.next + 1 + } + + _parseCurrentState(config) { + if (!config.state || !config.state.current) return undefined + return config.state.current } _encode({ type, value }) { diff --git a/test/helpers/stubs/staking-module.stub.js b/test/helpers/stubs/staking-module.stub.js index e333f50b5..994a33d10 100644 --- a/test/helpers/stubs/staking-module.stub.js +++ b/test/helpers/stubs/staking-module.stub.js @@ -8,13 +8,15 @@ class StakingModuleStub extends GenericStub { static async stubGetStakingModuleSummary( stakingModuleStub, - { totalExitedValidators, totalDepositedValidators, availableValidatorsCount } + { totalExitedValidators, totalDepositedValidators, depositableValidatorsCount }, + configOverrides = {} ) { await GenericStub.stub(stakingModuleStub, 'getStakingModuleSummary', { return: { type: ['uint256', 'uint256', 'uint256'], - value: [totalExitedValidators, totalDepositedValidators, availableValidatorsCount], + value: [totalExitedValidators, totalDepositedValidators, depositableValidatorsCount], }, + ...configOverrides, }) } From 4cbb8fb6c67f2d42aa86f5deb5125ca1f672929c Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Tue, 7 Mar 2023 22:20:50 +0400 Subject: [PATCH 187/236] Use _getStakingModuleById() in updateStakingModule() method --- contracts/0.8.9/StakingRouter.sol | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 8105427d4..3e996267e 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -233,8 +233,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version 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); + StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); stakingModule.targetShare = uint16(_targetShare); stakingModule.treasuryFee = uint16(_treasuryFee); @@ -1168,11 +1167,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version return _getStakingModuleById(_stakingModuleId).stakingModuleAddress; } - function _getStakingModuleAddressByIndex(uint256 _stakingModuleIndex) internal view returns (address) { - return _getStakingModuleByIndex(_stakingModuleIndex).stakingModuleAddress; - } - - function _getStorageStakingModulesMapping() internal pure returns (mapping(uint256 => StakingModule) storage result) { bytes32 position = STAKING_MODULES_MAPPING_POSITION; assembly { From 04f8c1a22b62d78bdb679a96f4e7cdf1565f66dc Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 00:42:36 +0400 Subject: [PATCH 188/236] Add updateTargetValidatorsLimits to the StakingRouter --- contracts/0.8.9/StakingRouter.sol | 16 +++++ contracts/0.8.9/interfaces/IStakingModule.sol | 10 +++ contracts/0.8.9/test_helpers/ModuleSolo.sol | 6 ++ .../0.8.9/test_helpers/StakingModuleMock.sol | 20 ++++++ lib/abi/StakingRouter.json | 2 +- .../staking-router/staking-router.test.js | 68 +++++++++++++++++++ 6 files changed, 121 insertions(+), 1 deletion(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 3e996267e..c59dd3356 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -243,6 +243,22 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version emit StakingModuleFeesSet(_stakingModuleId, _stakingModuleFee, _treasuryFee, msg.sender); } + /// @notice Updates the limit of the validators that can be used for deposit + /// @param _stakingModuleId Id of the staking module + /// @param _nodeOperatorId Id of the node operator + /// @param _isTargetLimitActive Active flag + /// @param _targetLimit Target limit of the node operator + function updateTargetValidatorsLimits( + uint256 _stakingModuleId, + uint256 _nodeOperatorId, + bool _isTargetLimitActive, + uint64 _targetLimit + ) external onlyRole(STAKING_MODULE_MANAGE_ROLE) { + address moduleAddr = _getStakingModuleById(_stakingModuleId).stakingModuleAddress; + IStakingModule(moduleAddr) + .updateTargetValidatorsLimits(_nodeOperatorId, _isTargetLimitActive, _targetLimit); + } + /// @notice Updates the number of the refunded validators in the staking module with the given /// node operator id /// @param _stakingModuleId Id of the staking module diff --git a/contracts/0.8.9/interfaces/IStakingModule.sol b/contracts/0.8.9/interfaces/IStakingModule.sol index dee857212..0697b2d04 100644 --- a/contracts/0.8.9/interfaces/IStakingModule.sol +++ b/contracts/0.8.9/interfaces/IStakingModule.sol @@ -103,6 +103,16 @@ interface IStakingModule { /// @param _refundedValidatorsCount New number of refunded validators of the node operator function updateRefundedValidatorsCount(uint256 _nodeOperatorId, uint256 _refundedValidatorsCount) external; + /// @notice Updates the limit of the validators that can be used for deposit + /// @param _nodeOperatorId Id of the node operator + /// @param _isTargetLimitActive Active flag + /// @param _targetLimit Target limit of the node operator + function updateTargetValidatorsLimits( + uint256 _nodeOperatorId, + bool _isTargetLimitActive, + uint64 _targetLimit + ) external; + /// @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 diff --git a/contracts/0.8.9/test_helpers/ModuleSolo.sol b/contracts/0.8.9/test_helpers/ModuleSolo.sol index 3ccdc1b33..0c645d6ae 100644 --- a/contracts/0.8.9/test_helpers/ModuleSolo.sol +++ b/contracts/0.8.9/test_helpers/ModuleSolo.sol @@ -90,6 +90,12 @@ contract ModuleSolo is IStakingModule { function updateRefundedValidatorsCount(uint256 _nodeOperatorId, uint256 _refundedValidatorsCount) external {} + function updateTargetValidatorsLimits( + uint256 _nodeOperatorId, + bool _isTargetLimitActive, + uint64 _targetLimit + ) external {} + function onExitedAndStuckValidatorsCountsUpdated() external {} function unsafeUpdateValidatorsCount( diff --git a/contracts/0.8.9/test_helpers/StakingModuleMock.sol b/contracts/0.8.9/test_helpers/StakingModuleMock.sol index f6de118c3..0e54f715f 100644 --- a/contracts/0.8.9/test_helpers/StakingModuleMock.sol +++ b/contracts/0.8.9/test_helpers/StakingModuleMock.sol @@ -162,6 +162,26 @@ contract StakingModuleMock is IStakingModule { ++lastCall_updateRefundedValidatorsCount.callCount; } + // solhint-disable-next-line + struct Call_updateTargetValidatorsLimits { + uint256 nodeOperatorId; + bool isTargetLimitActive; + uint64 targetLimit; + uint256 callCount; + } + + Call_updateTargetValidatorsLimits public lastCall_updateTargetValidatorsLimits; + function updateTargetValidatorsLimits( + uint256 _nodeOperatorId, + bool _isTargetLimitActive, + uint64 _targetLimit + ) external { + lastCall_updateTargetValidatorsLimits.nodeOperatorId = _nodeOperatorId; + lastCall_updateTargetValidatorsLimits.isTargetLimitActive = _isTargetLimitActive; + lastCall_updateTargetValidatorsLimits.targetLimit = _targetLimit; + ++lastCall_updateTargetValidatorsLimits.callCount; + } + uint256 public callCount_onExitedAndStuckValidatorsCountsUpdated; function onExitedAndStuckValidatorsCountsUpdated() external { diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index f3d81f580..27717ec33 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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"RewardsMintedReportFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"RewardsMintedReportFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_isTargetLimitActive","type":"bool"},{"internalType":"uint64","name":"_targetLimit","type":"uint64"}],"name":"updateTargetValidatorsLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/test/0.8.9/staking-router/staking-router.test.js b/test/0.8.9/staking-router/staking-router.test.js index af6e90eb2..3d0866268 100644 --- a/test/0.8.9/staking-router/staking-router.test.js +++ b/test/0.8.9/staking-router/staking-router.test.js @@ -942,6 +942,74 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { }) }) + describe('updateTargetValidatorsLimits()', () => { + before(snapshot) + after(revert) + + it('reverts if no STAKING_MODULE_MANAGE_ROLE role', async () => { + const moduleId = 1 + const nodeOperatorId = 1 + const isTargetLimitActive = true + const targetLimit = 3 + + await assert.revertsOZAccessControl( + router.updateTargetValidatorsLimits(moduleId, nodeOperatorId, isTargetLimitActive, targetLimit, { + from: stranger, + }), + stranger, + 'STAKING_MODULE_MANAGE_ROLE' + ) + }) + + it('reverts if module not register', async () => { + const moduleId = 1 + const nodeOperatorId = 1 + const isTargetLimitActive = true + const targetLimit = 3 + + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await assert.reverts( + router.updateTargetValidatorsLimits(moduleId, nodeOperatorId, isTargetLimitActive, targetLimit, { + from: admin, + }), + 'StakingModuleUnregistered()' + ) + }) + + it('update target validators limits works', async () => { + const moduleId = 1 + const nodeOperatorId = 1 + const isTargetLimitActive = true + const targetLimit = 3 + + await router.grantRole(await router.STAKING_MODULE_MANAGE_ROLE(), admin, { from: admin }) + await router.addStakingModule( + 'module 1', + module1.address, + 10_000, // 100 % _targetShare + 1_000, // 10 % _moduleFee + 5_000, // 50 % _treasuryFee + { from: admin } + ) + + let lastCall = await module1.lastCall_updateTargetValidatorsLimits() + assert.equals(lastCall.nodeOperatorId, 0) + assert.equals(lastCall.isTargetLimitActive, false) + assert.equals(lastCall.targetLimit, 0) + assert.equals(lastCall.callCount, 0) + + await router.updateTargetValidatorsLimits(moduleId, nodeOperatorId, isTargetLimitActive, targetLimit, { + from: admin, + }) + + lastCall = await module1.lastCall_updateTargetValidatorsLimits() + assert.equals(lastCall.nodeOperatorId, 1) + assert.equals(lastCall.isTargetLimitActive, true) + assert.equals(lastCall.targetLimit, targetLimit) + assert.equals(lastCall.callCount, 1) + }) + }) + describe('updateRefundedValidatorsCount()', async () => { before(snapshot) after(revert) From 610c8715695d557979e17844bd09d18d86b5063a Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 01:12:41 +0400 Subject: [PATCH 189/236] Use uint256 type for _targetLimit argument --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 5 +++-- contracts/0.8.9/StakingRouter.sol | 2 +- contracts/0.8.9/interfaces/IStakingModule.sol | 2 +- contracts/0.8.9/test_helpers/ModuleSolo.sol | 2 +- contracts/0.8.9/test_helpers/StakingModuleMock.sol | 4 ++-- lib/abi/NodeOperatorsRegistry.json | 2 +- lib/abi/StakingRouter.json | 2 +- test/0.4.24/node-operators-registry.test.js | 13 +++++++++++-- 8 files changed, 21 insertions(+), 11 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index d1dbbae24..18b4be817 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -590,13 +590,14 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @param _nodeOperatorId Id 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 { + function updateTargetValidatorsLimits(uint256 _nodeOperatorId, bool _isTargetLimitActive, uint256 _targetLimit) external { _onlyExistedNodeOperator(_nodeOperatorId); _auth(MANAGE_NODE_OPERATOR_ROLE); + _requireValidRange(_targetLimit <= UINT64_MAX); Packed64x4.Packed memory operatorTargetStats = _loadOperatorTargetValidatorsStats(_nodeOperatorId); operatorTargetStats.set(IS_TARGET_LIMIT_ACTIVE_OFFSET, _isTargetLimitActive ? 1 : 0); - operatorTargetStats.set(TARGET_VALIDATORS_COUNT_OFFSET, _isTargetLimitActive ? _targetLimit : 0); + operatorTargetStats.set(TARGET_VALIDATORS_COUNT_OFFSET, _isTargetLimitActive ? uint64(_targetLimit) : 0); _saveOperatorTargetValidatorsStats(_nodeOperatorId, operatorTargetStats); emit TargetValidatorsCountChanged(_nodeOperatorId, _targetLimit); diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index c59dd3356..7ec502e88 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -252,7 +252,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version uint256 _stakingModuleId, uint256 _nodeOperatorId, bool _isTargetLimitActive, - uint64 _targetLimit + uint256 _targetLimit ) external onlyRole(STAKING_MODULE_MANAGE_ROLE) { address moduleAddr = _getStakingModuleById(_stakingModuleId).stakingModuleAddress; IStakingModule(moduleAddr) diff --git a/contracts/0.8.9/interfaces/IStakingModule.sol b/contracts/0.8.9/interfaces/IStakingModule.sol index 0697b2d04..e7c878de9 100644 --- a/contracts/0.8.9/interfaces/IStakingModule.sol +++ b/contracts/0.8.9/interfaces/IStakingModule.sol @@ -110,7 +110,7 @@ interface IStakingModule { function updateTargetValidatorsLimits( uint256 _nodeOperatorId, bool _isTargetLimitActive, - uint64 _targetLimit + uint256 _targetLimit ) external; /// @notice Unsafely updates the number of validators in the EXITED/STUCK states for node operator with given id diff --git a/contracts/0.8.9/test_helpers/ModuleSolo.sol b/contracts/0.8.9/test_helpers/ModuleSolo.sol index 0c645d6ae..4bbe96f06 100644 --- a/contracts/0.8.9/test_helpers/ModuleSolo.sol +++ b/contracts/0.8.9/test_helpers/ModuleSolo.sol @@ -93,7 +93,7 @@ contract ModuleSolo is IStakingModule { function updateTargetValidatorsLimits( uint256 _nodeOperatorId, bool _isTargetLimitActive, - uint64 _targetLimit + uint256 _targetLimit ) external {} function onExitedAndStuckValidatorsCountsUpdated() external {} diff --git a/contracts/0.8.9/test_helpers/StakingModuleMock.sol b/contracts/0.8.9/test_helpers/StakingModuleMock.sol index 0e54f715f..6d7036015 100644 --- a/contracts/0.8.9/test_helpers/StakingModuleMock.sol +++ b/contracts/0.8.9/test_helpers/StakingModuleMock.sol @@ -166,7 +166,7 @@ contract StakingModuleMock is IStakingModule { struct Call_updateTargetValidatorsLimits { uint256 nodeOperatorId; bool isTargetLimitActive; - uint64 targetLimit; + uint256 targetLimit; uint256 callCount; } @@ -174,7 +174,7 @@ contract StakingModuleMock is IStakingModule { function updateTargetValidatorsLimits( uint256 _nodeOperatorId, bool _isTargetLimitActive, - uint64 _targetLimit + uint256 _targetLimit ) external { lastCall_updateTargetValidatorsLimits.nodeOperatorId = _nodeOperatorId; lastCall_updateTargetValidatorsLimits.isTargetLimitActive = _isTargetLimitActive; diff --git a/lib/abi/NodeOperatorsRegistry.json b/lib/abi/NodeOperatorsRegistry.json index 6efc49363..2b98683ac 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":"_nodeOperatorId","type":"uint256"}],"name":"clearNodeOperatorPenalty","outputs":[{"name":"","type":"bool"}],"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":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"initialize","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":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":"","type":"uint256"}],"name":"onRewardsMinted","outputs":[],"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":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_nodeOperatorIds","type":"bytes"},{"name":"_exitedValidatorsCounts","type":"bytes"}],"name":"updateExitedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorIds","type":"bytes"},{"name":"_stuckValidatorsCounts","type":"bytes"}],"name":"updateStuckValidatorsCount","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":"_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":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"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":"onExitedAndStuckValidatorsCountsUpdated","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":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"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenaltyCleared","outputs":[{"name":"","type":"bool"}],"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":"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":false,"name":"stuckPenaltyDelay","type":"uint256"}],"name":"StuckPenaltyDelayChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"},{"indexed":false,"name":"refundedValidatorsCount","type":"uint256"},{"indexed":false,"name":"stuckPenaltyEndTimestamp","type":"uint256"}],"name":"StuckPenaltyStateChanged","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":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":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":"_nodeOperatorId","type":"uint256"}],"name":"clearNodeOperatorPenalty","outputs":[{"name":"","type":"bool"}],"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":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"initialize","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":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":"","type":"uint256"}],"name":"onRewardsMinted","outputs":[],"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":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_nodeOperatorIds","type":"bytes"},{"name":"_exitedValidatorsCounts","type":"bytes"}],"name":"updateExitedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorIds","type":"bytes"},{"name":"_stuckValidatorsCounts","type":"bytes"}],"name":"updateStuckValidatorsCount","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":"_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":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint256"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"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":"onExitedAndStuckValidatorsCountsUpdated","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":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"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenaltyCleared","outputs":[{"name":"","type":"bool"}],"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":"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":false,"name":"stuckPenaltyDelay","type":"uint256"}],"name":"StuckPenaltyDelayChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"},{"indexed":false,"name":"refundedValidatorsCount","type":"uint256"},{"indexed":false,"name":"stuckPenaltyEndTimestamp","type":"uint256"}],"name":"StuckPenaltyStateChanged","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":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 diff --git a/lib/abi/StakingRouter.json b/lib/abi/StakingRouter.json index 27717ec33..4d4b74251 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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"RewardsMintedReportFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_isTargetLimitActive","type":"bool"},{"internalType":"uint64","name":"_targetLimit","type":"uint64"}],"name":"updateTargetValidatorsLimits","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":[{"internalType":"uint256","name":"firstArrayLength","type":"uint256"},{"internalType":"uint256","name":"secondArrayLength","type":"uint256"}],"name":"ArraysLengthMismatch","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":[{"internalType":"uint256","name":"etherValue","type":"uint256"},{"internalType":"uint256","name":"depositsCount","type":"uint256"}],"name":"InvalidDepositsValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPublicKeysBatchLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"code","type":"uint256"}],"name":"InvalidReportData","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidSignaturesBatchLength","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"StakingModuleAddressExists","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":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"ExitedAndStuckValidatorsCountsUpdateFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"RewardsMintedReportFailed","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"stakingModuleId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"lowLevelRevertData","type":"bytes"}],"name":"WithdrawalsCredentialsChangeFailed","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":"MAX_STAKING_MODULES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_STAKING_MODULE_NAME_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"_depositsCount","type":"uint256"},{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"bytes","name":"_depositCalldata","type":"bytes"}],"name":"deposit","outputs":[],"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":"address","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"},{"internalType":"uint256","name":"_maxDepositsValue","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":[],"name":"onValidatorsCountsByNodeOperatorReportingFinished","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.ValidatorsCountsCorrection","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"},{"inputs":[{"internalType":"uint256","name":"_stakingModuleId","type":"uint256"},{"internalType":"uint256","name":"_nodeOperatorId","type":"uint256"},{"internalType":"bool","name":"_isTargetLimitActive","type":"bool"},{"internalType":"uint256","name":"_targetLimit","type":"uint256"}],"name":"updateTargetValidatorsLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index 458d058dc..d7e6859ce 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -1448,7 +1448,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) }) - describe('updateTargetValidatorsLimit()', () => { + describe('updateTargetValidatorsLimits()', () => { const firstNodeOperatorId = 0 const secondNodeOperatorId = 1 @@ -1468,6 +1468,15 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ) }) + it('reverts with "OUT_OF_RANGE" error when called with targetLimit > UINT64_MAX', async () => { + const isTargetLimitSet = true + const targetLimit = toBN('0x10000000000000000') + await assert.reverts( + app.updateTargetValidatorsLimits(firstNodeOperatorId, isTargetLimitSet, targetLimit, { from: voting }), + 'OUT_OF_RANGE' + ) + }) + it('updates node operator target limit if called by sender with MANAGE_NODE_OPERATOR_ROLE', async () => { const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) @@ -1687,7 +1696,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob let firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) - const targetLimit = toBN('0x1FFFFFFFFFFFFFFFF') // UINT64_MAX + const targetLimit = toBN('0xFFFFFFFFFFFFFFFF') // UINT64_MAX await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, targetLimit, { from: voting }) firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) From 3d7fa1efa75e7697f29d581ba07176fd018b6aed Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 02:38:37 +0400 Subject: [PATCH 190/236] Use different addresses for different roles in nor tests --- test/0.4.24/node-operators-registry.test.js | 642 +++++++++++--------- 1 file changed, 360 insertions(+), 282 deletions(-) diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index d7e6859ce..03eff5c05 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -65,9 +65,11 @@ const PENALTY_DELAY = 2 * 24 * 60 * 60 // 2 days const StETH = artifacts.require('StETHMock') -contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nobody]) => { +contract('NodeOperatorsRegistry', (addresses) => { let appBase, app, locator, steth, dao const snapshot = new EvmSnapshot(ethers.provider) + const [admin, limitsManager, nodeOperatorsManager, signingKeysManager, stakingRouter, user1, user2, user3, nobody] = + addresses before('deploy base app', async () => { // Deploy the app's base contract. @@ -78,15 +80,15 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) locator = await LidoLocator.new(locatorConfig) - dao = await AragonDAO.create(appManager) + dao = await AragonDAO.create(admin) app = await dao.newAppInstance({ name: 'node-operators-registry', base: appBase, permissions: { - MANAGE_SIGNING_KEYS: voting, - MANAGE_NODE_OPERATOR_ROLE: voting, - SET_NODE_OPERATOR_LIMIT_ROLE: voting, - STAKING_ROUTER_ROLE: voting, + MANAGE_SIGNING_KEYS: [admin, signingKeysManager], + MANAGE_NODE_OPERATOR_ROLE: [admin, nodeOperatorsManager], + SET_NODE_OPERATOR_LIMIT_ROLE: [admin, limitsManager], + STAKING_ROUTER_ROLE: [admin, stakingRouter], }, }) @@ -361,51 +363,57 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it('reverts with error "WRONG_NAME_LENGTH" when called with empty name', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) - await assert.reverts(app.addNodeOperator('', ADDRESS_1, { from: voting }), 'WRONG_NAME_LENGTH') + await assert.reverts(app.addNodeOperator('', ADDRESS_1, { from: nodeOperatorsManager }), 'WRONG_NAME_LENGTH') }) it('reverts with error "WRONG_NAME_LENGTH" when called with name length > MAX_NODE_OPERATOR_NAME_LENGTH', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) const maxNameLength = await app.MAX_NODE_OPERATOR_NAME_LENGTH() const tooLongName = '&'.repeat(maxNameLength.toNumber() + 1) - await assert.reverts(app.addNodeOperator(tooLongName, ADDRESS_1, { from: voting }), 'WRONG_NAME_LENGTH') + await assert.reverts( + app.addNodeOperator(tooLongName, ADDRESS_1, { from: nodeOperatorsManager }), + 'WRONG_NAME_LENGTH' + ) }) it('reverts with error "ZERO_ADDRESS" when called with zero reward address', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) const name = 'Node Operator #1' - await assert.reverts(app.addNodeOperator(name, ZERO_ADDRESS, { from: voting }), 'ZERO_ADDRESS') + await assert.reverts(app.addNodeOperator(name, ZERO_ADDRESS, { from: nodeOperatorsManager }), 'ZERO_ADDRESS') }) it('reverts with error "MAX_COUNT_EXCEEDED" when total count of node operators = MAX_COUNT_EXCEEDED', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) const maxNodeOperatorsCount = await app.MAX_NODE_OPERATORS_COUNT() for (let i = 0; i < maxNodeOperatorsCount; ++i) { - await app.addNodeOperator(`Node Operator #${i}`, ADDRESS_1, { from: voting }) + await app.addNodeOperator(`Node Operator #${i}`, ADDRESS_1, { from: nodeOperatorsManager }) } assert.equals(await app.getNodeOperatorsCount(), maxNodeOperatorsCount) - await assert.reverts(app.addNodeOperator(`exceeded`, ADDRESS_2, { from: voting }), 'MAX_OPERATORS_COUNT_EXCEEDED') + await assert.reverts( + app.addNodeOperator(`exceeded`, ADDRESS_2, { from: nodeOperatorsManager }), + 'MAX_OPERATORS_COUNT_EXCEEDED' + ) }) it('creates node operator with correct state', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) const name = `Node Operator #1` - await app.addNodeOperator(name, ADDRESS_1, { from: voting }) + await app.addNodeOperator(name, ADDRESS_1, { from: nodeOperatorsManager }) const expectedNodeOperatorId = 0 @@ -421,45 +429,49 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it('returns correct node operator id', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) assert.equals(await app.getNodeOperatorsCount(), 0) const name = `Node Operator #1` - let expectedId = await app.methods['addNodeOperator(string,address)'].call(name, ADDRESS_1, { from: voting }) + let expectedId = await app.methods['addNodeOperator(string,address)'].call(name, ADDRESS_1, { + from: nodeOperatorsManager, + }) assert.equals(expectedId, 0) // create node operator to check that next id is correct - await app.addNodeOperator(name, ADDRESS_1, { from: voting }) + await app.addNodeOperator(name, ADDRESS_1, { from: nodeOperatorsManager }) - expectedId = await app.methods['addNodeOperator(string,address)'].call(name, ADDRESS_1, { from: voting }) + expectedId = await app.methods['addNodeOperator(string,address)'].call(name, ADDRESS_1, { + from: nodeOperatorsManager, + }) assert.equals(expectedId, 1) }) it('active & total operators count update correctly', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) assert.equals(await app.getNodeOperatorsCount(), 0) assert.equals(await app.getActiveNodeOperatorsCount(), 0) - await app.addNodeOperator(`Node Operator 1`, ADDRESS_1, { from: voting }) + await app.addNodeOperator(`Node Operator 1`, ADDRESS_1, { from: nodeOperatorsManager }) assert.equals(await app.getNodeOperatorsCount(), 1) assert.equals(await app.getActiveNodeOperatorsCount(), 1) }) it('emits NodeOperatorAdded events with correct params', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) assert.equals(await app.getNodeOperatorsCount(), 0) const name = `Node Operator 1` - const tx = await app.addNodeOperator(name, ADDRESS_1, { from: voting }) + const tx = await app.addNodeOperator(name, ADDRESS_1, { from: nodeOperatorsManager }) assert.emits( tx, @@ -472,9 +484,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob describe('activateNodeOperator()', () => { beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: admin }) const stakingModuleSummary = await app.getStakingModuleSummary() assert.equals(stakingModuleSummary.totalExitedValidators, 1) @@ -490,10 +502,10 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it('reverts when called with non-existent operator id', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) const nodeOperatorId = Number.MAX_SAFE_INTEGER - await assert.reverts(app.activateNodeOperator(nodeOperatorId, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts(app.activateNodeOperator(nodeOperatorId, { from: nodeOperatorsManager }), 'OUT_OF_RANGE') }) it('reverts with WRONG_OPERATOR_ACTIVE_STATE when called on active node operator', async () => { @@ -503,7 +515,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.isTrue(activeNodeOperator.active) await assert.reverts( - app.activateNodeOperator(activeNodeOperatorId, { from: voting }), + app.activateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }), 'WRONG_OPERATOR_ACTIVE_STATE' ) }) @@ -516,7 +528,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob app.getNonce(), ]) assert.isFalse(nodeOperator.active) - await app.activateNodeOperator(nodeOperatorId, { from: voting }) + await app.activateNodeOperator(nodeOperatorId, { from: nodeOperatorsManager }) const [keysOpIndexAfter, nonceAfter] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) assert.equals(keysOpIndexAfter, keysOpIndexBefore.toNumber() + 1) assert.notEquals(nonceAfter, nonceBefore) @@ -527,7 +539,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const nodeOperator = await app.getNodeOperator(nodeOperatorId, false) const keysOpIndexBefore = await app.getKeysOpIndex() assert.isFalse(nodeOperator.active) - const receipt = await app.activateNodeOperator(nodeOperatorId, { from: voting }) + const receipt = await app.activateNodeOperator(nodeOperatorId, { from: nodeOperatorsManager }) const nonceAfter = await app.getNonce() assert.emits(receipt, 'KeysOpIndexSet', { keysOpIndex: keysOpIndexBefore.toNumber() + 1 }) assert.emits(receipt, 'NonceChanged', { nonce: nonceAfter }) @@ -539,7 +551,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.isFalse(notActiveNodeOperator.active) - await app.activateNodeOperator(notActiveNodeOperatorId, { from: voting }) + await app.activateNodeOperator(notActiveNodeOperatorId, { from: nodeOperatorsManager }) const nodeOperator = await app.getNodeOperator(notActiveNodeOperatorId, false) assert.isTrue(nodeOperator.active) @@ -551,7 +563,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const activeNodeOperatorsCountBefore = await app.getActiveNodeOperatorsCount() assert.isFalse(notActiveNodeOperator.active) - await app.activateNodeOperator(notActiveNodeOperatorId, { from: voting }) + await app.activateNodeOperator(notActiveNodeOperatorId, { from: nodeOperatorsManager }) const activeNodeOperatorsCountAfter = await app.getActiveNodeOperatorsCount() assert.equals(activeNodeOperatorsCountAfter.toNumber(), activeNodeOperatorsCountBefore.toNumber() + 1) @@ -560,7 +572,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits NodeOperatorActiveSet(activate) event', async () => { const nodeOperatorId = await nodeOperators.findNodeOperatorId(app, (operator) => !operator.active) assert.notEqual(nodeOperatorId, -1, `Invariant: not active node operator not found`) - const tx = await app.activateNodeOperator(nodeOperatorId, { from: voting }) + const tx = await app.activateNodeOperator(nodeOperatorId, { from: nodeOperatorsManager }) assert.emits( tx, 'NodeOperatorActiveSet', @@ -574,7 +586,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const nodeOperatorId = nodeOperatorsBefore.findIndex((operator) => !operator.active) assert.notEqual(nodeOperatorId, -1, `Invariant: not active node operator not found`) - await app.activateNodeOperator(nodeOperatorId, { from: voting }) + await app.activateNodeOperator(nodeOperatorId, { from: nodeOperatorsManager }) const nodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) @@ -586,7 +598,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const nodeOperatorId = nodeOperatorsBefore.findIndex((operator) => !operator.active) assert.notEqual(nodeOperatorId, -1, `Invariant: not active node operator not found`) - await app.activateNodeOperator(nodeOperatorId, { from: voting }) + await app.activateNodeOperator(nodeOperatorId, { from: nodeOperatorsManager }) const nodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) @@ -602,9 +614,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob describe('deactivateNodeOperator()', async () => { beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: admin }) const stakingModuleSummary = await app.getStakingModuleSummary() assert.equals(stakingModuleSummary.totalExitedValidators, 1) @@ -623,12 +635,12 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it('reverts with "OUT_OF_RANGE" error when called with non-existent operator id', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + const hasPermission = await dao.hasPermission(nodeOperatorsManager, app, 'MANAGE_NODE_OPERATOR_ROLE') assert.isTrue(hasPermission) const nodeOperatorId = Number.MAX_SAFE_INTEGER - await assert.reverts(app.deactivateNodeOperator(nodeOperatorId, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts(app.deactivateNodeOperator(nodeOperatorId, { from: nodeOperatorsManager }), 'OUT_OF_RANGE') }) it('reverts with "WRONG_OPERATOR_ACTIVE_STATE" when called on not active node operator', async () => { @@ -639,7 +651,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.isFalse(activeNodeOperator.active) await assert.reverts( - app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }), + app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }), 'WRONG_OPERATOR_ACTIVE_STATE' ) }) @@ -648,7 +660,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const activeNodeOperatorId = await nodeOperators.findNodeOperatorId(app, (operator) => operator.active) assert.notEqual(activeNodeOperatorId, -1, `Invariant: active node operator not found`) - await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) const nodeOperator = await app.getNodeOperator(activeNodeOperatorId, false) assert.isFalse(nodeOperator.active) @@ -660,7 +672,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const activeNodeOperatorsCountBefore = await app.getActiveNodeOperatorsCount() - await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) const activeNodeOperatorsCountAfter = await app.getActiveNodeOperatorsCount() assert.equals(activeNodeOperatorsCountAfter.toNumber(), activeNodeOperatorsCountBefore.toNumber() - 1) @@ -685,7 +697,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob +operatorReportBefore.totalDepositedValidators > 0, 'Invariant Failed: vettedSigningKeysCount === 0' ) - await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) const [operatorReportAfter, allValidatorsReportAfter] = await Promise.all([ app.getNodeOperatorSummary(activeNodeOperatorId), @@ -712,7 +724,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob 'invariant failed: readyToDepositValidatorsKeysCountBefore <= depositedSigningKeysCount' ) - const receipt = await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + const receipt = await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) assert.emits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: activeNodeOperatorId, approvedValidatorsCount: usedSigningKeys, @@ -730,7 +742,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ]) assert.isTrue(nodeOperator.active, 'Invariant Failed: not active') - await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) const [operatorReportAfter, allValidatorsReportAfter] = await Promise.all([ app.getNodeOperatorSummary(activeNodeOperatorId), @@ -748,7 +760,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const activeNodeOperatorId = await nodeOperators.findNodeOperatorId(app, (operator) => operator.active) assert.notEqual(activeNodeOperatorId, -1, `Invariant: active node operator not found`) - const receipt = await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + const receipt = await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) assert.emits(receipt, 'NodeOperatorActiveSet', { nodeOperatorId: activeNodeOperatorId, active: false }) }) @@ -757,7 +769,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const activeNodeOperatorId = await nodeOperators.findNodeOperatorId(app, (operator) => operator.active) assert.notEqual(activeNodeOperatorId, -1, `Invariant: active node operator not found`) const [keysOpIndexBefore, nonceBefore] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) - await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) const [keysOpIndexAfter, nonceAfter] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) assert.equals(keysOpIndexAfter, keysOpIndexBefore.toNumber() + 1) assert.notEquals(nonceAfter, nonceBefore) @@ -767,7 +779,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const activeNodeOperatorId = await nodeOperators.findNodeOperatorId(app, (operator) => operator.active) assert.notEqual(activeNodeOperatorId, -1, `Invariant: active node operator not found`) const keysOpIndexBefore = await app.getKeysOpIndex() - const receipt = await app.deactivateNodeOperator(activeNodeOperatorId, { from: voting }) + const receipt = await app.deactivateNodeOperator(activeNodeOperatorId, { from: nodeOperatorsManager }) const nonceAfter = await app.getNonce() assert.emits(receipt, 'KeysOpIndexSet', { keysOpIndex: keysOpIndexBefore.toNumber() + 1 }) assert.emits(receipt, 'NonceChanged', { nonce: nonceAfter }) @@ -776,21 +788,24 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob describe('setNodeOperatorName()', async () => { beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: admin }) }) it('reverts with "OUT_OF_RANGE" error when called on non existent node operator', async () => { const notExitedNodeOperatorId = await app.getNodeOperatorsCount() await assert.reverts( - app.setNodeOperatorName(notExitedNodeOperatorId, 'new name', { from: voting }), + app.setNodeOperatorName(notExitedNodeOperatorId, 'new name', { from: nodeOperatorsManager }), 'OUT_OF_RANGE' ) }) it('reverts with "WRONG_NAME_LENGTH" error when called with empty name', async () => { const nodeOperatorId = 0 - await assert.reverts(app.setNodeOperatorName(nodeOperatorId, '', { from: voting }), 'WRONG_NAME_LENGTH') + await assert.reverts( + app.setNodeOperatorName(nodeOperatorId, '', { from: nodeOperatorsManager }), + 'WRONG_NAME_LENGTH' + ) }) it('reverts with "WRONG_NAME_LENGTH" error when name exceeds MAX_NODE_OPERATOR_NAME_LENGTH', async () => { @@ -798,7 +813,10 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const maxNameLength = await app.MAX_NODE_OPERATOR_NAME_LENGTH() const tooLongName = '#'.repeat(maxNameLength.toNumber() + 1) assert(tooLongName.length > maxNameLength.toNumber()) - await assert.reverts(app.setNodeOperatorName(nodeOperatorId, tooLongName, { from: voting }), 'WRONG_NAME_LENGTH') + await assert.reverts( + app.setNodeOperatorName(nodeOperatorId, tooLongName, { from: nodeOperatorsManager }), + 'WRONG_NAME_LENGTH' + ) }) it('reverts with "APP_AUTH_FAILED" error when called by address without MANAGE_NODE_OPERATOR_ROLE', async () => { @@ -810,13 +828,16 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('reverts with "VALUE_IS_THE_SAME" error when called with the same name', async () => { const nodeOperatorId = 0 const { name: currentName } = await app.getNodeOperator(nodeOperatorId, true) - await assert.reverts(app.setNodeOperatorName(nodeOperatorId, currentName, { from: voting }), 'VALUE_IS_THE_SAME') + await assert.reverts( + app.setNodeOperatorName(nodeOperatorId, currentName, { from: nodeOperatorsManager }), + 'VALUE_IS_THE_SAME' + ) }) it('updates the node operator name', async () => { const nodeOperatorId = 0 const newName = 'new name' - await app.setNodeOperatorName(nodeOperatorId, newName, { from: voting }) + await app.setNodeOperatorName(nodeOperatorId, newName, { from: nodeOperatorsManager }) const { name: nameAfter } = await app.getNodeOperator(nodeOperatorId, true) assert(nameAfter === newName) }) @@ -824,7 +845,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits NodeOperatorNameSet event with correct params', async () => { const nodeOperatorId = 0 const newName = 'new name' - const receipt = await app.setNodeOperatorName(nodeOperatorId, newName, { from: voting }) + const receipt = await app.setNodeOperatorName(nodeOperatorId, newName, { from: nodeOperatorsManager }) assert.emits( receipt, 'NodeOperatorNameSet', @@ -837,7 +858,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const anotherNodeOperatorId = 1 const newName = 'new name' const { name: anotherNodeOperatorNameBefore } = await app.getNodeOperator(anotherNodeOperatorId, true) - await app.setNodeOperatorName(nodeOperatorId, newName, { from: voting }) + await app.setNodeOperatorName(nodeOperatorId, newName, { from: nodeOperatorsManager }) const { name: anotherNodeOperatorNameAfter } = await app.getNodeOperator(anotherNodeOperatorId, true) assert.equals(anotherNodeOperatorNameBefore, anotherNodeOperatorNameAfter) }) @@ -849,20 +870,20 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const notExistedNodeOperatorId = 2 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) }) it('reverts with "OUT_OF_RANGE" error when called on non existent node operator', async () => { await assert.reverts( - app.setNodeOperatorRewardAddress(notExistedNodeOperatorId, ADDRESS_4, { from: voting }), + app.setNodeOperatorRewardAddress(notExistedNodeOperatorId, ADDRESS_4, { from: nodeOperatorsManager }), 'OUT_OF_RANGE' ) }) it('reverts with "ZERO_ADDRESS" error when new address is zero', async () => { await assert.reverts( - app.setNodeOperatorRewardAddress(firstNodeOperatorId, ZERO_ADDRESS, { from: voting }), + app.setNodeOperatorRewardAddress(firstNodeOperatorId, ZERO_ADDRESS, { from: nodeOperatorsManager }), 'ZERO_ADDRESS' ) }) @@ -879,7 +900,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it(`reverts with "VALUE_IS_THE_SAME" error when new reward address is the same`, async () => { const nodeOperator = await app.getNodeOperator(firstNodeOperatorId, false) await assert.reverts( - app.setNodeOperatorRewardAddress(firstNodeOperatorId, nodeOperator.rewardAddress, { from: voting }), + app.setNodeOperatorRewardAddress(firstNodeOperatorId, nodeOperator.rewardAddress, { + from: nodeOperatorsManager, + }), 'VALUE_IS_THE_SAME' ) }) @@ -887,13 +910,15 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('updates the reward address of the node operator', async () => { const { rewardAddress: rewardAddressBefore } = await app.getNodeOperator(firstNodeOperatorId, false) assert.notEqual(rewardAddressBefore, ADDRESS_4) - await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { from: voting }) + await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { from: nodeOperatorsManager }) const { rewardAddress: rewardAddressAfter } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(rewardAddressAfter, ADDRESS_4) }) it('emits "NodeOperatorRewardAddressSet" event with correct params', async () => { - const receipt = await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { from: voting }) + const receipt = await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { + from: nodeOperatorsManager, + }) assert.emits(receipt, 'NodeOperatorRewardAddressSet', { nodeOperatorId: firstNodeOperatorId, rewardAddress: ADDRESS_4, @@ -905,7 +930,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob secondNodeOperatorId, true ) - await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { from: voting }) + await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { from: nodeOperatorsManager }) const { rewardAddress: secondNodeOperatorRewardAddressAfter } = await app.getNodeOperator( secondNodeOperatorId, true @@ -923,12 +948,12 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await nodeOperators.addNodeOperator( app, { ...NODE_OPERATORS[0], totalSigningKeysCount: 100, vettedSigningKeysCount: 50, depositedSigningKeysCount: 20 }, - { from: voting } + { from: admin } ) await nodeOperators.addNodeOperator( app, { ...NODE_OPERATORS[1], totalSigningKeysCount: 50, vettedSigningKeysCount: 45, depositedSigningKeysCount: 30 }, - { from: voting } + { from: admin } ) }) @@ -942,39 +967,39 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it('reverts with "OUT_OF_RANGE" error when called on non existent validator', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'SET_NODE_OPERATOR_LIMIT_ROLE') + const hasPermission = await dao.hasPermission(limitsManager, app, 'SET_NODE_OPERATOR_LIMIT_ROLE') assert.isTrue(hasPermission) await assert.reverts( - app.setNodeOperatorStakingLimit(notExistedNodeOperatorId, 40, { from: voting }), + app.setNodeOperatorStakingLimit(notExistedNodeOperatorId, 40, { from: limitsManager }), 'OUT_OF_RANGE' ) }) 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') + const hasPermission = await dao.hasPermission(limitsManager, app, 'SET_NODE_OPERATOR_LIMIT_ROLE') assert.isTrue(hasPermission) - await app.deactivateNodeOperator(secondNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(secondNodeOperatorId, { from: nodeOperatorsManager }) assert.isFalse(await app.getNodeOperatorIsActive(secondNodeOperatorId)) await assert.reverts( - app.setNodeOperatorStakingLimit(secondNodeOperatorId, 40, { from: voting }), + app.setNodeOperatorStakingLimit(secondNodeOperatorId, 40, { from: limitsManager }), 'WRONG_OPERATOR_ACTIVE_STATE' ) }) it('newStakingLimit < depositedSigningKeys :: sets staking limit to deposited signing keys count', async () => { - await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 10, { from: voting }) + await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 10, { from: limitsManager }) const nodeOperator = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(nodeOperator.stakingLimit, 20) }) it('newStakingLimit > totalSigningKeysCount :: sets staking limit to total signing keys count', async () => { - await app.setNodeOperatorStakingLimit(secondNodeOperatorId, 1000, { from: voting }) + await app.setNodeOperatorStakingLimit(secondNodeOperatorId, 1000, { from: limitsManager }) const nodeOperator = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals(nodeOperator.stakingLimit, 50) }) it('depositedSigningKeys <= newStakingLimit <= totalSigningKeysCount :: sets staking limit to passed value', async () => { - await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 75, { from: voting }) + await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 75, { from: limitsManager }) const nodeOperator = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(nodeOperator.stakingLimit, 75) }) @@ -985,7 +1010,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob app.getNonce(), app.getKeysOpIndex(), ]) - const receipt = await app.setNodeOperatorStakingLimit(firstNodeOperatorId, stakingLimitBefore, { from: voting }) + const receipt = await app.setNodeOperatorStakingLimit(firstNodeOperatorId, stakingLimitBefore, { + from: limitsManager, + }) assert.notEmits(receipt, 'VettedSigningKeysCountChanged') const [{ stakingLimit: stakingLimitAfter }, nonceAfter, keysOpIndexAfter] = await Promise.all([ app.getNodeOperator(firstNodeOperatorId, false), @@ -999,21 +1026,23 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('reduces total vetted validator keys count correctly if new value less than previous', async () => { const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 30, { from: voting }) + await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 30, { from: limitsManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysCountAfter.toNumber(), 20) }) it('increases total vetted validator keys count correctly if new value greater than previous', async () => { const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 100, { from: voting }) + await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 100, { from: limitsManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter.toNumber() - vettedSigningKeysCountBefore.toNumber(), 50) }) it('emits VettedSigningKeysCountChanged event with correct params', async () => { const newStakingLimit = 75 - const receipt = await app.setNodeOperatorStakingLimit(firstNodeOperatorId, newStakingLimit, { from: voting }) + const receipt = await app.setNodeOperatorStakingLimit(firstNodeOperatorId, newStakingLimit, { + from: limitsManager, + }) assert.emits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: firstNodeOperatorId, approvedValidatorsCount: newStakingLimit, @@ -1022,7 +1051,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('increases keysOpIndex & changes nonce on vettedSigningKeysCount change', async () => { const [keysOpIndexBefore, nonceBefore] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) - await app.setNodeOperatorStakingLimit(0, 40, { from: voting }) + await app.setNodeOperatorStakingLimit(0, 40, { from: limitsManager }) const [keysOpIndexAfter, nonceAfter] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) assert.equals(keysOpIndexAfter, keysOpIndexBefore.toNumber() + 1) assert.equals(nonceAfter, nonceBefore.toNumber() + 1) @@ -1030,7 +1059,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits KeysOpIndexSet & NonceChanged on vettedSigningKeysCount change', async () => { const keysOpIndexBefore = await app.getKeysOpIndex() - const receipt = await app.setNodeOperatorStakingLimit(0, 40, { from: voting }) + const receipt = await app.setNodeOperatorStakingLimit(0, 40, { from: limitsManager }) const nonceAfter = await app.getNonce() assert.emits(receipt, 'KeysOpIndexSet', { keysOpIndex: keysOpIndexBefore.toNumber() + 1 }) assert.emits(receipt, 'NonceChanged', { nonce: nonceAfter }) @@ -1041,7 +1070,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob secondNodeOperatorId, true ) - await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { from: voting }) + await app.setNodeOperatorRewardAddress(firstNodeOperatorId, ADDRESS_4, { from: nodeOperatorsManager }) const { stakingLimit: secondNodeOperatorStakingLimitAfter } = await app.getNodeOperator( secondNodeOperatorId, true @@ -1056,15 +1085,18 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const notExistedNodeOperatorId = 2 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], exitedSigningKeysCount: 3 }, { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], exitedSigningKeysCount: 3 }, { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) }) it('reverts with "OUT_OF_RANGE" error when called on non existent validator', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'STAKING_ROUTER_ROLE') + const hasPermission = await dao.hasPermission(stakingRouter, app, 'STAKING_ROUTER_ROLE') assert.isTrue(hasPermission) const { operatorIds, keysCounts } = prepIdsCountsPayload(notExistedNodeOperatorId, 40) - await assert.reverts(app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts( + app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }), + 'OUT_OF_RANGE' + ) }) it('reverts with "APP_AUTH_FAILED" error when called by sender without STAKING_ROUTER_ROLE', async () => { @@ -1083,7 +1115,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob false ) const { operatorIds, keysCounts } = prepIdsCountsPayload(firstNodeOperatorId, exitedValidatorsKeysCountBefore) - await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }) + await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }) const { stoppedValidators: exitedValidatorsKeysCountAfter } = await app.getNodeOperator( firstNodeOperatorId, false @@ -1097,7 +1129,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob false ) const { operatorIds, keysCounts } = prepIdsCountsPayload(firstNodeOperatorId, exitedValidatorsKeysCountBefore) - const receipt = await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }) + const receipt = await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }) assert.notEmits(receipt, 'ExitedSigningKeysCountChanged') }) @@ -1106,7 +1138,10 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const nodeOperator = await app.getNodeOperator(firstNodeOperatorId, false) assert(newExitedValidatorsCount > nodeOperator.usedSigningKeys.toNumber()) const { operatorIds, keysCounts } = prepIdsCountsPayload(firstNodeOperatorId, newExitedValidatorsCount) - await assert.reverts(app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts( + app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }), + 'OUT_OF_RANGE' + ) }) it('reverts with "EXITED_VALIDATORS_COUNT_DECREASED" error when new exitedValidatorsKeysCount less then current one', async () => { @@ -1115,7 +1150,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const newExitedValidatorsKeysCount = nodeOperator.stoppedValidators.toNumber() - 1 const { operatorIds, keysCounts } = prepIdsCountsPayload(firstNodeOperatorId, newExitedValidatorsKeysCount) await assert.reverts( - app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }), + app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }), 'EXITED_VALIDATORS_COUNT_DECREASED' ) }) @@ -1128,7 +1163,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ) assert.notEquals(exitedValidatorsKeysCountBefore, newExitedValidatorsCount) const { operatorIds, keysCounts } = prepIdsCountsPayload(secondNodeOperatorId, newExitedValidatorsCount) - await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }) + await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }) const { stoppedValidators: exitedValidatorsKeysCountAfter } = await app.getNodeOperator( secondNodeOperatorId, false @@ -1146,7 +1181,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob app.testing_getTotalSigningKeysStats(), ]) const { operatorIds, keysCounts } = prepIdsCountsPayload(firstNodeOperatorId, newExitedValidatorsCount) - await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }) + await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }) const exitedSigningKeysCountIncrement = newExitedValidatorsCount - exitedValidatorsKeysCountBefore.toNumber() const { exitedSigningKeysCount: exitedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals( @@ -1158,7 +1193,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits ExitedSigningKeysCountChanged event with correct params', async () => { const newExitedValidatorsCount = 4 const { operatorIds, keysCounts } = prepIdsCountsPayload(firstNodeOperatorId, newExitedValidatorsCount) - const receipt = await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }) + const receipt = await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }) assert.emits(receipt, 'ExitedSigningKeysCountChanged', { nodeOperatorId: firstNodeOperatorId, exitedValidatorsCount: newExitedValidatorsCount, @@ -1172,7 +1207,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob true ) const { operatorIds, keysCounts } = prepIdsCountsPayload(secondNodeOperatorId, newExitedValidatorsCount) - await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }) + await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }) const { stakingLimit: secondNodeOperatorStakingLimitAfter } = await app.getNodeOperator(firstNodeOperatorId, true) assert.equals(secondNodeOperatorStakingLimitAfter, secondNodeOperatorStakingLimitBefore) }) @@ -1186,20 +1221,20 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const stuckValidatorsCount = 2 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], exitedSigningKeysCount }, { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], exitedSigningKeysCount }, { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) }) it('decreases the stuck validators count when new value is less then previous one', async () => { const newStuckValidatorsCount = 1 await app.unsafeUpdateValidatorsCount(firstNodeOperatorId, exitedSigningKeysCount, stuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const { stuckValidatorsCount: stuckValidatorsCountBefore } = await app.getNodeOperatorSummary(firstNodeOperatorId) assert(newStuckValidatorsCount < stuckValidatorsCountBefore) await app.unsafeUpdateValidatorsCount(firstNodeOperatorId, exitedSigningKeysCount, newStuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const { stuckValidatorsCount: stuckValidatorsCountAfter } = await app.getNodeOperatorSummary(firstNodeOperatorId) assert.equals(stuckValidatorsCountAfter, newStuckValidatorsCount) @@ -1212,7 +1247,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ) assert(newStuckValidatorsCount > stuckValidatorsCountBefore) await app.unsafeUpdateValidatorsCount(secondNodeOperatorId, exitedSigningKeysCount, newStuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const { stuckValidatorsCount: stuckValidatorsCountAfter } = await app.getNodeOperatorSummary(secondNodeOperatorId) assert.equals(stuckValidatorsCountAfter, newStuckValidatorsCount) @@ -1224,7 +1259,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob firstNodeOperatorId, exitedSigningKeysCount, newStuckValidatorsCount, - { from: voting } + { from: stakingRouter } ) assert.emits(receipt, 'StuckPenaltyStateChanged', { nodeOperatorId: firstNodeOperatorId, @@ -1235,7 +1270,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it("doesn't change the state when new stuck validators value is equal to the previous one", async () => { const { stuckValidatorsCount: stuckValidatorsCountBefore } = await app.getNodeOperatorSummary(firstNodeOperatorId) await app.unsafeUpdateValidatorsCount(firstNodeOperatorId, exitedSigningKeysCount, stuckValidatorsCountBefore, { - from: voting, + from: stakingRouter, }) const { stuckValidatorsCount: stuckValidatorsCountAfter } = await app.getNodeOperatorSummary(firstNodeOperatorId) @@ -1249,7 +1284,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob exitedSigningKeysCount, stuckValidatorsCountBefore, { - from: voting, + from: stakingRouter, } ) assert.notEmits(receipt, 'StuckPenaltyStateChanged') @@ -1261,7 +1296,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob firstNodeOperatorId ) await app.unsafeUpdateValidatorsCount(secondNodeOperatorId, exitedSigningKeysCount, newStuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const { stuckValidatorsCount: secondNodeOperatorStuckValidatorsCountAfter } = await app.getNodeOperatorSummary( firstNodeOperatorId @@ -1275,17 +1310,17 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert(newStuckValidatorsCount > stuckValidatorsCount) await assert.reverts( app.unsafeUpdateValidatorsCount(firstNodeOperatorId, exitedSigningKeysCount, newStuckValidatorsCount, { - from: voting, + from: stakingRouter, }), 'OUT_OF_RANGE' ) }) it('reverts with "OUT_OF_RANGE" error when called on non existent validator', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'STAKING_ROUTER_ROLE') + const hasPermission = await dao.hasPermission(stakingRouter, app, 'STAKING_ROUTER_ROLE') assert.isTrue(hasPermission) await assert.reverts( - app.unsafeUpdateValidatorsCount(notExistedNodeOperatorId, 40, stuckValidatorsCount, { from: voting }), + app.unsafeUpdateValidatorsCount(notExistedNodeOperatorId, 40, stuckValidatorsCount, { from: stakingRouter }), 'OUT_OF_RANGE' ) }) @@ -1308,7 +1343,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob firstNodeOperatorId, exitedValidatorsKeysCountBefore, stuckValidatorsCount, - { from: voting } + { from: stakingRouter } ) const { stoppedValidators: exitedValidatorsKeysCountAfter } = await app.getNodeOperator( firstNodeOperatorId, @@ -1327,7 +1362,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob exitedValidatorsKeysCountBefore, stuckValidatorsCount, { - from: voting, + from: stakingRouter, } ) assert.notEmits(receipt, 'ExitedSigningKeysCountChanged') @@ -1339,7 +1374,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert(newExitedValidatorsCount > nodeOperator.usedSigningKeys.toNumber()) await assert.reverts( app.unsafeUpdateValidatorsCount(firstNodeOperatorId, newExitedValidatorsCount, stuckValidatorsCount, { - from: voting, + from: stakingRouter, }), 'OUT_OF_RANGE' ) @@ -1354,7 +1389,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ) assert(newExitedValidatorsCount < exitedValidatorsKeysCountBefore.toNumber()) await app.unsafeUpdateValidatorsCount(firstNodeOperatorId, newExitedValidatorsCount, newStuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const { stoppedValidators: exitedValidatorsKeysCountAfter } = await app.getNodeOperator( firstNodeOperatorId, @@ -1371,7 +1406,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ) assert(newExitedValidatorsCount > exitedValidatorsKeysCountBefore.toNumber()) await app.unsafeUpdateValidatorsCount(secondNodeOperatorId, newExitedValidatorsCount, stuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const { stoppedValidators: exitedValidatorsKeysCountAfter } = await app.getNodeOperator( secondNodeOperatorId, @@ -1388,7 +1423,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ] = await Promise.all([app.getNodeOperator(firstNodeOperatorId, false), app.testing_getTotalSigningKeysStats()]) assert(newExitedValidatorsCount < exitedValidatorsKeysCountBefore.toNumber()) await app.unsafeUpdateValidatorsCount(firstNodeOperatorId, newExitedValidatorsCount, stuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const exitedSigningKeysCountIncrement = exitedValidatorsKeysCountBefore.toNumber() - newExitedValidatorsCount const { exitedSigningKeysCount: exitedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() @@ -1407,7 +1442,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob ] = await Promise.all([app.getNodeOperator(firstNodeOperatorId, false), app.testing_getTotalSigningKeysStats()]) assert(newExitedValidatorsCount > exitedValidatorsKeysCountBefore.toNumber()) await app.unsafeUpdateValidatorsCount(firstNodeOperatorId, newExitedValidatorsCount, newStuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const exitedSigningKeysCountIncrement = newExitedValidatorsCount - exitedValidatorsKeysCountBefore.toNumber() const { exitedSigningKeysCount: exitedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() @@ -1423,7 +1458,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob secondNodeOperatorId, newExitedValidatorsCount, stuckValidatorsCount, - { from: voting } + { from: stakingRouter } ) assert.emits(receipt, 'ExitedSigningKeysCountChanged', { nodeOperatorId: secondNodeOperatorId, @@ -1438,10 +1473,10 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob true ) await app.unsafeUpdateValidatorsCount(secondNodeOperatorId, newExitedValidatorsCount, stuckValidatorsCount, { - from: voting, + from: stakingRouter, }) await app.unsafeUpdateValidatorsCount(secondNodeOperatorId, newExitedValidatorsCount, stuckValidatorsCount, { - from: voting, + from: stakingRouter, }) const { stakingLimit: secondNodeOperatorStakingLimitAfter } = await app.getNodeOperator(firstNodeOperatorId, true) assert.equals(secondNodeOperatorStakingLimitAfter, secondNodeOperatorStakingLimitBefore) @@ -1453,12 +1488,12 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const secondNodeOperatorId = 1 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[firstNodeOperatorId] }, { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[secondNodeOperatorId], { from: voting }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[firstNodeOperatorId] }, { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[secondNodeOperatorId], { from: admin }) }) - it('reverts with "APP_AUTH_FAILED" error when called by sender without MANAGE_NODE_OPERATOR_ROLE', async () => { - const hasPermission = await dao.hasPermission(nobody, app, 'MANAGE_NODE_OPERATOR_ROLE') + it('reverts with "APP_AUTH_FAILED" error when called by sender without STAKING_ROUTER_ROLE', async () => { + const hasPermission = await dao.hasPermission(nobody, app, 'STAKING_ROUTER_ROLE') assert.isFalse(hasPermission) const isTargetLimitSet = false const targetLimit = 0 @@ -1472,18 +1507,20 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const isTargetLimitSet = true const targetLimit = toBN('0x10000000000000000') await assert.reverts( - app.updateTargetValidatorsLimits(firstNodeOperatorId, isTargetLimitSet, targetLimit, { from: voting }), + app.updateTargetValidatorsLimits(firstNodeOperatorId, isTargetLimitSet, targetLimit, { from: stakingRouter }), 'OUT_OF_RANGE' ) }) - it('updates node operator target limit if called by sender with MANAGE_NODE_OPERATOR_ROLE', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'MANAGE_NODE_OPERATOR_ROLE') + it('updates node operator target limit if called by sender with STAKING_ROUTER_ROLE', async () => { + const hasPermission = await dao.hasPermission(stakingRouter, app, 'STAKING_ROUTER_ROLE') assert.isTrue(hasPermission) const targetLimit = 10 const isTargetLimitSet = true - await app.updateTargetValidatorsLimits(firstNodeOperatorId, isTargetLimitSet, targetLimit, { from: voting }) + await app.updateTargetValidatorsLimits(firstNodeOperatorId, isTargetLimitSet, targetLimit, { + from: stakingRouter, + }) const keysStatTotal = await app.getStakingModuleSummary() const expectedExitedValidatorsCount = @@ -1512,8 +1549,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob describe('onWithdrawalCredentialsChanged()', () => { beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) // node operator without unused keys await nodeOperators.addNodeOperator( app, @@ -1522,19 +1559,19 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob vettedSigningKeysCount: NODE_OPERATORS[2].totalSigningKeysCount, depositedSigningKeysCount: NODE_OPERATORS[2].totalSigningKeysCount, }, - { from: voting } + { from: admin } ) }) - it('reverts with "APP_AUTH_FAILED" error when called by sender without MANAGE_NODE_OPERATOR_ROLE role', async () => { - const hasPermission = await dao.hasPermission(nobody, app, 'MANAGE_NODE_OPERATOR_ROLE') + it('reverts with "APP_AUTH_FAILED" error when called by sender without STAKING_ROUTER_ROLE role', async () => { + const hasPermission = await dao.hasPermission(nobody, app, 'STAKING_ROUTER_ROLE') assert.isFalse(hasPermission) - await assert.reverts(app.onWithdrawalCredentialsChanged(), 'APP_AUTH_FAILED') + await assert.reverts(app.onWithdrawalCredentialsChanged({ from: nobody }), 'APP_AUTH_FAILED') }) it('sets totalSigningKeysCount and vettedSigningKeysCount equal to depositedSigningKeys for all node operators', async () => { const allNodeOperatorsBefore = await nodeOperators.getAllNodeOperators(app) - await app.onWithdrawalCredentialsChanged({ from: voting }) + await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const allNodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) for (let i = 0; i < allNodeOperatorsBefore.length; ++i) { const nodeOperatorBefore = allNodeOperatorsBefore[i] @@ -1546,7 +1583,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits TotalSigningKeysCountChanged & VettedSigningKeysCountChanged events for node operator only if it had unused keys', async () => { const allNodeOperatorsBefore = await nodeOperators.getAllNodeOperators(app) - const receipt = await app.onWithdrawalCredentialsChanged({ from: voting }) + const receipt = await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const allNodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) for (let i = 0; i < allNodeOperatorsBefore.length; ++i) { const nodeOperatorBefore = allNodeOperatorsBefore[i] @@ -1569,7 +1606,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits NodeOperatorTotalKeysTrimmed event for node operator only if it had unused keys', async () => { const allNodeOperatorsBefore = await nodeOperators.getAllNodeOperators(app) - const receipt = await app.onWithdrawalCredentialsChanged({ from: voting }) + const receipt = await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const allNodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) for (let i = 0; i < allNodeOperatorsBefore.length; ++i) { const nodeOperatorBefore = allNodeOperatorsBefore[i] @@ -1596,7 +1633,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob totalSigningKeysStatsBefore.totalSigningKeysCount, totalSigningKeysStatsBefore.depositedSigningKeysCount ) - await app.onWithdrawalCredentialsChanged({ from: voting }) + await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const totalSigningKeysStatsAfter = await app.testing_getTotalSigningKeysStats() assert.equals( totalSigningKeysStatsAfter.vettedSigningKeysCount, @@ -1610,7 +1647,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('increases keysOpIndex & changes nonce', async () => { const [keysOpIndexBefore, nonceBefore] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) - await app.onWithdrawalCredentialsChanged({ from: voting }) + await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const [keysOpIndexAfter, nonceAfter] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) assert.equals(keysOpIndexAfter, keysOpIndexBefore.toNumber() + 1) assert.notEquals(nonceAfter, nonceBefore) @@ -1618,7 +1655,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits KeysOpIndexSet & NonceChanged', async () => { const keysOpIndexBefore = await app.getKeysOpIndex() - const receipt = await app.onWithdrawalCredentialsChanged({ from: voting }) + const receipt = await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const nonceAfter = await app.getNonce() assert.emits(receipt, 'KeysOpIndexSet', { keysOpIndex: keysOpIndexBefore.toNumber() + 1 }) assert.emits(receipt, 'NonceChanged', { nonce: nonceAfter }) @@ -1626,9 +1663,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it("doesn't change validators keys nonce if keys weren't invalidated", async () => { // invalidated all keys before the test to remove all unused keys of node operators - await app.onWithdrawalCredentialsChanged({ from: voting }) + await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) // the second invalidation must not invalidate keys - const receipt = await app.onWithdrawalCredentialsChanged({ from: voting }) + const receipt = await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const nonceBefore = await app.getNonce() assert.notEmits(receipt, 'NodeOperatorTotalKeysTrimmed') const nonceAfter = await app.getNonce() @@ -1640,8 +1677,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const firstNodeOperatorId = 0 const secondNodeOperatorId = 1 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], vettedSigningKeysCount: 8 }, { from: voting }) - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[1], depositedSigningKeysCount: 5 }, { from: voting }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], vettedSigningKeysCount: 8 }, { from: admin }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[1], depositedSigningKeysCount: 5 }, { from: admin }) }) it('_getCorrectedNodeOperator() - deposited < exited+target < vetted', async () => { @@ -1651,7 +1688,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.depositedSigningKeysCount, 5) assert.equals(+firstNodeOperatorKeysStats.exitedSigningKeysCount, 1) - await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, 6, { from: voting }) + await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, 6, { from: stakingRouter }) firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 7) @@ -1666,7 +1703,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.depositedSigningKeysCount, 5) assert.equals(+firstNodeOperatorKeysStats.exitedSigningKeysCount, 1) - await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, 1000, { from: voting }) + await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, 1000, { from: stakingRouter }) firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) @@ -1681,7 +1718,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.depositedSigningKeysCount, 5) assert.equals(+firstNodeOperatorKeysStats.exitedSigningKeysCount, 1) - await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, 4, { from: voting }) + await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, 4, { from: stakingRouter }) firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) assert.equals( @@ -1697,7 +1734,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) const targetLimit = toBN('0xFFFFFFFFFFFFFFFF') // UINT64_MAX - await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, targetLimit, { from: voting }) + await app.updateTargetValidatorsLimits(firstNodeOperatorId, true, targetLimit, { from: stakingRouter }) firstNodeOperatorKeysStats = await app.testing_getNodeOperator(firstNodeOperatorId) assert.equals(+firstNodeOperatorKeysStats.maxSigningKeysCount, 8) @@ -1745,8 +1782,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const firstNodeOperatorId = 0 const secondNodeOperatorId = 1 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], vettedSigningKeysCount: 8 }, { from: voting }) - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[1], depositedSigningKeysCount: 5 }, { from: voting }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], vettedSigningKeysCount: 8 }, { from: admin }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[1], depositedSigningKeysCount: 5 }, { from: admin }) }) it('returns empty result when registry has no node operators', async () => { @@ -1763,8 +1800,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('returns empty result when registry has no active node operators', async () => { // deactivate node operators before testing - await app.deactivateNodeOperator(firstNodeOperatorId, { from: voting }) - await app.deactivateNodeOperator(secondNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(firstNodeOperatorId, { from: nodeOperatorsManager }) + await app.deactivateNodeOperator(secondNodeOperatorId, { from: nodeOperatorsManager }) const [firstNodeOperator, secondNodeOperator] = await Promise.all([ app.getNodeOperator(firstNodeOperatorId, false), app.getNodeOperator(secondNodeOperatorId, false), @@ -1782,7 +1819,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('returns empty result when registry has no unused keys', async () => { // remove unused keys - await app.onWithdrawalCredentialsChanged({ from: voting }) + await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const [firstNodeOperator, secondNodeOperator] = await Promise.all([ app.getNodeOperator(firstNodeOperatorId, false), app.getNodeOperator(secondNodeOperatorId, false), @@ -1885,7 +1922,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it("doesn't allocates keys to deactivated node operators", async () => { - await app.deactivateNodeOperator(firstNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(firstNodeOperatorId, { from: nodeOperatorsManager }) const [firstNodeOperatorReport, secondNodeOperatorReport] = await Promise.all([ app.getNodeOperatorSummary(firstNodeOperatorId), @@ -1967,8 +2004,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const secondNodeOperatorId = 1 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) }) it('reverts with error "APP_AUTH_FAILED" when called by sender without STAKING_ROUTER_ROLE', async () => { @@ -1988,17 +2025,17 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('reverts with error "INVALID_ALLOCATED_KEYS_COUNT" when module has not enough keys', async () => { await app.testing_resetRegistry() - await app.addNodeOperator('fo o', ADDRESS_1, { from: voting }) - await app.addNodeOperator(' bar', ADDRESS_2, { from: voting }) + await app.addNodeOperator('fo o', ADDRESS_1, { from: nodeOperatorsManager }) + await app.addNodeOperator(' bar', ADDRESS_2, { from: nodeOperatorsManager }) const firstOperatorKeys = new signingKeys.FakeValidatorKeys(3) const secondOperatorKeys = new signingKeys.FakeValidatorKeys(3) - await app.addSigningKeys(0, 3, ...firstOperatorKeys.slice(), { from: voting }) - await app.addSigningKeys(1, 3, ...secondOperatorKeys.slice(), { from: voting }) + await app.addSigningKeys(0, 3, ...firstOperatorKeys.slice(), { from: signingKeysManager }) + await app.addSigningKeys(1, 3, ...secondOperatorKeys.slice(), { from: signingKeysManager }) - await app.setNodeOperatorStakingLimit(0, 10, { from: voting }) - await app.setNodeOperatorStakingLimit(1, 10, { from: voting }) + await app.setNodeOperatorStakingLimit(0, 10, { from: limitsManager }) + await app.setNodeOperatorStakingLimit(1, 10, { from: limitsManager }) const stakingModuleSummary = await app.getStakingModuleSummary() assert.equals(stakingModuleSummary.depositableValidatorsCount, 6) @@ -2011,17 +2048,17 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob // clear the registry to remove all unused keys with node operators await app.testing_resetRegistry() - await app.addNodeOperator('fo o', ADDRESS_1, { from: voting }) - await app.addNodeOperator(' bar', ADDRESS_2, { from: voting }) + await app.addNodeOperator('fo o', ADDRESS_1, { from: nodeOperatorsManager }) + await app.addNodeOperator(' bar', ADDRESS_2, { from: nodeOperatorsManager }) const firstOperatorKeys = new signingKeys.FakeValidatorKeys(3) const secondOperatorKeys = new signingKeys.FakeValidatorKeys(3) - await app.addSigningKeys(0, 3, ...firstOperatorKeys.slice(), { from: voting }) - await app.addSigningKeys(1, 3, ...secondOperatorKeys.slice(), { from: voting }) + await app.addSigningKeys(0, 3, ...firstOperatorKeys.slice(), { from: signingKeysManager }) + await app.addSigningKeys(1, 3, ...secondOperatorKeys.slice(), { from: signingKeysManager }) - await app.setNodeOperatorStakingLimit(0, 10, { from: voting }) - await app.setNodeOperatorStakingLimit(1, 10, { from: voting }) + await app.setNodeOperatorStakingLimit(0, 10, { from: limitsManager }) + await app.setNodeOperatorStakingLimit(1, 10, { from: limitsManager }) let stakingModuleSummary = await app.getStakingModuleSummary() assert.equals(stakingModuleSummary.depositableValidatorsCount, 6) @@ -2140,14 +2177,17 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const secondNodeOperatorId = 1 const notExistedNodeOperatorId = 2 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) }) it('reverts with "OUT_OF_RANGE" error when called on non existent validator', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'STAKING_ROUTER_ROLE') + const hasPermission = await dao.hasPermission(stakingRouter, app, 'STAKING_ROUTER_ROLE') assert.isTrue(hasPermission) - await assert.reverts(app.getNodeOperator(notExistedNodeOperatorId, false, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts( + app.getNodeOperator(notExistedNodeOperatorId, false, { from: stakingRouter }), + 'OUT_OF_RANGE' + ) }) it('returns correct node operator info', async () => { @@ -2174,9 +2214,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const secondNodeOperatorId = 1 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[2], { from: admin }) }) it('returns empty data when no node operators', async () => { @@ -2189,8 +2229,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it('returns empty data when all node operators are deactivated', async () => { - await app.deactivateNodeOperator(firstNodeOperatorId, { from: voting }) - await app.deactivateNodeOperator(secondNodeOperatorId, { from: voting }) + await app.deactivateNodeOperator(firstNodeOperatorId, { from: nodeOperatorsManager }) + await app.deactivateNodeOperator(secondNodeOperatorId, { from: nodeOperatorsManager }) const totalRewardsShare = web3.utils.toWei('10') const { recipients, shares } = await app.getRewardsDistribution(totalRewardsShare) @@ -2206,7 +2246,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob NODE_OPERATORS[secondNodeOperatorId].depositedSigningKeysCount, ] ) - await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: voting }) + await app.updateExitedValidatorsCount(operatorIds, keysCounts, { from: stakingRouter }) const activeNodeOperators = await nodeOperators.filterNodeOperators(app, (nodeOperator) => nodeOperator.active) const totalRewardsShare = web3.utils.toWei('10') const { recipients, shares } = await app.getRewardsDistribution(totalRewardsShare) @@ -2248,8 +2288,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const nonExistentNodeOperatorId = 3 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { name: '1', rewardAddress: ADDRESS_1 }, { from: voting }) - await nodeOperators.addNodeOperator(app, { name: '2', rewardAddress: ADDRESS_2 }, { from: voting }) + await nodeOperators.addNodeOperator(app, { name: '1', rewardAddress: ADDRESS_1 }, { from: admin }) + await nodeOperators.addNodeOperator(app, { name: '2', rewardAddress: ADDRESS_2 }, { from: admin }) }) it('reverts with APP_AUTH_FAILED error when called by sender without MANAGE_SIGNING_KEYS role', async () => { @@ -2266,7 +2306,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('reverts with OUT_OF_RANGE error when keys count > UINT64_MAX', async () => { const keysCount = toBN('0x10000000000000000') await assert.reverts( - app.addSigningKeys(secondNodeOperatorId, keysCount, '0x', '0x', { from: voting }), + app.addSigningKeys(secondNodeOperatorId, keysCount, '0x', '0x', { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2275,7 +2315,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = firstNodeOperatorKeys.count const [publicKeys, signatures] = firstNodeOperatorKeys.slice() await assert.reverts( - app.addSigningKeys(nonExistentNodeOperatorId, keysCount, publicKeys, signatures, { from: voting }), + app.addSigningKeys(nonExistentNodeOperatorId, keysCount, publicKeys, signatures, { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2283,7 +2323,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('reverts with "OUT_OF_RANGE" error when keys count is 0', async () => { const keysCount = 0 await assert.reverts( - app.addSigningKeys(firstNodeOperatorId, keysCount, '0x', '0x', { from: voting }), + app.addSigningKeys(firstNodeOperatorId, keysCount, '0x', '0x', { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2292,7 +2332,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = 2 const [publicKeys, signatures] = secondNodeOperatorKeys.slice(0, keysCount) await assert.reverts( - app.addSigningKeys(firstNodeOperatorId, keysCount, publicKeys + 'deadbeaf', signatures, { from: voting }), + app.addSigningKeys(firstNodeOperatorId, keysCount, publicKeys + 'deadbeaf', signatures, { + from: signingKeysManager, + }), 'LENGTH_MISMATCH' ) }) @@ -2301,7 +2343,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = 2 const [publicKeys, signatures] = secondNodeOperatorKeys.slice(0, keysCount) await assert.reverts( - app.addSigningKeys(firstNodeOperatorId, keysCount, publicKeys, signatures.slice(0, -2), { from: voting }), + app.addSigningKeys(firstNodeOperatorId, keysCount, publicKeys, signatures.slice(0, -2), { + from: signingKeysManager, + }), 'LENGTH_MISMATCH' ) }) @@ -2311,7 +2355,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const [publicKeys] = secondNodeOperatorKeys.slice(0, keysCount) const [, signatures] = secondNodeOperatorKeys.slice(0, keysCount + 1) await assert.reverts( - app.addSigningKeys(firstNodeOperatorId, keysCount, publicKeys, signatures.slice(0, -2), { from: voting }), + app.addSigningKeys(firstNodeOperatorId, keysCount, publicKeys, signatures.slice(0, -2), { + from: signingKeysManager, + }), 'LENGTH_MISMATCH' ) }) @@ -2320,7 +2366,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = 1 const [, signature] = firstNodeOperatorKeys.get(0) await assert.reverts( - app.addSigningKeys(firstNodeOperatorId, keysCount, signingKeys.EMPTY_PUBLIC_KEY, signature, { from: voting }), + app.addSigningKeys(firstNodeOperatorId, keysCount, signingKeys.EMPTY_PUBLIC_KEY, signature, { + from: signingKeysManager, + }), 'EMPTY_KEY' ) }) @@ -2328,7 +2376,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('increases node operator total signing keys counter correctly', async () => { const { totalSigningKeys: totalSigningKeysCountBefore } = await app.getNodeOperator(firstNodeOperatorId, false) await app.addSigningKeys(firstNodeOperatorId, firstNodeOperatorKeys.count, ...firstNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) const { totalSigningKeys: totalSigningKeysCountAfter } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals( @@ -2340,7 +2388,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it("doesn't modify total signing keys counter of other node operators", async () => { const { totalSigningKeys: totalSigningKeysCountBefore } = await app.getNodeOperator(secondNodeOperatorId, false) await app.addSigningKeys(firstNodeOperatorId, firstNodeOperatorKeys.count, ...firstNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) const { totalSigningKeys: totalSigningKeysCountAfter } = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals(totalSigningKeysCountBefore, totalSigningKeysCountAfter) @@ -2348,7 +2396,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('stores keys correctly for node operator without keys', async () => { await app.addSigningKeys(secondNodeOperatorId, secondNodeOperatorKeys.count, ...secondNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) for (let i = 0; i < secondNodeOperatorKeys.count; ++i) { const { key, depositSignature } = await app.getSigningKey(secondNodeOperatorId, i) @@ -2364,14 +2412,14 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob firstNodeOperatorId, initialKeysCount, ...firstNodeOperatorKeys.slice(0, initialKeysCount), - { from: voting } + { from: signingKeysManager } ) await app.addSigningKeys( firstNodeOperatorId, firstNodeOperatorKeys.count - initialKeysCount, ...firstNodeOperatorKeys.slice(2), { - from: voting, + from: signingKeysManager, } ) for (let i = initialKeysCount; i < firstNodeOperatorKeys.count; ++i) { @@ -2384,10 +2432,10 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it("doesn't modify the keys of other node operators", async () => { await app.addSigningKeys(firstNodeOperatorId, firstNodeOperatorKeys.count, ...firstNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) await app.addSigningKeys(secondNodeOperatorId, secondNodeOperatorKeys.count, ...secondNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) for (let i = 0; i < firstNodeOperatorKeys.count; ++i) { const { key, depositSignature } = await app.getSigningKey(firstNodeOperatorId, i) @@ -2399,11 +2447,11 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('increases global total signing keys counter correctly', async () => { await app.addSigningKeys(secondNodeOperatorId, secondNodeOperatorKeys.count, ...secondNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) const { totalSigningKeysCount: totalSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.addSigningKeys(firstNodeOperatorId, firstNodeOperatorKeys.count, ...firstNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) const { totalSigningKeysCount: totalSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(totalSigningKeysCountAfter, totalSigningKeysCountBefore.toNumber() + firstNodeOperatorKeys.count) @@ -2412,7 +2460,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('increases keysOpIndex & changes nonce', async () => { const [keysOpIndexBefore, nonceBefore] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) await app.addSigningKeys(firstNodeOperatorId, firstNodeOperatorKeys.count, ...firstNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, }) const [keysOpIndexAfter, nonceAfter] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) assert.equals(keysOpIndexAfter, keysOpIndexBefore.toNumber() + 1) @@ -2426,7 +2474,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob firstNodeOperatorKeys.count, ...firstNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, } ) const nonceAfter = await app.getNonce() @@ -2440,7 +2488,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob firstNodeOperatorKeys.count, ...firstNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, } ) for (let i = 0; i < firstNodeOperatorKeys.count; ++i) { @@ -2459,7 +2507,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob secondNodeOperatorKeys.count, ...secondNodeOperatorKeys.slice(), { - from: voting, + from: signingKeysManager, } ) assert.emits(receipt, 'TotalSigningKeysCountChanged', { @@ -2474,7 +2522,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const firstNodeOperatorKeys = new signingKeys.FakeValidatorKeys(1) beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { name: '1', rewardAddress: user1 }, { from: voting }) + await nodeOperators.addNodeOperator(app, { name: '1', rewardAddress: user1 }, { from: admin }) }) it('reverts with APP_AUTH_FAILED error when called not by reward address', async () => { @@ -2525,15 +2573,18 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob beforeEach(async () => { await nodeOperators - .addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) + .addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) .then((r) => (firstNodeOperatorKeys = r.validatorKeys)) await nodeOperators - .addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + .addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) .then((r) => (secondNodeOperatorKeys = r.validatorKeys)) }) it('reverts with "OUT_OF_RANGE" error when called on non existent validator', async () => { - await assert.reverts(app.removeSigningKey(nonExistentNodeOperatorId, 0, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts( + app.removeSigningKey(nonExistentNodeOperatorId, 0, { from: signingKeysManager }), + 'OUT_OF_RANGE' + ) }) it('reverts with APP_AUTH_FAILED error when called by sender without MANAGE_SIGNING_KEYS role', async () => { @@ -2545,25 +2596,34 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('reverts with OUT_OF_RANGE error when index greater than UINT64_MAX', async () => { const keyIndex = toBN('0x10000000000000000') - await assert.reverts(app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts( + app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }), + 'OUT_OF_RANGE' + ) }) it('reverts with OUT_OF_RANGE error when index is greater than total signing keys count', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - await assert.reverts(app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts( + app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }), + 'OUT_OF_RANGE' + ) }) it('reverts with OUT_OF_RANGE error when key with passed index was deposited', async () => { const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount - 1 assert(keyIndex >= 0) - await assert.reverts(app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }), 'OUT_OF_RANGE') + await assert.reverts( + app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }), + 'OUT_OF_RANGE' + ) }) it('decreases total signing keys counter for node operator', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].depositedSigningKeysCount assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) const { totalSigningKeys: totalSigningKeysBefore } = await app.getNodeOperator(secondNodeOperatorId, false) - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { totalSigningKeys: totalSigningKeysAfter } = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals(totalSigningKeysAfter.toNumber(), totalSigningKeysBefore.toNumber() - 1) }) @@ -2572,7 +2632,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].depositedSigningKeysCount + 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) const { totalSigningKeysCount: totalSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { totalSigningKeysCount: totalSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(totalSigningKeysCountAfter.toNumber(), totalSigningKeysCountBefore.toNumber() - 1) }) @@ -2581,7 +2641,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].vettedSigningKeysCount + 1 assert.isTrue(keyIndex <= NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount) const { stakingLimit: stakingLimitBefore } = await app.getNodeOperator(firstNodeOperatorId, false) - await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }) const { stakingLimit: stakingLimitAfter } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(stakingLimitBefore, stakingLimitAfter) }) @@ -2590,7 +2650,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].vettedSigningKeysCount assert.isTrue(keyIndex <= NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount) const { stakingLimit: stakingLimitBefore } = await app.getNodeOperator(firstNodeOperatorId, false) - await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }) const { stakingLimit: stakingLimitAfter } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(stakingLimitBefore, stakingLimitAfter) }) @@ -2598,7 +2658,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('sets vetted signing keys counter equal to passed key index if it less than vetted keys counter', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { stakingLimit: stakingLimitAfter } = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals(stakingLimitAfter.toNumber(), keyIndex) }) @@ -2607,7 +2667,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex assert.equals( @@ -2627,7 +2687,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob excessValidatorsCount: excessValidatorsCountBefore, } = await app.testing_getTotalTargetStats() - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex @@ -2654,7 +2714,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) @@ -2663,7 +2723,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount + 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) @@ -2671,7 +2731,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('increases keysOpIndex & changes nonce', async () => { const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount + 1 const [keysOpIndexBefore, nonceBefore] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) - await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }) const [keysOpIndexAfter, nonceAfter] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) assert.equals(keysOpIndexAfter, keysOpIndexBefore.toNumber() + 1) assert.notEquals(nonceAfter, nonceBefore) @@ -2680,7 +2740,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits KeysOpIndexSet & NonceChanged', async () => { const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount + 1 const keysOpIndexBefore = await app.getKeysOpIndex() - const receipt = await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }) + const receipt = await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }) const nonceAfter = await app.getNonce() assert.emits(receipt, 'KeysOpIndexSet', { keysOpIndex: keysOpIndexBefore.toNumber() + 1 }) assert.emits(receipt, 'NonceChanged', { nonce: nonceAfter }) @@ -2688,7 +2748,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('correctly removes the last unused signing key', async () => { const keyIndex = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - 1 - await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }) const { totalSigningKeys } = await app.getNodeOperator(firstNodeOperatorId, false) for (let i = 0; i < totalSigningKeys.toNumber(); ++i) { const { key, depositSignature } = await app.getSigningKey(firstNodeOperatorId, i) @@ -2701,7 +2761,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('correctly removes unused signing key from the middle', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 assert.notEqual(NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - 1, keyIndex) - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) for (let i = 0; i < keyIndex; ++i) { const { key, depositSignature } = await app.getSigningKey(secondNodeOperatorId, i) const [expectedPublicKey, expectedSignature] = secondNodeOperatorKeys.get(i) @@ -2729,7 +2789,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob for (let i = 0; i < unusedKeysCount; ++i) { // always remove the first signing key await app.removeSigningKey(firstNodeOperatorId, NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount, { - from: voting, + from: signingKeysManager, }) } const { totalSigningKeys, stakingLimit, usedSigningKeys } = await app.getNodeOperator(firstNodeOperatorId, false) @@ -2751,7 +2811,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob // remove all unused signing keys of first node operator for (let i = 0; i < unusedKeysCount; ++i) { await app.removeSigningKey(firstNodeOperatorId, NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount, { - from: voting, + from: signingKeysManager, }) } @@ -2766,10 +2826,12 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('after key removal new key adding works correctly', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) const { totalSigningKeys } = await app.getNodeOperator(secondNodeOperatorId, false) const keysToAdd = new signingKeys.FakeValidatorKeys(1) - await app.addSigningKeys(secondNodeOperatorId, keysToAdd.count, ...keysToAdd.slice(), { from: voting }) + await app.addSigningKeys(secondNodeOperatorId, keysToAdd.count, ...keysToAdd.slice(), { + from: signingKeysManager, + }) const { key, depositSignature } = await app.getSigningKey(secondNodeOperatorId, totalSigningKeys.toNumber()) assert.equals(key, keysToAdd.get(0)[0]) assert.equals(depositSignature, keysToAdd.get(0)[1]) @@ -2778,7 +2840,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits VettedSigningKeysCountChanged event with correct params if passed index is less then current vetted signing keys count', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - const receipt = await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + const receipt = await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) assert.emits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: secondNodeOperatorId, approvedValidatorsCount: keyIndex, @@ -2788,21 +2850,21 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it("doesn't emit VettedSigningKeysCountChanged event if passed index is equal to the current vetted signing keys count", async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - const receipt = await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + const receipt = await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) assert.notEmits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: secondNodeOperatorId }) }) it("doesn't emit VettedSigningKeysCountChanged event if passed index is greater than current vetted signing keys count", async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount + 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - const receipt = await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: voting }) + const receipt = await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) assert.notEmits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: secondNodeOperatorId }) }) it('emits TotalSigningKeysCountChanged event with correct params', async () => { const keyIndex = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - 1 assert.isTrue(keyIndex <= NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount) - const receipt = await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }) + const receipt = await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }) assert.emits( receipt, 'TotalSigningKeysCountChanged', @@ -2817,7 +2879,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('emits SigningKeyRemoved event with correct params', async () => { const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount assert.isTrue(keyIndex < NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount) - const receipt = await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: voting }) + const receipt = await app.removeSigningKey(firstNodeOperatorId, keyIndex, { from: signingKeysManager }) assert.emits( receipt, 'SigningKeyRemoved', @@ -2838,10 +2900,10 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob beforeEach(async () => { await nodeOperators - .addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) + .addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) .then((r) => (firstNodeOperatorKeys = r.validatorKeys)) await nodeOperators - .addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + .addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) .then((r) => (secondNodeOperatorKeys = r.validatorKeys)) }) @@ -2855,7 +2917,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('returns earlier if keys count is 0', async () => { const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount - await app.removeSigningKeys(firstNodeOperatorId, keyIndex, 0, { from: voting }) + await app.removeSigningKeys(firstNodeOperatorId, keyIndex, 0, { from: signingKeysManager }) const { totalSigningKeys } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(totalSigningKeys, NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount) }) @@ -2864,7 +2926,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = 0 const keysCount = 10 await assert.reverts( - app.removeSigningKeys(nonExistentNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeys(nonExistentNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2873,7 +2935,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = toBN('0x10000000000000000') const keysCount = 10 await assert.reverts( - app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2882,7 +2944,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount const keysCount = toBN('0x10000000000000000') await assert.reverts( - app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2891,7 +2953,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = toBN('0x8000000000000000') const keysCount = toBN('0x8000000000000000') await assert.reverts( - app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2901,7 +2963,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex + 1 assert(keyIndex + keysCount > NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) await assert.reverts( - app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2912,7 +2974,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = NODE_OPERATORS[firstNodeOperatorId].vettedSigningKeysCount - keyIndex assert(keysCount > 0) await assert.reverts( - app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }), 'OUT_OF_RANGE' ) }) @@ -2922,7 +2984,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) const { totalSigningKeys: totalSigningKeysBefore } = await app.getNodeOperator(secondNodeOperatorId, false) - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { totalSigningKeys: totalSigningKeysAfter } = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals(totalSigningKeysAfter.toNumber(), totalSigningKeysBefore.toNumber() - keysCount) }) @@ -2932,7 +2994,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex assert(keysCount > 0) const { totalSigningKeysCount: totalSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { totalSigningKeysCount: totalSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(totalSigningKeysCountAfter.toNumber(), totalSigningKeysCountBefore.toNumber() - keysCount) }) @@ -2942,7 +3004,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) const { stakingLimit: stakingLimitBefore } = await app.getNodeOperator(firstNodeOperatorId, false) - await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { stakingLimit: stakingLimitAfter } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(stakingLimitBefore, stakingLimitAfter) }) @@ -2951,7 +3013,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].vettedSigningKeysCount const keysCount = 1 const { stakingLimit: stakingLimitBefore } = await app.getNodeOperator(firstNodeOperatorId, false) - await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { stakingLimit: stakingLimitAfter } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(stakingLimitBefore, stakingLimitAfter) }) @@ -2960,7 +3022,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { stakingLimit: stakingLimitAfter } = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals(stakingLimitAfter.toNumber(), keyIndex) }) @@ -2969,7 +3031,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 const keysCount = 2 const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex assert.equals( @@ -2982,7 +3044,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex - 1 const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) @@ -2991,7 +3053,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount + 1 const keysCount = 1 const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) @@ -3001,7 +3063,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) const [keysOpIndexBefore, nonceBefore] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) - await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const [keysOpIndexAfter, nonceAfter] = await Promise.all([app.getKeysOpIndex(), app.getNonce()]) assert.equals(keysOpIndexAfter, keysOpIndexBefore.toNumber() + 1) assert.notEquals(nonceAfter, nonceBefore) @@ -3012,7 +3074,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keysCount = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) const keysOpIndexBefore = await app.getKeysOpIndex() - const receipt = await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }) + const receipt = await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { + from: signingKeysManager, + }) const nonceAfter = await app.getNonce() assert.emits(receipt, 'KeysOpIndexSet', { keysOpIndex: keysOpIndexBefore.toNumber() + 1 }) assert.emits(receipt, 'NonceChanged', { nonce: nonceAfter }) @@ -3022,7 +3086,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { totalSigningKeys, stakingLimit } = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals(totalSigningKeys, NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount) assert.equals(stakingLimit, NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount) @@ -3038,7 +3102,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].depositedSigningKeysCount const keysCount = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex assert(keysCount > 0) - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { totalSigningKeys, stakingLimit } = await app.getNodeOperator(secondNodeOperatorId, false) assert.equals( totalSigningKeys, @@ -3077,7 +3141,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount + 1 const keysCount = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - keyIndex - 1 assert(keysCount > 0) - await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { totalSigningKeys, stakingLimit } = await app.getNodeOperator(firstNodeOperatorId, false) assert.equals(totalSigningKeys, NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - keysCount) assert.equals(stakingLimit, keyIndex) @@ -3110,7 +3174,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount assert(unusedKeysCount > 0) - await app.removeSigningKeys(firstNodeOperatorId, keyIndex, unusedKeysCount, { from: voting }) + await app.removeSigningKeys(firstNodeOperatorId, keyIndex, unusedKeysCount, { from: signingKeysManager }) const { totalSigningKeys, stakingLimit, usedSigningKeys } = await app.getNodeOperator(firstNodeOperatorId, false) for (let i = 0; i < totalSigningKeys.toNumber(); ++i) { const { key, depositSignature } = await app.getSigningKey(firstNodeOperatorId, i) @@ -3129,7 +3193,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount assert(unusedKeysCount > 0) - await app.removeSigningKeys(firstNodeOperatorId, keyIndex, unusedKeysCount, { from: voting }) + await app.removeSigningKeys(firstNodeOperatorId, keyIndex, unusedKeysCount, { from: signingKeysManager }) for (let i = 0; i < secondNodeOperatorKeys.count; ++i) { const { key, depositSignature } = await app.getSigningKey(secondNodeOperatorId, i) @@ -3142,10 +3206,12 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob it('after keys removal new key adding works correctly', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 const keysCount = 2 - await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) const { totalSigningKeys } = await app.getNodeOperator(secondNodeOperatorId, false) const keysToAdd = new signingKeys.FakeValidatorKeys(1) - await app.addSigningKeys(secondNodeOperatorId, keysToAdd.count, ...keysToAdd.slice(), { from: voting }) + await app.addSigningKeys(secondNodeOperatorId, keysToAdd.count, ...keysToAdd.slice(), { + from: signingKeysManager, + }) const { key, depositSignature } = await app.getSigningKey(secondNodeOperatorId, totalSigningKeys.toNumber()) assert.equals(key, keysToAdd.get(0)[0]) assert.equals(depositSignature, keysToAdd.get(0)[1]) @@ -3155,7 +3221,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) - const receipt = await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + const receipt = await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { + from: signingKeysManager, + }) assert.emits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: secondNodeOperatorId, approvedValidatorsCount: keyIndex, @@ -3166,7 +3234,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount const keysCount = 3 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - const receipt = await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + const receipt = await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { + from: signingKeysManager, + }) assert.notEmits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: secondNodeOperatorId }) }) @@ -3174,7 +3244,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount + 1 const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) - const receipt = await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: voting }) + const receipt = await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { + from: signingKeysManager, + }) assert.notEmits(receipt, 'VettedSigningKeysCountChanged', { nodeOperatorId: secondNodeOperatorId }) }) @@ -3182,7 +3254,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount const keysCount = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) - const receipt = await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }) + const receipt = await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { + from: signingKeysManager, + }) assert.emits(receipt, 'TotalSigningKeysCountChanged', { nodeOperatorId: firstNodeOperatorId, totalValidatorsCount: NODE_OPERATORS[firstNodeOperatorId].depositedSigningKeysCount, @@ -3193,7 +3267,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].vettedSigningKeysCount const keysCount = NODE_OPERATORS[firstNodeOperatorId].totalSigningKeysCount - keyIndex assert(keysCount > 0) - const receipt = await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { from: voting }) + const receipt = await app.removeSigningKeys(firstNodeOperatorId, keyIndex, keysCount, { + from: signingKeysManager, + }) for (let i = keyIndex; i < keyIndex + keysCount; ++i) { assert.emits( receipt, @@ -3213,13 +3289,13 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const rewardAddress = user1 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], rewardAddress }, { from: voting }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], rewardAddress }, { from: admin }) }) it('reverts with OUT_OF_RANGE error when index greater than UINT64_MAX', async () => { const keyIndex = toBN('0x10000000000000000') await assert.reverts( - app.removeSigningKeyOperatorBH(firstNodeOperatorId, keyIndex, { from: voting }), + app.removeSigningKeyOperatorBH(firstNodeOperatorId, keyIndex, { from: rewardAddress }), 'OUT_OF_RANGE' ) }) @@ -3246,14 +3322,14 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const rewardAddress = user1 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], rewardAddress }, { from: voting }) + await nodeOperators.addNodeOperator(app, { ...NODE_OPERATORS[0], rewardAddress }, { from: admin }) }) it('reverts with OUT_OF_RANGE error when index greater than UINT64_MAX', async () => { const keyIndex = toBN('0x10000000000000000') const keysCount = 1 await assert.reverts( - app.removeSigningKeysOperatorBH(firstNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeysOperatorBH(firstNodeOperatorId, keyIndex, keysCount, { from: rewardAddress }), 'OUT_OF_RANGE' ) }) @@ -3262,7 +3338,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = NODE_OPERATORS[firstNodeOperatorId].vettedSigningKeysCount const keysCount = toBN('0x10000000000000000') await assert.reverts( - app.removeSigningKeysOperatorBH(firstNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeysOperatorBH(firstNodeOperatorId, keyIndex, keysCount, { from: rewardAddress }), 'OUT_OF_RANGE' ) }) @@ -3271,7 +3347,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const keyIndex = toBN('0x8000000000000000') const keysCount = toBN('0x8000000000000000') await assert.reverts( - app.removeSigningKeysOperatorBH(firstNodeOperatorId, keyIndex, keysCount, { from: voting }), + app.removeSigningKeysOperatorBH(firstNodeOperatorId, keyIndex, keysCount, { from: rewardAddress }), 'OUT_OF_RANGE' ) }) @@ -3315,7 +3391,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob steth.sharesOf(user3), ]) // calls distributeRewards() inside - await app.onExitedAndStuckValidatorsCountsUpdated({ from: voting }) + await app.onExitedAndStuckValidatorsCountsUpdated({ from: stakingRouter }) const recipientsSharesAfter = await Promise.all([ steth.sharesOf(user1), steth.sharesOf(user2), @@ -3332,7 +3408,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await steth.mintShares(app.address, ETH(10)) // calls distributeRewards() inside - await app.onExitedAndStuckValidatorsCountsUpdated({ from: voting }) + await app.onExitedAndStuckValidatorsCountsUpdated({ from: stakingRouter }) assert.equals(await steth.sharesOf(user1), ETH(3)) assert.equals(await steth.sharesOf(user2), ETH(7)) @@ -3344,7 +3420,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await steth.mintShares(app.address, ETH(10)) // calls distributeRewards() inside - const receipt = await app.onExitedAndStuckValidatorsCountsUpdated({ from: voting }) + const receipt = await app.onExitedAndStuckValidatorsCountsUpdated({ from: stakingRouter }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user1, sharesAmount: ETH(3) }) assert.emits(receipt, 'RewardsDistributed', { rewardAddress: user2, sharesAmount: ETH(7) }) @@ -3360,7 +3436,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob // already have three operators added for (let i = 3; i < maxNodeOperatorsCount; ++i) { - await app.testing_addNodeOperator(`Node Operator #${i}`, generateRandomAddress(), 5, 5, 5, 0, { from: voting }) + await app.testing_addNodeOperator(`Node Operator #${i}`, generateRandomAddress(), 5, 5, 5, 0, { + from: limitsManager, + }) } assert.equals(await app.getNodeOperatorsCount(), maxNodeOperatorsCount) @@ -3368,7 +3446,7 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await steth.mintShares(app.address, ETH(10)) // calls distributeRewards() inside - const tx = await app.onExitedAndStuckValidatorsCountsUpdated({ from: voting }) + const tx = await app.onExitedAndStuckValidatorsCountsUpdated({ from: stakingRouter }) // just show the used gas console.log(`gas used to distribute rewards for ${maxNodeOperatorsCount} NOs:`, +tx.receipt.gasUsed) @@ -3384,8 +3462,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const notExistedNodeOperatorId = 3 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await app.addNodeOperator('empty', ADDRESS_2, { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await app.addNodeOperator('empty', ADDRESS_2, { from: nodeOperatorsManager }) }) it('reverts with OUT_OF_RANGE error when called with not existed node operator id', async () => { @@ -3410,8 +3488,8 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob const notExistedNodeOperatorId = 3 beforeEach(async () => { - await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) - await app.addNodeOperator('empty', ADDRESS_2, { from: voting }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await app.addNodeOperator('empty', ADDRESS_2, { from: nodeOperatorsManager }) }) it('reverts with OUT_OF_RANGE error when called with not existed node operator id', async () => { @@ -3439,10 +3517,10 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob beforeEach(async () => { await nodeOperators - .addNodeOperator(app, NODE_OPERATORS[0], { from: voting }) + .addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) .then((r) => (firstNodeOperatorKeys = r.validatorKeys)) await nodeOperators - .addNodeOperator(app, NODE_OPERATORS[1], { from: voting }) + .addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) .then((r) => (secondNodeOperatorKeys = r.validatorKeys)) }) @@ -3507,18 +3585,18 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob }) it('reverts with OUT_OF_RANGE', async () => { - await app.addNodeOperator('0', user1, { from: voting }) + await app.addNodeOperator('0', user1, { from: nodeOperatorsManager }) await assert.reverts(app.getSigningKeys(0, 0, 10), 'OUT_OF_RANGE') }) it('returns specified signing keys', async () => { - await app.addNodeOperator('0', user1, { from: voting }) + await app.addNodeOperator('0', user1, { from: nodeOperatorsManager }) const keys = [pad('0xaa0101', 48), pad('0xaa0202', 48), pad('0xaa0303', 48)] const sigs = [pad('0xa1', 96), pad('0xa2', 96), pad('0xa3', 96)] - await app.addSigningKeys(0, 3, hexConcat(...keys), hexConcat(...sigs), { from: voting }) + await app.addSigningKeys(0, 3, hexConcat(...keys), hexConcat(...sigs), { from: signingKeysManager }) const { pubkeys, signatures, used } = await app.getSigningKeys(0, 1, 2) @@ -3535,9 +3613,9 @@ contract('NodeOperatorsRegistry', ([appManager, voting, user1, user2, user3, nob await assert.reverts(app.onRewardsMinted(123, { from: user1 })) }) it('no reverts with STAKING_ROUTER_ROLE', async () => { - const hasPermission = await dao.hasPermission(voting, app, 'STAKING_ROUTER_ROLE') + const hasPermission = await dao.hasPermission(stakingRouter, app, 'STAKING_ROUTER_ROLE') assert.isTrue(hasPermission) - await app.onRewardsMinted(123, { from: voting }) + await app.onRewardsMinted(123, { from: stakingRouter }) }) }) }) From a1278891ad4461b9ec6102ee1ffb6b07d051b75f Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 02:41:01 +0400 Subject: [PATCH 191/236] Fix wrong methods roles in NodeOperatorsRegistry --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 18b4be817..f1070c39b 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -592,7 +592,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @param _isTargetLimitActive active flag function updateTargetValidatorsLimits(uint256 _nodeOperatorId, bool _isTargetLimitActive, uint256 _targetLimit) external { _onlyExistedNodeOperator(_nodeOperatorId); - _auth(MANAGE_NODE_OPERATOR_ROLE); + _auth(STAKING_ROUTER_ROLE); _requireValidRange(_targetLimit <= UINT64_MAX); Packed64x4.Packed memory operatorTargetStats = _loadOperatorTargetValidatorsStats(_nodeOperatorId); @@ -676,15 +676,20 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @notice Invalidates all unused deposit data for all node operators function onWithdrawalCredentialsChanged() external { + _auth(STAKING_ROUTER_ROLE); uint256 operatorsCount = getNodeOperatorsCount(); if (operatorsCount > 0) { - invalidateReadyToDepositKeysRange(0, operatorsCount - 1); + _invalidateReadyToDepositKeysRange(0, operatorsCount - 1); } } /// @notice Invalidates all unused validators keys for all node operators - function invalidateReadyToDepositKeysRange(uint256 _indexFrom, uint256 _indexTo) public { + function invalidateReadyToDepositKeysRange(uint256 _indexFrom, uint256 _indexTo) external { _auth(MANAGE_NODE_OPERATOR_ROLE); + _invalidateReadyToDepositKeysRange(_indexFrom, _indexTo); + } + + function _invalidateReadyToDepositKeysRange(uint256 _indexFrom, uint256 _indexTo) internal { _requireValidRange(_indexFrom <= _indexTo && _indexTo < getNodeOperatorsCount()); uint64 trimmedKeysCount; From f9cd0b0a987b7f9eb73f8f2d29624d7f496f34a7 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 03:29:05 +0400 Subject: [PATCH 192/236] Fix getRewardsDistribution precision loss --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 7 ++++--- test/0.4.24/node-operators-registry.test.js | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index f1070c39b..e8042e5cb 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -947,10 +947,11 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { if (totalActiveValidatorsCount == 0) return (recipients, shares, penalized); - uint256 perValidatorReward = _totalRewardShares.div(totalActiveValidatorsCount); - for (idx = 0; idx < activeCount; ++idx) { - shares[idx] = shares[idx].mul(perValidatorReward); + /// @dev unsafe division used below for gas savings. It's safe in the current case + /// because SafeMath.div() only validates that the divider isn't equal to zero. + /// totalActiveValidatorsCount guaranteed greater than zero. + shares[idx] = shares[idx].mul(_totalRewardShares) / totalActiveValidatorsCount; } return (recipients, shares, penalized); diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index 03eff5c05..966929319 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -2269,9 +2269,11 @@ contract('NodeOperatorsRegistry', (addresses) => { 0n ) - const perValidatorReward = totalRewardsShare / totalActiveNodeOperators const expectedRewardsDistribution = NODE_OPERATORS.filter((n) => n.isActive !== false).map((n) => - n.isActive === false ? 0n : perValidatorReward * BigInt(n.depositedSigningKeysCount - n.exitedSigningKeysCount) + n.isActive === false + ? 0n + : (totalRewardsShare * BigInt(n.depositedSigningKeysCount - n.exitedSigningKeysCount)) / + totalActiveNodeOperators ) assert.equals(shares.length, expectedRewardsDistribution.length) for (let i = 0; i < shares.length; ++i) { From 889dd2624b39467420d635fe6f55d6f7c434e65e Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 03:38:16 +0400 Subject: [PATCH 193/236] getStakingModuleActiveValidatorsCount takes into account exited validators count in StakingRouter --- contracts/0.8.9/StakingRouter.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 7ec502e88..5a4f22e65 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -812,13 +812,16 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version view returns (uint256 activeValidatorsCount) { + StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId); ( uint256 totalExitedValidatorsCount, uint256 totalDepositedValidatorsCount, /* uint256 depositableValidatorsCount */ - ) = IStakingModule(_getStakingModuleAddressById(_stakingModuleId)).getStakingModuleSummary(); + ) = IStakingModule(stakingModule.stakingModuleAddress).getStakingModuleSummary(); - activeValidatorsCount = totalDepositedValidatorsCount - totalExitedValidatorsCount; + activeValidatorsCount = totalDepositedValidatorsCount - Math256.max( + stakingModule.exitedValidatorsCount, totalExitedValidatorsCount + ); } /// @dev calculate the max count of deposits which the staking module can provide data for based From cf243fc16146c50746588ddbfb525531ca7d1aae Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 10:28:26 +0400 Subject: [PATCH 194/236] Limit the stuckPenaltyDelay value --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 2 ++ lib/abi/NodeOperatorsRegistry.json | 2 +- test/0.4.24/node-operators-registry.test.js | 31 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index e8042e5cb..013a82ad5 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -80,6 +80,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { // uint256 public constant MAX_NODE_OPERATORS_COUNT = 200; uint256 public constant MAX_NODE_OPERATOR_NAME_LENGTH = 255; + uint256 public constant MAX_STUCK_PENALTY_DELAY = 365 days; uint256 internal constant UINT64_MAX = 0xFFFFFFFFFFFFFFFF; @@ -1322,6 +1323,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @dev set new stuck penalty delay, duration in sec function _setStuckPenaltyDelay(uint256 _delay) internal { + _requireValidRange(_delay <= MAX_STUCK_PENALTY_DELAY); STUCK_PENALTY_DELAY_POSITION.setStorageUint256(_delay); emit StuckPenaltyDelayChanged(_delay); } diff --git a/lib/abi/NodeOperatorsRegistry.json b/lib/abi/NodeOperatorsRegistry.json index 2b98683ac..846e58f1a 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":"_nodeOperatorId","type":"uint256"}],"name":"clearNodeOperatorPenalty","outputs":[{"name":"","type":"bool"}],"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":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"initialize","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":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":"","type":"uint256"}],"name":"onRewardsMinted","outputs":[],"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":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_nodeOperatorIds","type":"bytes"},{"name":"_exitedValidatorsCounts","type":"bytes"}],"name":"updateExitedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorIds","type":"bytes"},{"name":"_stuckValidatorsCounts","type":"bytes"}],"name":"updateStuckValidatorsCount","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":"_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":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint256"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"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":"onExitedAndStuckValidatorsCountsUpdated","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":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"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenaltyCleared","outputs":[{"name":"","type":"bool"}],"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":"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":false,"name":"stuckPenaltyDelay","type":"uint256"}],"name":"StuckPenaltyDelayChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"},{"indexed":false,"name":"refundedValidatorsCount","type":"uint256"},{"indexed":false,"name":"stuckPenaltyEndTimestamp","type":"uint256"}],"name":"StuckPenaltyStateChanged","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":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":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":"_nodeOperatorId","type":"uint256"}],"name":"clearNodeOperatorPenalty","outputs":[{"name":"","type":"bool"}],"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":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"initialize","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":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":"","type":"uint256"}],"name":"onRewardsMinted","outputs":[],"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":false,"inputs":[{"name":"_locator","type":"address"},{"name":"_type","type":"bytes32"},{"name":"_stuckPenaltyDelay","type":"uint256"}],"name":"finalizeUpgrade_v2","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_nodeOperatorIds","type":"bytes"},{"name":"_exitedValidatorsCounts","type":"bytes"}],"name":"updateExitedValidatorsCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_nodeOperatorIds","type":"bytes"},{"name":"_stuckValidatorsCounts","type":"bytes"}],"name":"updateStuckValidatorsCount","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":"_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":"_isTargetLimitActive","type":"bool"},{"name":"_targetLimit","type":"uint256"}],"name":"updateTargetValidatorsLimits","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"_depositsCount","type":"uint256"},{"name":"","type":"bytes"}],"name":"obtainDepositData","outputs":[{"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":true,"inputs":[],"name":"MAX_STUCK_PENALTY_DELAY","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"onExitedAndStuckValidatorsCountsUpdated","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":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"},{"constant":true,"inputs":[{"name":"_nodeOperatorId","type":"uint256"}],"name":"isOperatorPenaltyCleared","outputs":[{"name":"","type":"bool"}],"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":"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":false,"name":"stuckPenaltyDelay","type":"uint256"}],"name":"StuckPenaltyDelayChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"nodeOperatorId","type":"uint256"},{"indexed":false,"name":"stuckValidatorsCount","type":"uint256"},{"indexed":false,"name":"refundedValidatorsCount","type":"uint256"},{"indexed":false,"name":"stuckPenaltyEndTimestamp","type":"uint256"}],"name":"StuckPenaltyStateChanged","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":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 diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index 966929319..1070b5e64 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -12,6 +12,7 @@ const signingKeys = require('../helpers/signing-keys') const { prepIdsCountsPayload, ETH, pad, hexConcat, toBN, padRight } = require('../helpers/utils') const { getRandomLocatorConfig } = require('../helpers/locator') const { ZERO_ADDRESS } = require('../helpers/constants') +const { wei } = require('../helpers/wei') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistryMock') const SigningKeys = artifacts.require('SigningKeys') @@ -3620,4 +3621,34 @@ contract('NodeOperatorsRegistry', (addresses) => { await app.onRewardsMinted(123, { from: stakingRouter }) }) }) + + describe('setStuckPenaltyDelay()', () => { + it('reverts with error "APP_AUTH_FAILED" when called by sender without MANAGE_NODE_OPERATOR_ROLE', async () => { + const hasPermission = await dao.hasPermission(nobody, app, 'MANAGE_NODE_OPERATOR_ROLE') + assert.isFalse(hasPermission) + const maxStuckPenaltyDelay = await app.MAX_STUCK_PENALTY_DELAY() + await assert.reverts(app.setStuckPenaltyDelay(maxStuckPenaltyDelay, { from: nobody }), 'APP_AUTH_FAILED') + }) + + it('reverts with error "OUT_OF_RANGE" when new value exceeds MAX_PENALTY_DELAY', async () => { + const maxStuckPenaltyDelay = wei.int(await app.MAX_STUCK_PENALTY_DELAY()) + await assert.reverts( + app.setStuckPenaltyDelay(wei.str(maxStuckPenaltyDelay + 1n), { from: nodeOperatorsManager }), + 'OUT_OF_RANGE' + ) + }) + + it('sets stuck penalty delay correctly', async () => { + const newStuckPenaltyDelay = await app.MAX_STUCK_PENALTY_DELAY() + assert.notEquals(await app.getStuckPenaltyDelay(), newStuckPenaltyDelay) + await app.setStuckPenaltyDelay(newStuckPenaltyDelay, { from: nodeOperatorsManager }) + assert.equals(await app.getStuckPenaltyDelay(), newStuckPenaltyDelay) + }) + + it('emits event StuckPenaltyDelayChanged() when setStuckPenaltyDelay is called', async () => { + const sameStackPenaltyDelay = await app.getStuckPenaltyDelay() + const tx = await app.setStuckPenaltyDelay(sameStackPenaltyDelay, { from: nodeOperatorsManager }) + assert.emits(tx, 'StuckPenaltyDelayChanged', { stuckPenaltyDelay: sameStackPenaltyDelay }) + }) + }) }) From 64765b2f0f2c45b52438ac416784101adb3b59ce Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 12:47:04 +0400 Subject: [PATCH 195/236] updateExitedValidatorsCountByStakingModule don't read staking module id from storage --- contracts/0.8.9/StakingRouter.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 5a4f22e65..a047aa4ac 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -306,8 +306,10 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version revert ArraysLengthMismatch(_stakingModuleIds.length, _exitedValidatorsCounts.length); } + uint256 stakingModuleId; for (uint256 i = 0; i < _stakingModuleIds.length; ) { - StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleIds[i]); + stakingModuleId = _stakingModuleIds[i]; + StakingModule storage stakingModule = _getStakingModuleById(stakingModuleId); uint256 prevReportedExitedValidatorsCount = stakingModule.exitedValidatorsCount; if (_exitedValidatorsCounts[i] < prevReportedExitedValidatorsCount) { @@ -323,7 +325,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version if (totalExitedValidatorsCount < prevReportedExitedValidatorsCount) { // not all of the exited validators were async reported to the module emit StakingModuleExitedValidatorsIncompleteReporting( - stakingModule.id, + stakingModuleId, prevReportedExitedValidatorsCount - totalExitedValidatorsCount ); } From b86c4697bccf5b6b9cf5cc1a36ce682734e50707 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 16:22:08 +0400 Subject: [PATCH 196/236] Doesn't call onRewardsMinted with zero rewards minted --- contracts/0.8.9/StakingRouter.sol | 16 +++++++++------- test/0.8.9/staking-router/staking-router.test.js | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index a047aa4ac..e4d001121 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -283,13 +283,15 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version } for (uint256 i = 0; i < _stakingModuleIds.length; ) { - address moduleAddr = _getStakingModuleById(_stakingModuleIds[i]).stakingModuleAddress; - try IStakingModule(moduleAddr).onRewardsMinted(_totalShares[i]) {} - catch (bytes memory lowLevelRevertData) { - emit RewardsMintedReportFailed( - _stakingModuleIds[i], - lowLevelRevertData - ); + if (_totalShares[i] > 0) { + address moduleAddr = _getStakingModuleById(_stakingModuleIds[i]).stakingModuleAddress; + try IStakingModule(moduleAddr).onRewardsMinted(_totalShares[i]) {} + catch (bytes memory lowLevelRevertData) { + emit RewardsMintedReportFailed( + _stakingModuleIds[i], + lowLevelRevertData + ); + } } unchecked { ++i; } } diff --git a/test/0.8.9/staking-router/staking-router.test.js b/test/0.8.9/staking-router/staking-router.test.js index 3d0866268..6fed47211 100644 --- a/test/0.8.9/staking-router/staking-router.test.js +++ b/test/0.8.9/staking-router/staking-router.test.js @@ -912,6 +912,21 @@ contract('StakingRouter', ([deployer, lido, admin, appManager, stranger]) => { assert.equal(+module2lastcall.totalShares, 400) }) + it("doesn't call onRewardsMinted() on staking module when its share is equal to zero", async () => { + const stakingModuleIds = [1, 2] + const totalShares = [500, 0] + + await router.reportRewardsMinted(stakingModuleIds, totalShares, { from: admin }) + + const module1lastcall = await module1.lastCall_onRewardsMinted() + assert.equal(+module1lastcall.callCount, 2) + assert.equal(+module1lastcall.totalShares, 800) + + const module2lastcall = await module2.lastCall_onRewardsMinted() + assert.equal(+module2lastcall.callCount, 1) + assert.equal(+module2lastcall.totalShares, 400) + }) + it('handles reverted staking modules correctly', async () => { const stakingModuleWithBug = await StakingModuleStub.new() // staking module will revert with message "UNHANDLED_ERROR" From 8bb30e04f98f4cc539ea624d177704bcef3d96b5 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 17:05:06 +0400 Subject: [PATCH 197/236] Fix typo in the _addSigningKeys variable name --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 013a82ad5..92059e6e2 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -1009,7 +1009,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { // upd totals Packed64x4.Packed memory summarySigningKeysStats = _loadSummarySigningKeysStats(); summarySigningKeysStats.set( - TOTAL_KEYS_COUNT_OFFSET, summarySigningKeysStats.get(SUMMARY_TOTAL_KEYS_COUNT_OFFSET).add(uint64(_keysCount)) + SUMMARY_TOTAL_KEYS_COUNT_OFFSET, summarySigningKeysStats.get(SUMMARY_TOTAL_KEYS_COUNT_OFFSET).add(uint64(_keysCount)) ); _saveSummarySigningKeysStats(summarySigningKeysStats); From ad130a613ca09af4cd91040b788544f5346c7639 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Wed, 8 Mar 2023 17:23:16 +0400 Subject: [PATCH 198/236] Burn shares in _distributeRewards() in one call --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 92059e6e2..8de645296 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -1289,8 +1289,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { (address[] memory recipients, uint256[] memory shares, bool[] memory penalized) = getRewardsDistribution(sharesToDistribute); - distributed = 0; - + uint256 burned; for (uint256 idx; idx < recipients.length; ++idx) { /// @dev skip ultra-low amounts processing to avoid transfer zero amount in case of a penalty if (shares[idx] < 2) continue; @@ -1298,13 +1297,16 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @dev half reward punishment /// @dev ignore remainder since it accumulated on contract balance shares[idx] >>= 1; - IBurner(getLocator().burner()).requestBurnShares(address(this), shares[idx]); + burned = burned.add(shares[idx]); emit NodeOperatorPenalized(recipients[idx], shares[idx]); } stETH.transferShares(recipients[idx], shares[idx]); distributed = distributed.add(shares[idx]); emit RewardsDistributed(recipients[idx], shares[idx]); } + if (burned > 0) { + IBurner(getLocator().burner()).requestBurnShares(address(this), burned); + } } function getLocator() public view returns (ILidoLocator) { From 14c355beb17bf430687185af1526113addba72ab Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 9 Mar 2023 03:22:34 +0400 Subject: [PATCH 199/236] Fix typo in activateNodeOperator() comment --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 8de645296..741088fd4 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -323,7 +323,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { } /// @notice Activates deactivated node operator with given id - /// @param _nodeOperatorId Node operator id to deactivate + /// @param _nodeOperatorId Node operator id to activate function activateNodeOperator(uint256 _nodeOperatorId) external { _onlyExistedNodeOperator(_nodeOperatorId); _auth(MANAGE_NODE_OPERATOR_ROLE); From db9af5d94e907f3111a3bb89092b31ac2b53407a Mon Sep 17 00:00:00 2001 From: Artyom Veremeenko Date: Thu, 9 Mar 2023 10:06:31 +0400 Subject: [PATCH 200/236] follow-ups: refactor, docs, tests --- contracts/0.8.9/WithdrawalQueue.sol | 8 +-- .../0.8.9/oracle/ValidatorsExitBusOracle.sol | 12 +++-- .../PausableUntilPrivateExposed.sol | 5 +- contracts/0.8.9/utils/PausableUntil.sol | 28 ++++++---- lib/abi/ValidatorsExitBusOracle.json | 2 +- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- ...ors-exit-bus-oracle-access-control.test.js | 8 +-- .../validators-exit-bus-oracle-deploy.test.js | 2 +- ...exit-bus-oracle-submit-report-data.test.js | 2 +- test/0.8.9/pausable-until.test.js | 51 ++++++++++++++++--- test/0.8.9/withdrawal-queue.test.js | 16 +++--- 12 files changed, 96 insertions(+), 42 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index f1eeb553d..2364df84b 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -94,17 +94,17 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @dev Reverts with `ResumedExpected()` if contract is already paused /// @dev Reverts with `AccessControl:...` reason if sender has no `PAUSE_ROLE` /// @dev Reverts with `ZeroPauseDuration()` if zero duration is passed - function pause(uint256 _duration) external onlyRole(PAUSE_ROLE) { + function pauseFor(uint256 _duration) external onlyRole(PAUSE_ROLE) { _pauseFor(_duration); } /// @notice Pause withdrawal requests placement and finalization. Claiming finalized requests will still be available - /// @param _resumeSince the first second to resume since + /// @param _pauseUntilInclusive the last second to pause until inclusive /// @dev Reverts with `ResumeSinceInPast()` if the timestamp is in the past /// @dev Reverts with `AccessControl:...` reason if sender has no `PAUSE_ROLE` /// @dev Reverts with `ResumedExpected()` if contract is already paused - function pauseUntil(uint256 _resumeSince) external onlyRole(PAUSE_ROLE) { - _pauseUntil(_resumeSince); + function pauseUntil(uint256 _pauseUntilInclusive) external onlyRole(PAUSE_ROLE) { + _pauseUntil(_pauseUntilInclusive); } /// @notice Request the sequence of stETH withdrawals according to passed `withdrawalRequestInputs` data diff --git a/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol b/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol index 295321808..d55120563 100644 --- a/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol +++ b/contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol @@ -125,15 +125,17 @@ contract ValidatorsExitBusOracle is BaseOracle, PausableUntil { /// @dev Reverts with `AccessControl:...` reason if sender has no `PAUSE_ROLE` /// @dev Reverts with `ZeroPauseDuration()` if zero duration is passed /// - function pause(uint256 _duration) external onlyRole(PAUSE_ROLE) { + function pauseFor(uint256 _duration) external onlyRole(PAUSE_ROLE) { _pauseFor(_duration); } - /// @notice Pause withdrawal requests placement and finalization. Claiming finalized requests will still be available - /// @param _resumeSince the first second to resume since + /// @notice Pause accepting report data + /// @param _pauseUntilInclusive the last second to pause until /// @dev Reverts with `ResumeSinceInPast()` if the timestamp is in the past - function pauseUntil(uint256 _resumeSince) external onlyRole(PAUSE_ROLE) { - _pauseUntil(_resumeSince); + /// @dev Reverts with `AccessControl:...` reason if sender has no `PAUSE_ROLE` + /// @dev Reverts with `ResumedExpected()` if contract is already paused + function pauseUntil(uint256 _pauseUntilInclusive) external onlyRole(PAUSE_ROLE) { + _pauseUntil(_pauseUntilInclusive); } /// diff --git a/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol b/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol index ed86baf14..be89de367 100644 --- a/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol +++ b/contracts/0.8.9/test_helpers/PausableUntilPrivateExposed.sol @@ -20,8 +20,11 @@ contract PausableUntilPrivateExposed is PausableUntil { _resume(); } - function pause(uint256 _duration) external { + function pauseFor(uint256 _duration) external { _pauseFor(_duration); } + function pauseUntil(uint256 _pauseUntilInclusive) external { + _pauseUntil(_pauseUntilInclusive); + } } diff --git a/contracts/0.8.9/utils/PausableUntil.sol b/contracts/0.8.9/utils/PausableUntil.sol index ae4ba6c52..c739df308 100644 --- a/contracts/0.8.9/utils/PausableUntil.sol +++ b/contracts/0.8.9/utils/PausableUntil.sol @@ -13,7 +13,7 @@ contract PausableUntil { /// Special value for the infinite pause uint256 public constant PAUSE_INFINITELY = type(uint256).max; - /// @notice Emitted when paused by the `pause(duration)` call + /// @notice Emitted when paused by the `pauseFor(duration)` call event Paused(uint256 duration); /// @notice Emitted when resumed by the `resume` call event Resumed(); @@ -60,13 +60,15 @@ contract PausableUntil { return RESUME_SINCE_TIMESTAMP_POSITION.getStorageUint256(); } - function _resume() internal whenPaused { + function _resume() internal { + _checkPaused(); RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(block.timestamp); emit Resumed(); } - function _pauseFor(uint256 _duration) internal whenResumed { + function _pauseFor(uint256 _duration) internal { + _checkResumed(); if (_duration == 0) revert ZeroPauseDuration(); uint256 resumeSince; @@ -75,17 +77,25 @@ contract PausableUntil { } else { resumeSince = block.timestamp + _duration; } + _setPausedState(resumeSince); + } - RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(resumeSince); + function _pauseUntil(uint256 _pauseUntilInclusive) internal { + _checkResumed(); + if (_pauseUntilInclusive <= block.timestamp) revert ResumeSinceInPast(); - emit Paused(_duration); - } + uint256 resumeSince; + if (_pauseUntilInclusive != PAUSE_INFINITELY) { + resumeSince = _pauseUntilInclusive + 1; + } else { + resumeSince = PAUSE_INFINITELY; + } + _setPausedState(resumeSince); - function _pauseUntil(uint256 _resumeSince) internal whenResumed { - if (_resumeSince < block.timestamp) revert ResumeSinceInPast(); + } + function _setPausedState(uint256 _resumeSince) internal { RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(_resumeSince); - emit Paused(_resumeSince - block.timestamp); } } diff --git a/lib/abi/ValidatorsExitBusOracle.json b/lib/abi/ValidatorsExitBusOracle.json index a5b3bedbf..d4c7d3af4 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":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":"ResumeSinceInPast","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":[],"name":"getResumeSinceTimestamp","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":"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":"uint256","name":"_resumeSince","type":"uint256"}],"name":"pauseUntil","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":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":"ResumeSinceInPast","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":[],"name":"getResumeSinceTimestamp","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":"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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 256ce0012..4f0585aa5 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_resumeSince","type":"uint256"}],"name":"pauseUntil","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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 8a35ff77f..d21054992 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":[{"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"uint256","name":"_resumeSince","type":"uint256"}],"name":"pauseUntil","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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":[{"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js index ecb0ec368..319e305f4 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-access-control.test.js @@ -133,13 +133,13 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, account1 context('pause', () => { it('should revert without PAUSE_ROLE role', async () => { - await assert.revertsOZAccessControl(oracle.pause(0, { from: stranger }), stranger, 'PAUSE_ROLE') + await assert.revertsOZAccessControl(oracle.pauseFor(0, { from: stranger }), stranger, 'PAUSE_ROLE') }) it('should allow calling from a possessor of PAUSE_ROLE role', async () => { await oracle.grantRole(pauseRoleKeccak156, account1) - const tx = await oracle.pause(9999, { from: account1 }) + const tx = await oracle.pauseFor(9999, { from: account1 }) assert.emits(tx, 'Paused', { duration: 9999 }) }) }) @@ -150,13 +150,13 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, account1 context('resume', () => { it('should revert without RESUME_ROLE role', async () => { - await oracle.pause(9999, { from: admin }) + await oracle.pauseFor(9999, { from: admin }) await assert.revertsOZAccessControl(oracle.resume({ from: stranger }), stranger, 'RESUME_ROLE') }) it('should allow calling from a possessor of RESUME_ROLE role', async () => { - await oracle.pause(9999, { from: admin }) + await oracle.pauseFor(9999, { from: admin }) await oracle.grantRole(resumeRoleKeccak156, account1) const tx = await oracle.resume({ from: account1 }) 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 f047e7740..b69b28e8f 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 @@ -180,7 +180,7 @@ contract('ValidatorsExitBusOracle', ([admin, member1]) => { assert.equal(await oracle.isPaused(), true) await oracle.resume() assert.equal(await oracle.isPaused(), false) - await oracle.pause(123) + await oracle.pauseFor(123) assert.equal(await oracle.isPaused(), true) }) }) diff --git a/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js b/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js index bc9c75b2e..45f611c18 100644 --- a/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js +++ b/test/0.8.9/oracle/validators-exit-bus-oracle-submit-report-data.test.js @@ -429,7 +429,7 @@ contract('ValidatorsExitBusOracle', ([admin, member1, member2, member3, stranger it('reverts on paused contract', async () => { await consensus.advanceTimeToNextFrameStart() const PAUSE_INFINITELY = await oracle.PAUSE_INFINITELY() - await oracle.pause(PAUSE_INFINITELY, { from: admin }) + await oracle.pauseFor(PAUSE_INFINITELY, { from: admin }) const report = await prepareReportAndSubmitHash() assert.reverts(oracle.submitReportData(report, oracleVersion, { from: member1 }), 'ResumedExpected()') }) diff --git a/test/0.8.9/pausable-until.test.js b/test/0.8.9/pausable-until.test.js index 136dab74d..a1b05d969 100644 --- a/test/0.8.9/pausable-until.test.js +++ b/test/0.8.9/pausable-until.test.js @@ -32,7 +32,7 @@ contract('PausableUntil', ([deployer]) => { assert.equals(await pausable.getResumeSinceTimestamp(), resumeSinceTimestamp) } - await assert.revertsWithCustomError(pausable.pause(12345), `ResumedExpected()`) + await assert.revertsWithCustomError(pausable.pauseFor(12345), `ResumedExpected()`) await assert.revertsWithCustomError(pausable.stubUnderModifierWhenResumed(), `ResumedExpected()`) } @@ -52,14 +52,14 @@ contract('PausableUntil', ([deployer]) => { }) it(`revert if pause for zero duration`, async () => { - await assert.revertsWithCustomError(pausable.pause(0), `ZeroPauseDuration()`) + await assert.revertsWithCustomError(pausable.pauseFor(0), `ZeroPauseDuration()`) }) it(`pause infinitely`, async () => { await assertResumedState() const MONTH_IN_SECS = 30 * 24 * 60 * 60 - await pausable.pause(PAUSE_INFINITELY) + await pausable.pauseFor(PAUSE_INFINITELY) await assertPausedState(PAUSE_INFINITELY) await advanceChainTime(MONTH_IN_SECS) @@ -69,11 +69,11 @@ contract('PausableUntil', ([deployer]) => { await assertPausedState(PAUSE_INFINITELY) }) - it(`pause on specific pauseDuration`, async () => { + it(`pause for specific duration`, async () => { assert.isFalse(await pausable.isPaused()) const pauseDuration = 3 * 60 - await pausable.pause(pauseDuration) + await pausable.pauseFor(pauseDuration) const resumeSinceTimestamp = (await getCurrentBlockTimestamp()) + pauseDuration await assertPausedState(resumeSinceTimestamp) @@ -81,7 +81,42 @@ contract('PausableUntil', ([deployer]) => { assert.isTrue(await pausable.isPaused()) await advanceChainTime(resumeSinceTimestamp - 1 - (await getCurrentBlockTimestamp())) assert.equals(await getCurrentBlockTimestamp(), resumeSinceTimestamp - 1) - // Check only view here because with revert transactions chain can pass more than 1 seconds + // Check only view here because with reverted transactions chain can pass more than 1 seconds + assert.isTrue(await pausable.isPaused()) + + await advanceChainTime(1) + assert.equals(await getCurrentBlockTimestamp(), resumeSinceTimestamp) + await assertResumedState() + }) + + it(`pause until infinity`, async () => { + await assertResumedState() + const MONTH_IN_SECS = 30 * 24 * 60 * 60 + + await pausable.pauseUntil(PAUSE_INFINITELY) + await assertPausedState(PAUSE_INFINITELY) + + await advanceChainTime(MONTH_IN_SECS) + await assertPausedState(PAUSE_INFINITELY) + + await advanceChainTime(12 * MONTH_IN_SECS) + await assertPausedState(PAUSE_INFINITELY) + }) + + it(`pause until`, async () => { + assert.isFalse(await pausable.isPaused()) + const pauseDuration = 3 * 60 + const pauseUntilInclusive = (await getCurrentBlockTimestamp()) + pauseDuration - 1 + const resumeSinceTimestamp = pauseUntilInclusive + 1 + + await pausable.pauseUntil(pauseUntilInclusive) + await assertPausedState(resumeSinceTimestamp) + + await advanceChainTime(Math.floor(pauseDuration / 2)) + assert.isTrue(await pausable.isPaused()) + await advanceChainTime(resumeSinceTimestamp - 1 - (await getCurrentBlockTimestamp())) + assert.equals(await getCurrentBlockTimestamp(), resumeSinceTimestamp - 1) + // Check only view here because with reverted transactions chain can pass more than 1 seconds assert.isTrue(await pausable.isPaused()) await advanceChainTime(1) @@ -90,11 +125,11 @@ contract('PausableUntil', ([deployer]) => { }) it(`resume`, async () => { - await pausable.pause(PAUSE_INFINITELY) + await pausable.pauseFor(PAUSE_INFINITELY) await pausable.resume() await assertResumedState() - await pausable.pause(123) + await pausable.pauseFor(123) await pausable.resume() await assertResumedState() }) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 796d64d59..632ffa6c4 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -54,19 +54,23 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const [PAUSE_ROLE, RESUME_ROLE] = await Promise.all([withdrawalQueue.PAUSE_ROLE(), withdrawalQueue.RESUME_ROLE()]) await withdrawalQueue.grantRole(PAUSE_ROLE, pauser, { from: daoAgent }) await withdrawalQueue.grantRole(RESUME_ROLE, resumer, { from: daoAgent }) - await withdrawalQueue.pause(100000000, { from: pauser }) + await withdrawalQueue.pauseFor(100000000, { from: pauser }) assert(await withdrawalQueue.isPaused()) await withdrawalQueue.resume({ from: resumer }) assert(!(await withdrawalQueue.isPaused())) - await assert.revertsOZAccessControl(withdrawalQueue.pause(100000000, { from: resumer }), resumer, 'PAUSE_ROLE') - await assert.revertsOZAccessControl(withdrawalQueue.pause(100000000, { from: stranger }), stranger, 'PAUSE_ROLE') - await withdrawalQueue.pause(100000000, { from: pauser }) + await assert.revertsOZAccessControl(withdrawalQueue.pauseFor(100000000, { from: resumer }), resumer, 'PAUSE_ROLE') + await assert.revertsOZAccessControl( + withdrawalQueue.pauseFor(100000000, { from: stranger }), + stranger, + 'PAUSE_ROLE' + ) + await withdrawalQueue.pauseFor(100000000, { from: pauser }) await assert.revertsOZAccessControl(withdrawalQueue.resume({ from: pauser }), pauser, 'RESUME_ROLE') await assert.revertsOZAccessControl(withdrawalQueue.resume({ from: stranger }), stranger, 'RESUME_ROLE') }) it('withdraw/finalize only allowed when at resumed state', async () => { - await withdrawalQueue.pause(100000000, { from: daoAgent }) + await withdrawalQueue.pauseFor(100000000, { from: daoAgent }) assert(await withdrawalQueue.isPaused()) await assert.reverts(withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }), 'ResumedExpected()') const stubPermit = [0, 0, ZERO_BYTES32, ZERO_BYTES32, ZERO_BYTES32] @@ -251,7 +255,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('One cant request while is paused', async () => { const PAUSE_INFINITELY = await withdrawalQueue.PAUSE_INFINITELY() - await withdrawalQueue.pause(PAUSE_INFINITELY, { from: daoAgent }) + await withdrawalQueue.pauseFor(PAUSE_INFINITELY, { from: daoAgent }) await assert.reverts(withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), 'ResumedExpected()') }) From 72fe5050fd77a8ed17b96dd935fc0b05659076e7 Mon Sep 17 00:00:00 2001 From: Artyom Veremeenko Date: Thu, 9 Mar 2023 10:45:22 +0400 Subject: [PATCH 201/236] fix: error name and tests --- contracts/0.8.9/utils/PausableUntil.sol | 6 +++--- lib/abi/ValidatorsExitBusOracle.json | 2 +- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- test/0.8.9/pausable-until.test.js | 22 ++++++++++++++++++++++ 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/contracts/0.8.9/utils/PausableUntil.sol b/contracts/0.8.9/utils/PausableUntil.sol index c739df308..9ccb7ddc5 100644 --- a/contracts/0.8.9/utils/PausableUntil.sol +++ b/contracts/0.8.9/utils/PausableUntil.sol @@ -13,7 +13,7 @@ contract PausableUntil { /// Special value for the infinite pause uint256 public constant PAUSE_INFINITELY = type(uint256).max; - /// @notice Emitted when paused by the `pauseFor(duration)` call + /// @notice Emitted when paused by the `pauseFor` or `pauseUntil` call event Paused(uint256 duration); /// @notice Emitted when resumed by the `resume` call event Resumed(); @@ -21,7 +21,7 @@ contract PausableUntil { error ZeroPauseDuration(); error PausedExpected(); error ResumedExpected(); - error ResumeSinceInPast(); + error PauseUntilMustBeInFuture(); /// @notice Reverts when resumed modifier whenPaused() { @@ -82,7 +82,7 @@ contract PausableUntil { function _pauseUntil(uint256 _pauseUntilInclusive) internal { _checkResumed(); - if (_pauseUntilInclusive <= block.timestamp) revert ResumeSinceInPast(); + if (_pauseUntilInclusive <= block.timestamp) revert PauseUntilMustBeInFuture(); uint256 resumeSince; if (_pauseUntilInclusive != PAUSE_INFINITELY) { diff --git a/lib/abi/ValidatorsExitBusOracle.json b/lib/abi/ValidatorsExitBusOracle.json index d4c7d3af4..580e95171 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":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","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":[],"name":"RefSlotAlreadyProcessing","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":"ResumeSinceInPast","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":[],"name":"getResumeSinceTimestamp","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":"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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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":[{"internalType":"uint256","name":"initialRefSlot","type":"uint256"},{"internalType":"uint256","name":"processingRefSlot","type":"uint256"}],"name":"InitialRefSlotCannotBeLessThanProcessingOne","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[],"name":"InvalidRequestsData","type":"error"},{"inputs":[],"name":"InvalidRequestsDataLength","type":"error"},{"inputs":[],"name":"InvalidRequestsDataSortOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"moduleId","type":"uint256"},{"internalType":"uint256","name":"nodeOpId","type":"uint256"},{"internalType":"uint256","name":"prevRequestedValidatorIndex","type":"uint256"},{"internalType":"uint256","name":"requestedValidatorIndex","type":"uint256"}],"name":"NodeOpValidatorIndexMustIncrease","type":"error"},{"inputs":[],"name":"NonZeroContractVersionOnInit","type":"error"},{"inputs":[],"name":"OnlyConsensusContractCanSubmitReport","type":"error"},{"inputs":[],"name":"PauseUntilMustBeInFuture","type":"error"},{"inputs":[],"name":"PausedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ProcessingDeadlineMissed","type":"error"},{"inputs":[],"name":"RefSlotAlreadyProcessing","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":[],"name":"getResumeSinceTimestamp","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":"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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index 4f0585aa5..aa67b47b5 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"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":[],"name":"PauseUntilMustBeInFuture","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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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 diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index d21054992..78c9633aa 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumeSinceInPast","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":[{"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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":"_stETH","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":"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":[],"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":"PauseUntilMustBeInFuture","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"MANAGE_TOKEN_URI_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":[{"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":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","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"},{"internalType":"uint256","name":"_shareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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 diff --git a/test/0.8.9/pausable-until.test.js b/test/0.8.9/pausable-until.test.js index a1b05d969..a247badc3 100644 --- a/test/0.8.9/pausable-until.test.js +++ b/test/0.8.9/pausable-until.test.js @@ -89,6 +89,28 @@ contract('PausableUntil', ([deployer]) => { await assertResumedState() }) + it(`revert if pause until timestamp in past`, async () => { + const getNextTxBlockTimestamp = async () => { + return (await getCurrentBlockTimestamp()) + 1 + } + await assert.revertsWithCustomError( + pausable.pauseUntil(await getNextTxBlockTimestamp()), + `PauseUntilMustBeInFuture()` + ) + await assert.revertsWithCustomError( + pausable.pauseUntil((await getNextTxBlockTimestamp()) - 1), + `PauseUntilMustBeInFuture()` + ) + await assert.revertsWithCustomError( + pausable.pauseUntil(Math.floor((await getNextTxBlockTimestamp()) / 2)), + `PauseUntilMustBeInFuture()` + ) + await assert.revertsWithCustomError(pausable.pauseUntil(0), `PauseUntilMustBeInFuture()`) + + // But do not revert for timestamp 1 second after now + await pausable.pauseUntil((await getNextTxBlockTimestamp()) + 1) + }) + it(`pause until infinity`, async () => { await assertResumedState() const MONTH_IN_SECS = 30 * 24 * 60 * 60 From 60bc9b77b036eec22b2ab8a3a1d49c6b6614c600 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 9 Mar 2023 11:36:56 +0300 Subject: [PATCH 202/236] fix: follow-up fixes for PausableUntil --- contracts/0.8.9/utils/PausableUntil.sol | 10 +++--- test/0.8.9/pausable-until.test.js | 43 ++++++++++++++++--------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/contracts/0.8.9/utils/PausableUntil.sol b/contracts/0.8.9/utils/PausableUntil.sol index 9ccb7ddc5..91e2c4153 100644 --- a/contracts/0.8.9/utils/PausableUntil.sol +++ b/contracts/0.8.9/utils/PausableUntil.sol @@ -63,7 +63,6 @@ contract PausableUntil { function _resume() internal { _checkPaused(); RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(block.timestamp); - emit Resumed(); } @@ -82,7 +81,7 @@ contract PausableUntil { function _pauseUntil(uint256 _pauseUntilInclusive) internal { _checkResumed(); - if (_pauseUntilInclusive <= block.timestamp) revert PauseUntilMustBeInFuture(); + if (_pauseUntilInclusive < block.timestamp) revert PauseUntilMustBeInFuture(); uint256 resumeSince; if (_pauseUntilInclusive != PAUSE_INFINITELY) { @@ -91,11 +90,14 @@ contract PausableUntil { resumeSince = PAUSE_INFINITELY; } _setPausedState(resumeSince); - } function _setPausedState(uint256 _resumeSince) internal { RESUME_SINCE_TIMESTAMP_POSITION.setStorageUint256(_resumeSince); - emit Paused(_resumeSince - block.timestamp); + if (_resumeSince == PAUSE_INFINITELY) { + emit Paused(PAUSE_INFINITELY); + } else { + emit Paused(_resumeSince - block.timestamp); + } } } diff --git a/test/0.8.9/pausable-until.test.js b/test/0.8.9/pausable-until.test.js index a247badc3..97e966cc6 100644 --- a/test/0.8.9/pausable-until.test.js +++ b/test/0.8.9/pausable-until.test.js @@ -59,7 +59,9 @@ contract('PausableUntil', ([deployer]) => { await assertResumedState() const MONTH_IN_SECS = 30 * 24 * 60 * 60 - await pausable.pauseFor(PAUSE_INFINITELY) + const tx = await pausable.pauseFor(PAUSE_INFINITELY) + assert.emits(tx, 'Paused', { duration: PAUSE_INFINITELY }) + await assertPausedState(PAUSE_INFINITELY) await advanceChainTime(MONTH_IN_SECS) @@ -73,7 +75,9 @@ contract('PausableUntil', ([deployer]) => { assert.isFalse(await pausable.isPaused()) const pauseDuration = 3 * 60 - await pausable.pauseFor(pauseDuration) + const tx = await pausable.pauseFor(pauseDuration) + assert.emits(tx, 'Paused', { duration: pauseDuration }) + const resumeSinceTimestamp = (await getCurrentBlockTimestamp()) + pauseDuration await assertPausedState(resumeSinceTimestamp) @@ -93,10 +97,6 @@ contract('PausableUntil', ([deployer]) => { const getNextTxBlockTimestamp = async () => { return (await getCurrentBlockTimestamp()) + 1 } - await assert.revertsWithCustomError( - pausable.pauseUntil(await getNextTxBlockTimestamp()), - `PauseUntilMustBeInFuture()` - ) await assert.revertsWithCustomError( pausable.pauseUntil((await getNextTxBlockTimestamp()) - 1), `PauseUntilMustBeInFuture()` @@ -107,15 +107,18 @@ contract('PausableUntil', ([deployer]) => { ) await assert.revertsWithCustomError(pausable.pauseUntil(0), `PauseUntilMustBeInFuture()`) - // But do not revert for timestamp 1 second after now - await pausable.pauseUntil((await getNextTxBlockTimestamp()) + 1) + // But do not revert for the next tx timestamp (i.e., pause lasts for the one block) + const tx = await pausable.pauseUntil(await getNextTxBlockTimestamp()) + assert.emits(tx, 'Paused', { duration: 1 }) }) it(`pause until infinity`, async () => { await assertResumedState() const MONTH_IN_SECS = 30 * 24 * 60 * 60 - await pausable.pauseUntil(PAUSE_INFINITELY) + const tx = await pausable.pauseUntil(PAUSE_INFINITELY) + assert.emits(tx, 'Paused', { duration: PAUSE_INFINITELY }) + await assertPausedState(PAUSE_INFINITELY) await advanceChainTime(MONTH_IN_SECS) @@ -128,10 +131,12 @@ contract('PausableUntil', ([deployer]) => { it(`pause until`, async () => { assert.isFalse(await pausable.isPaused()) const pauseDuration = 3 * 60 - const pauseUntilInclusive = (await getCurrentBlockTimestamp()) + pauseDuration - 1 + const pauseUntilInclusive = (await getCurrentBlockTimestamp()) + pauseDuration const resumeSinceTimestamp = pauseUntilInclusive + 1 - await pausable.pauseUntil(pauseUntilInclusive) + const tx = await pausable.pauseUntil(pauseUntilInclusive) + assert.emits(tx, 'Paused', { duration: pauseDuration }) + await assertPausedState(resumeSinceTimestamp) await advanceChainTime(Math.floor(pauseDuration / 2)) @@ -147,12 +152,20 @@ contract('PausableUntil', ([deployer]) => { }) it(`resume`, async () => { - await pausable.pauseFor(PAUSE_INFINITELY) - await pausable.resume() + let tx = await pausable.pauseFor(PAUSE_INFINITELY) + assert.emits(tx, 'Paused', { duration: PAUSE_INFINITELY }) + + tx = await pausable.resume() + assert.emits(tx, 'Resumed') + await assertResumedState() - await pausable.pauseFor(123) - await pausable.resume() + tx = await pausable.pauseFor(123) + assert.emits(tx, 'Paused', { duration: 123 }) + + tx = await pausable.resume() + assert.emits(tx, 'Resumed') + await assertResumedState() }) }) From 37a5496cc2c8fc6d77a25832834d4f01aaaf92a0 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 9 Mar 2023 14:10:58 +0400 Subject: [PATCH 203/236] Fix typos and better naming for local variable --- contracts/0.4.24/nos/NodeOperatorsRegistry.sol | 10 +++++----- contracts/0.8.9/StakingRouter.sol | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 741088fd4..b177856ec 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -621,7 +621,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { ); uint64 curRefundedValidatorsCount = stuckPenaltyStats.get(STUCK_VALIDATORS_COUNT_OFFSET); - if (_stuckValidatorsCount<= curRefundedValidatorsCount && curStuckValidatorsCount > curRefundedValidatorsCount) { + if (_stuckValidatorsCount <= curRefundedValidatorsCount && curStuckValidatorsCount > curRefundedValidatorsCount) { stuckPenaltyStats.set(STUCK_PENALTY_END_TIMESTAMP_OFFSET, uint64(block.timestamp + getStuckPenaltyDelay())); } @@ -1289,7 +1289,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { (address[] memory recipients, uint256[] memory shares, bool[] memory penalized) = getRewardsDistribution(sharesToDistribute); - uint256 burned; + uint256 toBurn; for (uint256 idx; idx < recipients.length; ++idx) { /// @dev skip ultra-low amounts processing to avoid transfer zero amount in case of a penalty if (shares[idx] < 2) continue; @@ -1297,15 +1297,15 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { /// @dev half reward punishment /// @dev ignore remainder since it accumulated on contract balance shares[idx] >>= 1; - burned = burned.add(shares[idx]); + toBurn = toBurn.add(shares[idx]); emit NodeOperatorPenalized(recipients[idx], shares[idx]); } stETH.transferShares(recipients[idx], shares[idx]); distributed = distributed.add(shares[idx]); emit RewardsDistributed(recipients[idx], shares[idx]); } - if (burned > 0) { - IBurner(getLocator().burner()).requestBurnShares(address(this), burned); + if (toBurn > 0) { + IBurner(getLocator().burner()).requestBurnShares(address(this), toBurn); } } diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index e4d001121..addee10d0 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -243,7 +243,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version emit StakingModuleFeesSet(_stakingModuleId, _stakingModuleFee, _treasuryFee, msg.sender); } - /// @notice Updates the limit of the validators that can be used for deposit + /// @notice Updates the limit of the validators that can be used for deposit /// @param _stakingModuleId Id of the staking module /// @param _nodeOperatorId Id of the node operator /// @param _isTargetLimitActive Active flag From 0d40671ddede7b6a5bfbc5f811f61d199097c592 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Thu, 9 Mar 2023 17:28:25 +0700 Subject: [PATCH 204/236] fix: legacyOracle getCurrentEpochId and tests --- contracts/0.4.24/oracle/LegacyOracle.sol | 14 +++-- .../0.4.24/test_helpers/MockLegacyOracle.sol | 15 ++++++ lib/abi/LegacyOracle.json | 2 +- test/0.4.24/legacy-oracle.test.js | 52 +++++++++++++++---- 4 files changed, 67 insertions(+), 16 deletions(-) diff --git a/contracts/0.4.24/oracle/LegacyOracle.sol b/contracts/0.4.24/oracle/LegacyOracle.sol index 7cd084640..429d6915d 100644 --- a/contracts/0.4.24/oracle/LegacyOracle.sol +++ b/contracts/0.4.24/oracle/LegacyOracle.sol @@ -156,17 +156,16 @@ contract LegacyOracle is Versioned, AragonApp { genesisTime = spec.genesisTime; } + + /** * @notice DEPRECATED, kept for compatibility purposes only. * * Returns the epoch calculated from current timestamp */ - function getCurrentEpochId() external view returns (uint256 epochId) { + function getCurrentEpochId() external view returns (uint256) { ChainSpec memory spec = _getChainSpec(); - IHashConsensus consensus = _getAccountingConsensusContract(); - uint256 refSlot; - (refSlot,) = consensus.getCurrentFrame(); - epochId = (refSlot + 1) / spec.slotsPerEpoch; + return (_getTime() - spec.genesisTime) / (spec.slotsPerEpoch * spec.secondsPerSlot);// solhint-disable-line not-rely-on-time } /** @@ -318,6 +317,10 @@ contract LegacyOracle is Versioned, AragonApp { _setContractVersion(4); } + function _getTime() internal view returns (uint256) { + return block.timestamp; // solhint-disable-line not-rely-on-time + } + function _getChainSpec() internal view @@ -335,6 +338,7 @@ contract LegacyOracle is Versioned, AragonApp { require(_chainSpec.slotsPerEpoch > 0, "BAD_SLOTS_PER_EPOCH"); require(_chainSpec.secondsPerSlot > 0, "BAD_SECONDS_PER_SLOT"); require(_chainSpec.genesisTime > 0, "BAD_GENESIS_TIME"); + require(_chainSpec.epochsPerFrame > 0, "BAD_EPOCHS_PER_FRAME"); uint256 data = ( uint256(_chainSpec.epochsPerFrame) << 192 | diff --git a/contracts/0.4.24/test_helpers/MockLegacyOracle.sol b/contracts/0.4.24/test_helpers/MockLegacyOracle.sol index 01049a671..f12162aa4 100644 --- a/contracts/0.4.24/test_helpers/MockLegacyOracle.sol +++ b/contracts/0.4.24/test_helpers/MockLegacyOracle.sol @@ -15,6 +15,10 @@ interface ILegacyOracle { function getLastCompletedEpochId() external view returns (uint256); } +interface ITimeProvider { + function getTime() external view returns (uint256); +} + contract MockLegacyOracle is ILegacyOracle, LegacyOracle { @@ -49,6 +53,17 @@ contract MockLegacyOracle is ILegacyOracle, LegacyOracle { _setChainSpec(ChainSpec(epochsPerFrame,slotsPerEpoch,secondsPerSlot,genesisTime)); } + + function _getTime() internal view returns (uint256) { + address accountingOracle = ACCOUNTING_ORACLE_POSITION.getStorageAddress(); + return ITimeProvider(accountingOracle).getTime(); + } + + function getTime() external view returns (uint256) { + return _getTime(); + } + + function handleConsensusLayerReport(uint256 refSlot, uint256 clBalance, uint256 clValidators) external diff --git a/lib/abi/LegacyOracle.json b/lib/abi/LegacyOracle.json index f43a2461f..6fd74b812 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":"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 +[{"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":"","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 diff --git a/test/0.4.24/legacy-oracle.test.js b/test/0.4.24/legacy-oracle.test.js index 67e0035fc..b248c7bfb 100644 --- a/test/0.4.24/legacy-oracle.test.js +++ b/test/0.4.24/legacy-oracle.test.js @@ -1,7 +1,7 @@ const { contract, ethers, artifacts, web3 } = require('hardhat') const { assert } = require('../helpers/assert') const { impersonate } = require('../helpers/blockchain') -const { e9, e18, e27 } = require('../helpers/utils') +const { e9, e18, e27, toBN } = require('../helpers/utils') const { legacyOracleFactory } = require('../helpers/factories') const OssifiableProxy = artifacts.require('OssifiableProxy') @@ -43,6 +43,12 @@ const getReportFields = (override = {}) => ({ ...override, }) +const oldGetCurrentEpochId = (timestamp) => { + return toBN(timestamp) + .sub(toBN(GENESIS_TIME)) + .div(toBN(SLOTS_PER_EPOCH).mul(toBN(SECONDS_PER_SLOT))) +} + async function deployLegacyOracleWithAccountingOracle({ admin, initialEpoch = 1, lastProcessingRefSlot = 31 }) { const legacyOracle = await legacyOracleFactory({ appManager: { address: admin } }) const { locatorAddr, consensus, oracle, lido } = await deployAccountingOracleSetup(admin, { @@ -63,13 +69,12 @@ module.exports = { contract('LegacyOracle', ([admin, stranger]) => { context('Fresh deploy and puppet methods checks', () => { - let legacyOracle, accountingOracle, lido, consensus + let legacyOracle, accountingOracle, lido before('deploy', async () => { const deployed = await deployLegacyOracleWithAccountingOracle({ admin }) legacyOracle = deployed.legacyOracle accountingOracle = deployed.accountingOracle lido = deployed.lido - consensus = deployed.consensus }) it('initial state is correct', async () => { @@ -81,9 +86,6 @@ contract('LegacyOracle', ([admin, stranger]) => { assert.equals(spec.slotsPerEpoch, SLOTS_PER_EPOCH) assert.equals(spec.secondsPerSlot, SECONDS_PER_SLOT) assert.equals(spec.genesisTime, GENESIS_TIME) - const frame = await consensus.getCurrentFrame() - const epochId = frame.refSlot.addn(1).divn(SLOTS_PER_EPOCH) - assert.equals(await legacyOracle.getCurrentEpochId(), epochId) assert.equals(await legacyOracle.getLastCompletedEpochId(), 0) }) @@ -125,6 +127,38 @@ contract('LegacyOracle', ([admin, stranger]) => { }) }) + context('getCurrentEpochId implementation is correct', () => { + let legacyOracle, consensus, oracle, locatorAddr + + before('deploy time-travelable mock', async () => { + const implementation = await MockLegacyOracle.new({ from: admin }) + const proxy = await OssifiableProxy.new(implementation.address, admin, '0x') + legacyOracle = await MockLegacyOracle.at(proxy.address) + ;({ consensus, oracle, locatorAddr } = await deployAccountingOracleSetup(admin, { + legacyOracleAddrArg: legacyOracle.address, + getLegacyOracle: () => { + return legacyOracle + }, + dataSubmitter: admin, + })) + await legacyOracle.initialize(locatorAddr, consensus.address) + await initAccountingOracle({ + admin, + oracle, + consensus, + shouldMigrateLegacyOracle: false, + lastProcessingRefSlot: 0, + }) + }) + + it('test', async () => { + for (let index = 0; index < 20; index++) { + assert.equals(await legacyOracle.getCurrentEpochId(), oldGetCurrentEpochId(await consensus.getTime())) + await consensus.advanceTimeByEpochs(1) + } + }) + }) + context('Migration from old contract', () => { const lastCompletedEpoch = 10 let oldImplementation @@ -205,14 +239,12 @@ contract('LegacyOracle', ([admin, stranger]) => { it('time in sync with consensus', async () => { await deployedInfra.consensus.advanceTimeToNextFrameStart() - const epochId = await proxyAsNewImplementation.getCurrentEpochId() const { frameEpochId, frameStartTime, frameEndTime } = await proxyAsNewImplementation.getCurrentFrame() - assert.equals(epochId, frameEpochId) const consensusFrame = await deployedInfra.consensus.getCurrentFrame() const refSlot = consensusFrame.refSlot.toNumber() - assert.equals(epochId, Math.floor((refSlot + 1) / SLOTS_PER_EPOCH)) + assert.equals(frameEpochId, Math.floor((refSlot + 1) / SLOTS_PER_EPOCH)) assert.equals(frameStartTime, computeTimestampAtSlot(refSlot + 1)) - assert.equals(frameEndTime, computeTimestampAtEpoch(+epochId + EPOCHS_PER_FRAME) - 1) + assert.equals(frameEndTime, computeTimestampAtEpoch(+frameEpochId + EPOCHS_PER_FRAME) - 1) }) it.skip('handlePostTokenRebase from lido') From 3b0f946516d2a1ac4cf849ee8e16f5d84f8faf65 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 12:29:13 +0200 Subject: [PATCH 205/236] =?UTF-8?q?=F0=9F=94=AA:=20remove=20checkpoint=20o?= =?UTF-8?q?ptimization=20on=20wq=20finalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 26 ++++--------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index b59d733f3..05fe269eb 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -24,8 +24,6 @@ abstract contract WithdrawalQueueBase { uint256 internal constant MAX_BATCHES_LENGTH = 36; uint256 internal constant MAX_REQUESTS_PER_CALL = 1000; - uint256 internal constant SHARE_RATE_UNLIMITED = type(uint256).max; - /// @dev return value for the `find...` methods in case of no result uint256 internal constant NOT_FOUND = 0; @@ -358,28 +356,12 @@ abstract contract WithdrawalQueueBase { uint128 stETHToFinalize = requestToFinalize.cumulativeStETH - lastFinalizedRequest.cumulativeStETH; if (_amountOfETH > stETHToFinalize) revert TooMuchEtherToFinalize(_amountOfETH, stETHToFinalize); - // if `_maxShareRate` is effectively above all of finalizing requests' share rates - // we can effectively say that there is no limit because all the request - // will be fullfilled by their nominal value - uint256 maxShareRate = SHARE_RATE_UNLIMITED; - // if we have a crossing point or avg batch share rate is more than `_maxShareRate` - // then there are some requests that will be discounted and we should store - // `_maxShareRate` to apply this discount on claim - if (_batches.length > 1 || stETHToFinalize > _amountOfETH) { - maxShareRate = _maxShareRate; - } - uint256 firstRequestIdToFinalize = lastFinalizedRequestId + 1; uint256 lastCheckpointIndex = getLastCheckpointIndex(); - Checkpoint storage lastCheckpoint = _getCheckpoints()[lastCheckpointIndex]; - - // In the most common scenario (no slashings) maxShareRate will be SHARE_RATE_UNLIMITED all the time - // and we'll save gas on report and integrations will save gas on hint calculations - if (maxShareRate != lastCheckpoint.maxShareRate) { - // add a new discount if it differs from the previous - _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstRequestIdToFinalize, maxShareRate); - _setLastCheckpointIndex(lastCheckpointIndex + 1); - } + + // add a new checkpoint with current finalization max share rate + _getCheckpoints()[lastCheckpointIndex + 1] = Checkpoint(firstRequestIdToFinalize, _maxShareRate); + _setLastCheckpointIndex(lastCheckpointIndex + 1); _setLockedEtherAmount(getLockedEtherAmount() + _amountOfETH); _setLastFinalizedRequestId(lastRequestIdToBeFinalized); From 39806687e5c798b3628200276c2257bee75691d9 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 12:29:50 +0200 Subject: [PATCH 206/236] =?UTF-8?q?=F0=9F=93=9A:=20improve=20wq=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 05fe269eb..060c76173 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -339,7 +339,7 @@ abstract contract WithdrawalQueueBase { } } - /// @dev Finalize requests from last finalized one up to `_nextFinalizedRequestId` + /// @dev Finalize requests in the queue /// Emits WithdrawalBatchFinalized event. /// Checks that: /// - _amountOfETH is less or equal to the nominal value of all requests to be finalized @@ -406,7 +406,7 @@ abstract contract WithdrawalQueueBase { emit WithdrawalRequested(requestId, msg.sender, _owner, _amountOfStETH, _amountOfShares); } - /// @notice Returns status of the withdrawal request with `_requestId` id + /// @dev Returns status of the withdrawal request with `_requestId` id function _getStatus(uint256 _requestId) internal view returns (WithdrawalRequestStatus memory status) { if (_requestId == 0 || _requestId > getLastRequestId()) revert InvalidRequestId(_requestId); @@ -423,7 +423,7 @@ abstract contract WithdrawalQueueBase { ); } - /// @notice View function to find a checkpoint hint for `claimWithdrawal()` + /// @dev View function to find a checkpoint hint for `claimWithdrawal()` /// Search will be performed in the range of `[_firstIndex, _lastIndex]` /// /// NB!: Range search ought to be used to optimize gas cost. @@ -475,7 +475,7 @@ abstract contract WithdrawalQueueBase { return min; } - /// @notice Claim `_requestId` request and transfer locked ether to `_recipient`. Emits WithdrawalClaimed event + /// @dev Claim `_requestId` request and transfer locked ether to `_recipient`. Emits WithdrawalClaimed event /// @param _requestId request id to claim /// @param _hint hint for discount checkpoint index to avoid extensive search over the checkpoints. /// @param _recipient address to send ether to @@ -501,7 +501,7 @@ abstract contract WithdrawalQueueBase { emit WithdrawalClaimed(_requestId, msg.sender, _recipient, ethWithDiscount); } - /// @notice Calculates discounted ether value for `_requestId` using a provided `_hint`. Checks if hint is valid + /// @dev Calculates discounted ether value for `_requestId` using a provided `_hint`. Checks if hint is valid /// @return claimableEther discounted eth for `_requestId`. Returns 0 if request is not claimable function _calculateClaimableEther(WithdrawalRequest storage _request, uint256 _requestId, uint256 _hint) internal @@ -535,7 +535,7 @@ abstract contract WithdrawalQueueBase { return eth; } - // quazi-constructor + /// @dev quazi-constructor function _initializeQueue() internal { // setting dummy zero structs in checkpoints and queue beginning // to avoid uint underflows and related if-branches @@ -564,7 +564,7 @@ abstract contract WithdrawalQueueBase { } // - // Internal getters and setters + // Internal getters and setters for unstructured storage // function _getQueue() internal pure returns (mapping(uint256 => WithdrawalRequest) storage queue) { bytes32 position = QUEUE_POSITION; From ccec9dcdb556baf5b8b9ce06e0ac89513b6e3fc9 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 9 Mar 2023 13:48:59 +0300 Subject: [PATCH 207/236] chore: style fixes --- contracts/0.4.24/oracle/LegacyOracle.sol | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/contracts/0.4.24/oracle/LegacyOracle.sol b/contracts/0.4.24/oracle/LegacyOracle.sol index 429d6915d..ecd7e07fd 100644 --- a/contracts/0.4.24/oracle/LegacyOracle.sol +++ b/contracts/0.4.24/oracle/LegacyOracle.sol @@ -156,8 +156,6 @@ contract LegacyOracle is Versioned, AragonApp { genesisTime = spec.genesisTime; } - - /** * @notice DEPRECATED, kept for compatibility purposes only. * @@ -165,7 +163,8 @@ contract LegacyOracle is Versioned, AragonApp { */ function getCurrentEpochId() external view returns (uint256) { ChainSpec memory spec = _getChainSpec(); - return (_getTime() - spec.genesisTime) / (spec.slotsPerEpoch * spec.secondsPerSlot);// solhint-disable-line not-rely-on-time + // solhint-disable-line not-rely-on-time + return (_getTime() - spec.genesisTime) / (spec.slotsPerEpoch * spec.secondsPerSlot); } /** @@ -378,12 +377,12 @@ contract LegacyOracle is Versioned, AragonApp { IHashConsensus consensus = _getAccountingConsensusContract(); uint256 refSlot; (refSlot,) = consensus.getCurrentFrame(); - + // new accounting oracle's ref. slot is the last slot of the epoch preceding the one the frame starts at frameStartTime = spec.genesisTime + (refSlot + 1) * spec.secondsPerSlot; // new accounting oracle's frame ends at the timestamp of the frame's last slot; old oracle's frame // ended a second before the timestamp of the first slot of the next frame - frameEndTime = frameStartTime + spec.secondsPerSlot*spec.slotsPerEpoch*spec.epochsPerFrame - 1; + frameEndTime = frameStartTime + spec.secondsPerSlot * spec.slotsPerEpoch * spec.epochsPerFrame - 1; frameEpochId = (refSlot + 1) / spec.slotsPerEpoch; } From 8c0857ef766be723b4b04a3471733538ab2afc3c Mon Sep 17 00:00:00 2001 From: Artyom Veremeenko Date: Thu, 9 Mar 2023 16:07:38 +0400 Subject: [PATCH 208/236] feat (WithdrawalQueue): restore wsteth withdrawals --- contracts/0.8.9/WithdrawalQueue.sol | 66 +++++++++- contracts/0.8.9/WithdrawalQueueERC721.sol | 6 +- lib/abi/IWstETH.json | 1 + lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- test/0.8.9/withdrawal-queue-deploy.test.js | 5 +- test/0.8.9/withdrawal-queue.test.js | 137 ++++++++++++++++++++- test/0.8.9/withdrawal-request-nft.test.js | 8 +- test/helpers/factories.js | 4 +- test/helpers/withdrawals.js | 4 +- test/scenario/helpers/deploy.js | 4 +- 11 files changed, 219 insertions(+), 20 deletions(-) create mode 100644 lib/abi/IWstETH.json diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index 18bc96e73..cdfa4b386 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -21,6 +21,14 @@ interface IStETH is IERC20, IERC20Permit { function getSharesByPooledEth(uint256 _pooledEthAmount) external view returns (uint256); } +/// @notice Interface defining a Lido liquid staking pool wrapper +/// @dev see WstETH.sol for full docs +interface IWstETH is IERC20, IERC20Permit { + function unwrap(uint256 _wstETHAmount) external returns (uint256); + function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); + function stETH() external view returns (IStETH); +} + /// @title A contract for handling stETH withdrawal request queue within the Lido protocol /// @author folkyatina abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, WithdrawalQueueBase, Versioned { @@ -49,7 +57,9 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit uint256 public constant MAX_STETH_WITHDRAWAL_AMOUNT = 1000 * 1e18; /// @notice Lido stETH token address to be set upon construction - IStETH internal immutable STETH; + IStETH public immutable STETH; + /// @notice Lido wstETH token address to be set upon construction + IWstETH public immutable WSTETH; /// @notice Emitted when the contract initialized event InitializedV1(address _admin); @@ -63,10 +73,11 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit error RequestIdsNotSorted(); error ZeroRecipient(); - /// @param _stETH address of stETH contract - constructor(address _stETH) { + /// @param _wstETH address of WstETH contract + constructor(IWstETH _wstETH) { // init immutables - STETH = IStETH(_stETH); + WSTETH = _wstETH; + STETH = WSTETH.stETH(); } /// @notice Initialize the contract storage explicitly. @@ -115,6 +126,24 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit } } + /// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data + /// @param amounts an array of stETH amount values. The standalone withdrawal request will + /// be created for each item in the passed list. + /// @param _owner address that will be able to transfer or claim the request. + /// If `owner` is set to `address(0)`, `msg.sender` will be used as owner. + /// @return requestIds an array of the created withdrawal requests + function requestWithdrawalsWstETH(uint256[] calldata amounts, address _owner) + public + returns (uint256[] memory requestIds) + { + _checkResumed(); + if (_owner == address(0)) _owner = msg.sender; + requestIds = new uint256[](amounts.length); + for (uint256 i = 0; i < amounts.length; ++i) { + requestIds[i] = _requestWithdrawalWstETH(amounts[i], _owner); + } + } + struct PermitInput { uint256 value; uint256 deadline; @@ -139,6 +168,23 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit return requestWithdrawals(_amounts, _owner); } + /// @notice Request the sequence of wstETH withdrawals according to passed `withdrawalRequestInputs` data + /// using EIP-2612 Permit + /// @param _amounts an array of stETH amount values. The standalone withdrawal request will + /// be created for each item in the passed list. + /// @param _owner address that will be able to transfer or claim the request. + /// If `owner` is set to `address(0)`, `msg.sender` will be used as owner. + /// @param _permit data required for the wstETH.permit() method to set the allowance + /// @return requestIds an array of the created withdrawal requests + function requestWithdrawalsWstETHWithPermit( + uint256[] calldata _amounts, + address _owner, + PermitInput calldata _permit + ) external returns (uint256[] memory requestIds) { + WSTETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s); + return requestWithdrawalsWstETH(_amounts, _owner); + } + /// @notice Returns all withdrawal requests that belongs to the `_owner` address /// /// WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed @@ -328,6 +374,18 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit _emitTransfer(address(0), _owner, requestId); } + function _requestWithdrawalWstETH(uint256 _amountOfWstETH, address _owner) internal returns (uint256 requestId) { + WSTETH.transferFrom(msg.sender, address(this), _amountOfWstETH); + uint256 amountOfStETH = WSTETH.unwrap(_amountOfWstETH); + _checkWithdrawalRequestAmount(amountOfStETH); + + uint256 amountOfShares = STETH.getSharesByPooledEth(amountOfStETH); + + requestId = _enqueue(uint128(amountOfStETH), uint128(amountOfShares), _owner); + + _emitTransfer(address(0), _owner, requestId); + } + function _checkWithdrawalRequestAmount(uint256 _amountOfStETH) internal pure { if (_amountOfStETH < MIN_STETH_WITHDRAWAL_AMOUNT) { revert RequestAmountTooSmall(_amountOfStETH); diff --git a/contracts/0.8.9/WithdrawalQueueERC721.sol b/contracts/0.8.9/WithdrawalQueueERC721.sol index d15150c39..e22d8201f 100644 --- a/contracts/0.8.9/WithdrawalQueueERC721.sol +++ b/contracts/0.8.9/WithdrawalQueueERC721.sol @@ -13,7 +13,7 @@ import {EnumerableSet} from "@openzeppelin/contracts-v4.4/utils/structs/Enumerab import {Address} from "@openzeppelin/contracts-v4.4/utils/Address.sol"; import {Strings} from "@openzeppelin/contracts-v4.4/utils/Strings.sol"; -import {WithdrawalQueue} from "./WithdrawalQueue.sol"; +import {IWstETH, WithdrawalQueue} from "./WithdrawalQueue.sol"; import {AccessControlEnumerable} from "./utils/access/AccessControlEnumerable.sol"; import {UnstructuredRefStorage} from "./lib/UnstructuredRefStorage.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; @@ -73,10 +73,10 @@ contract WithdrawalQueueERC721 is IERC721Metadata, WithdrawalQueue { bytes32 private immutable NAME; bytes32 private immutable SYMBOL; - /// @param _stETH address of WstETH contract + /// @param _wstETH address of WstETH contract /// @param _name IERC721Metadata name string. Should be shorter than 32 bytes /// @param _symbol IERC721Metadata symbol string. Should be shorter than 32 bytes - constructor(address _stETH, string memory _name, string memory _symbol) WithdrawalQueue(_stETH) { + constructor(address _wstETH, string memory _name, string memory _symbol) WithdrawalQueue(IWstETH(_wstETH)) { if (bytes(_name).length == 0 || bytes(_symbol).length == 0) revert ZeroMetadata(); NAME = _toBytes32(_name); SYMBOL = _toBytes32(_symbol); diff --git a/lib/abi/IWstETH.json b/lib/abi/IWstETH.json new file mode 100644 index 000000000..b034090cf --- /dev/null +++ b/lib/abi/IWstETH.json @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"getStETHByWstETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"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"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stETH","outputs":[{"internalType":"contract IStETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_wstETHAmount","type":"uint256"}],"name":"unwrap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index d6edf91d9..4db9677a2 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index b6807e970..34445f2b4 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ 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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file diff --git a/test/0.8.9/withdrawal-queue-deploy.test.js b/test/0.8.9/withdrawal-queue-deploy.test.js index a75b007fc..075d93ed3 100644 --- a/test/0.8.9/withdrawal-queue-deploy.test.js +++ b/test/0.8.9/withdrawal-queue-deploy.test.js @@ -6,6 +6,7 @@ const withdrawals = require('../helpers/withdrawals') const { assert } = require('../helpers/assert') const StETHMock = artifacts.require('StETHPermitMock.sol') +const WstETH = artifacts.require('WstETHMock.sol') const EIP712StETH = artifacts.require('EIP712StETH') const NFTDescriptorMock = artifacts.require('NFTDescriptorMock.sol') @@ -26,12 +27,13 @@ async function deployWithdrawalQueue({ }) { const nftDescriptor = await NFTDescriptorMock.new(NFT_DESCRIPTOR_BASE_URI) const steth = await StETHMock.new({ value: ETH(1), from: stethOwner }) + const wsteth = await WstETH.new(steth.address, { from: stethOwner }) const eip712StETH = await EIP712StETH.new(steth.address, { from: stethOwner }) await steth.initializeEIP712StETH(eip712StETH.address) const { queue: withdrawalQueue, impl: withdrawalQueueImplementation } = await withdrawals.deploy( queueAdmin, - steth.address, + wsteth.address, queueName, symbol ) @@ -54,6 +56,7 @@ async function deployWithdrawalQueue({ return { initTx, steth, + wsteth, withdrawalQueue, nftDescriptor, withdrawalQueueImplementation, diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 7a9ecbaa8..66d4f827c 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -3,14 +3,14 @@ const { bn, getEventArgument, ZERO_ADDRESS } = require('@aragon/contract-helpers const { ETH, StETH, shareRate, shares } = require('../helpers/utils') const { assert } = require('../helpers/assert') -const { signPermit } = require('../0.6.12/helpers/permit_helpers') -const { MAX_UINT256, ACCOUNTS_AND_KEYS } = require('../0.6.12/helpers/constants') +const { signPermit, makeDomainSeparator } = require('../0.6.12/helpers/permit_helpers') +const { MAX_UINT256, ACCOUNTS_AND_KEYS, ZERO_BYTES32 } = require('../0.6.12/helpers/constants') const { impersonate, EvmSnapshot, getCurrentBlockTimestamp, setBalance } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, oracle]) => { - let withdrawalQueue, steth + let withdrawalQueue, steth, wsteth const snapshot = new EvmSnapshot(ethers.provider) @@ -28,6 +28,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) steth = deployed.steth + wsteth = deployed.wsteth withdrawalQueue = deployed.withdrawalQueue await steth.setTotalPooledEther(ETH(600)) @@ -75,6 +76,16 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, assert(await withdrawalQueue.isPaused()) await assert.reverts(withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }), 'ResumedExpected()') + await assert.reverts( + withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], owner, { from: user }), + 'ResumedExpected()' + ) + const stubPermit = [0, 0, ZERO_BYTES32, ZERO_BYTES32, ZERO_BYTES32] + await assert.reverts( + withdrawalQueue.requestWithdrawalsWstETHWithPermit([ETH(1)], owner, stubPermit, { from: user }), + 'ResumedExpected()' + ) + const [alice] = ACCOUNTS_AND_KEYS const amount = ETH(1) const deadline = MAX_UINT256 @@ -280,6 +291,10 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const PAUSE_INFINITELY = await withdrawalQueue.PAUSE_INFINITELY() await withdrawalQueue.pause(PAUSE_INFINITELY, { from: daoAgent }) await assert.reverts(withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), 'ResumedExpected()') + await assert.reverts( + withdrawalQueue.requestWithdrawalsWstETH([ETH(300)], owner, { from: user }), + 'ResumedExpected()' + ) }) it('data is being accumulated properly', async () => { @@ -916,6 +931,39 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) + context('findCheckpointHintsUnbounded()', () => { + let requestId + const amount = ETH(20) + + beforeEach('Enqueue a request', async () => { + await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) + requestId = await withdrawalQueue.getLastRequestId() + }) + + it('returns correct hints array for given request ids', async () => { + await withdrawalQueue.finalize(requestId, { from: steth.address, value: ETH(20) }) + + await steth.mintShares(owner, shares(1)) + await steth.approve(withdrawalQueue.address, StETH(300), { from: owner }) + + const secondRequestAmount = ETH(10) + await withdrawalQueue.requestWithdrawals([secondRequestAmount], owner, { from: owner }) + const secondRequestId = await withdrawalQueue.getLastRequestId() + + const thirdRequestAmount = ETH(30) + await withdrawalQueue.requestWithdrawals([thirdRequestAmount], user, { from: user }) + const thirdRequestId = await withdrawalQueue.getLastRequestId() + + await withdrawalQueue.finalize(thirdRequestId, { from: steth.address, value: ETH(40) }) + + const hints = await withdrawalQueue.findCheckpointHintsUnbounded([requestId, secondRequestId, thirdRequestId]) + assert.equal(hints.length, 3) + assert.equals(hints[0], 1) + assert.equals(hints[1], 1) + assert.equals(hints[2], 1) + }) + }) + context('claimWithdrawals()', () => { const amount = ETH(20) @@ -955,6 +1003,89 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) }) + context('requestWithdrawalsWstETH()', () => { + it('works correctly with non empty payload and different tokens', async () => { + await wsteth.mint(user, ETH(100)) + await steth.mintShares(wsteth.address, shares(100)) + await steth.mintShares(user, shares(100)) + await wsteth.approve(withdrawalQueue.address, ETH(300), { from: user }) + const requests = [ETH(10), ETH(20)] + const wstETHBalanceBefore = await wsteth.balanceOf(user) + const lastRequestIdBefore = await withdrawalQueue.getLastRequestId() + + await withdrawalQueue.requestWithdrawalsWstETH(requests, stranger, { from: user }) + + assert.equals(await withdrawalQueue.getLastRequestId(), lastRequestIdBefore.add(bn(requests.length))) + const wstETHBalanceAfter = await wsteth.balanceOf(user) + assert.equals(wstETHBalanceAfter, wstETHBalanceBefore.sub(bn(requests[0])).sub(bn(requests[1]))) + }) + + it('uses sender address as owner if zero passed', async () => { + await wsteth.mint(user, ETH(1)) + await steth.mintShares(wsteth.address, shares(1)) + await steth.mintShares(user, shares(1)) + await wsteth.approve(withdrawalQueue.address, ETH(1), { from: user }) + + const tx = await withdrawalQueue.requestWithdrawalsWstETH([ETH(1)], ZERO_ADDRESS, { from: user }) + + assert.emits(tx, 'WithdrawalRequested', { + requestId: 1, + requestor: user.toLowerCase(), + owner: user.toLowerCase(), + amountOfStETH: await steth.getPooledEthByShares(ETH(1)), + amountOfShares: shares(1), + }) + }) + }) + + context('requestWithdrawalsWstETHWithPermit()', () => { + const [alice] = ACCOUNTS_AND_KEYS + it('works correctly with non empty payload', async () => { + await wsteth.mint(user, ETH(100)) + await steth.mintShares(wsteth.address, shares(100)) + await steth.mintShares(user, shares(100)) + await wsteth.approve(withdrawalQueue.address, ETH(300), { from: user }) + await impersonate(ethers.provider, alice.address) + await web3.eth.sendTransaction({ to: alice.address, from: user, value: ETH(1) }) + await wsteth.transfer(alice.address, ETH(100), { from: user }) + + const requests = [] + + const withdrawalRequestsCount = 5 + for (let i = 0; i < withdrawalRequestsCount; ++i) { + requests.push(ETH(10)) + } + + const amount = bn(ETH(10)).mul(bn(withdrawalRequestsCount)) + const chainId = await wsteth.getChainId() + const deadline = MAX_UINT256 + const domainSeparator = makeDomainSeparator('Wrapped liquid staked Ether 2.0', '1', chainId, wsteth.address) + const { v, r, s } = signPermit( + alice.address, + withdrawalQueue.address, + amount, // amount + 0, // nonce + deadline, + domainSeparator, + alice.key + ) + const permission = [ + amount, + deadline, // deadline + v, + r, + s, + ] + + const aliceBalancesBefore = await wsteth.balanceOf(alice.address) + const lastRequestIdBefore = await withdrawalQueue.getLastRequestId() + await withdrawalQueue.requestWithdrawalsWstETHWithPermit(requests, owner, permission, { from: alice.address }) + assert.equals(await withdrawalQueue.getLastRequestId(), lastRequestIdBefore.add(bn(requests.length))) + const aliceBalancesAfter = await wsteth.balanceOf(alice.address) + assert.equals(aliceBalancesAfter, aliceBalancesBefore.sub(bn(ETH(10)).mul(bn(withdrawalRequestsCount)))) + }) + }) + context('requestWithdrawalsWithPermit()', () => { const [alice] = ACCOUNTS_AND_KEYS it('works correctly with non empty payload', async () => { diff --git a/test/0.8.9/withdrawal-request-nft.test.js b/test/0.8.9/withdrawal-request-nft.test.js index a9a9b87ec..03c52db4a 100644 --- a/test/0.8.9/withdrawal-request-nft.test.js +++ b/test/0.8.9/withdrawal-request-nft.test.js @@ -7,11 +7,12 @@ const { shares, ETH, shareRate } = require('../helpers/utils') const withdrawals = require('../helpers/withdrawals') const StETH = artifacts.require('StETHMock') +const WstETH = artifacts.require('WstETHMock') const ERC721ReceiverMock = artifacts.require('ERC721ReceiverMock') contract('WithdrawalNFT', (addresses) => { const [deployer, stEthHolder, nftHolderStETH, recipient, stranger] = addresses - let withdrawalQueueERC721, stETH, erc721ReceiverMock + let withdrawalQueueERC721, stETH, wstETH, erc721ReceiverMock let nftHolderStETHTokenIds, nonExistedTokenId const snapshot = new EvmSnapshot(ethers.provider) @@ -19,11 +20,14 @@ contract('WithdrawalNFT', (addresses) => { stETH = await StETH.new({ value: ETH(1), from: deployer }) await setBalance(stETH.address, ETH(100)) + wstETH = await WstETH.new(stETH.address, { from: deployer }) erc721ReceiverMock = await ERC721ReceiverMock.new({ from: deployer }) - withdrawalQueueERC721 = (await withdrawals.deploy(deployer, stETH.address, 'Lido TEST Request', 'unstEsT')).queue + withdrawalQueueERC721 = (await withdrawals.deploy(deployer, wstETH.address, 'Lido TEST Request', 'unstEsT')).queue await withdrawalQueueERC721.initialize(deployer) + await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.PAUSE_ROLE(), deployer) await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.RESUME_ROLE(), deployer) await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.FINALIZE_ROLE(), deployer) + await withdrawalQueueERC721.grantRole(await withdrawalQueueERC721.ORACLE_ROLE(), deployer) await withdrawalQueueERC721.resume({ from: deployer }) await stETH.setTotalPooledEther(ETH(101)) diff --git a/test/helpers/factories.js b/test/helpers/factories.js index 9b356a8ef..c080ddb22 100644 --- a/test/helpers/factories.js +++ b/test/helpers/factories.js @@ -255,8 +255,8 @@ async function elRewardsVaultFactory({ pool, treasury }) { return await LidoExecutionLayerRewardsVault.new(pool.address, treasury.address) } -async function withdrawalQueueFactory({ appManager, oracle, pool }) { - const withdrawalQueue = (await withdrawals.deploy(appManager.address, pool.address)).queue +async function withdrawalQueueFactory({ appManager, pool, oracle, wsteth }) { + const withdrawalQueue = (await withdrawals.deploy(appManager.address, wsteth.address)).queue await withdrawalQueue.initialize(appManager.address) diff --git a/test/helpers/withdrawals.js b/test/helpers/withdrawals.js index 1c4bc53bf..0413bd2f5 100644 --- a/test/helpers/withdrawals.js +++ b/test/helpers/withdrawals.js @@ -3,8 +3,8 @@ const { artifacts } = require('hardhat') const OssifiableProxy = artifacts.require('OssifiableProxy.sol') const WithdrawalQueueERC721 = artifacts.require('WithdrawalQueueERC721Mock.sol') -async function deploy(ownerAddress, stethAddress, name = 'Lido: Withdrawal Request NFT', symbol = 'unstETH') { - const impl = await WithdrawalQueueERC721.new(stethAddress, name, symbol) +async function deploy(ownerAddress, wstethAddress, name = 'Lido: Withdrawal Request NFT', symbol = 'unstETH') { + const impl = await WithdrawalQueueERC721.new(wstethAddress, name, symbol) const proxy = await OssifiableProxy.new(impl.address, ownerAddress, '0x') const queue = await WithdrawalQueueERC721.at(proxy.address) diff --git a/test/scenario/helpers/deploy.js b/test/scenario/helpers/deploy.js index 52a9bb416..633bd0c27 100644 --- a/test/scenario/helpers/deploy.js +++ b/test/scenario/helpers/deploy.js @@ -4,6 +4,7 @@ const withdrawals = require('../../helpers/withdrawals') const { newDao, newApp } = require('../../0.4.24/helpers/dao') const Lido = artifacts.require('LidoMock.sol') +const WstETH = artifacts.require('WstETH.sol') const LidoELRewardsVault = artifacts.require('LidoExecutionLayerRewardsVault.sol') const NodeOperatorsRegistry = artifacts.require('NodeOperatorsRegistry') const OracleMock = artifacts.require('AccountingOracleMock.sol') @@ -131,7 +132,8 @@ async function deployDaoAndPool(appManager, voting) { const eip712StETH = await EIP712StETH.new({ from: appManager }) - const withdrawalQueue = (await withdrawals.deploy(appManager, pool.address)).queue + const wsteth = await WstETH.new(pool.address) + const withdrawalQueue = (await withdrawals.deploy(appManager, wsteth.address)).queue await pool.initialize( oracleMock.address, From 6887eca29554de1264ee7bf02a6e745b872a5fd4 Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 9 Mar 2023 16:31:23 +0400 Subject: [PATCH 209/236] Fix _invalidateReadyToDepositKeysRange summary accounting --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 33 +++++----- .../NodeOperatorsRegistryMock.sol | 16 ++--- test/0.4.24/node-operators-registry.test.js | 65 +++++++------------ 3 files changed, 46 insertions(+), 68 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index b177856ec..437d1ce96 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -221,7 +221,7 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { uint256 totalOperators = getNodeOperatorsCount(); Packed64x4.Packed memory signingKeysStats; Packed64x4.Packed memory operatorTargetStats; - Packed64x4.Packed memory summarySigningKeysStats = _loadSummarySigningKeysStats(); + Packed64x4.Packed memory summarySigningKeysStats = Packed64x4.Packed(0); uint64 vettedSigningKeysCountBefore; uint64 totalSigningKeysCount; uint64 depositedSigningKeysCount; @@ -693,31 +693,32 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { function _invalidateReadyToDepositKeysRange(uint256 _indexFrom, uint256 _indexTo) internal { _requireValidRange(_indexFrom <= _indexTo && _indexTo < getNodeOperatorsCount()); - uint64 trimmedKeysCount; - uint64 totalTrimmedKeysCount; - Packed64x4.Packed memory signingKeysStats; + Packed64x4.Packed memory summarySigningKeysStats = _loadSummarySigningKeysStats(); + uint64 summaryTotalKeysCount = summarySigningKeysStats.get(SUMMARY_TOTAL_KEYS_COUNT_OFFSET); + uint64 summaryDepositedKeysCount = summarySigningKeysStats.get(SUMMARY_DEPOSITED_KEYS_COUNT_OFFSET); + + if (summaryTotalKeysCount == summaryDepositedKeysCount) return; + + summarySigningKeysStats.set(SUMMARY_TOTAL_KEYS_COUNT_OFFSET, summaryDepositedKeysCount); + summarySigningKeysStats.set(SUMMARY_MAX_VALIDATORS_COUNT_OFFSET, summaryDepositedKeysCount); + _saveSummarySigningKeysStats(summarySigningKeysStats); + _increaseValidatorsKeysNonce(); + Packed64x4.Packed memory signingKeysStats; for (uint256 nodeOperatorId = _indexFrom; nodeOperatorId <= _indexTo; ++nodeOperatorId) { signingKeysStats = _loadOperatorSigningKeysStats(nodeOperatorId); - uint64 depositedSigningKeysCount = signingKeysStats.get(DEPOSITED_KEYS_COUNT_OFFSET); - trimmedKeysCount = signingKeysStats.get(TOTAL_KEYS_COUNT_OFFSET) - depositedSigningKeysCount; - if (trimmedKeysCount == 0) continue; - totalTrimmedKeysCount += trimmedKeysCount; + uint64 totalSigningKeysCount = signingKeysStats.get(TOTAL_KEYS_COUNT_OFFSET); + + if (depositedSigningKeysCount == totalSigningKeysCount) continue; signingKeysStats.set(TOTAL_KEYS_COUNT_OFFSET, depositedSigningKeysCount); signingKeysStats.set(VETTED_KEYS_COUNT_OFFSET, depositedSigningKeysCount); _saveOperatorSigningKeysStats(nodeOperatorId, signingKeysStats); - - _updateSummaryMaxValidatorsCount(nodeOperatorId); - + _applyNodeOperatorLimits(nodeOperatorId); emit TotalSigningKeysCountChanged(nodeOperatorId, depositedSigningKeysCount); emit VettedSigningKeysCountChanged(nodeOperatorId, depositedSigningKeysCount); - emit NodeOperatorTotalKeysTrimmed(nodeOperatorId, trimmedKeysCount); - } - - if (totalTrimmedKeysCount > 0) { - _increaseValidatorsKeysNonce(); + emit NodeOperatorTotalKeysTrimmed(nodeOperatorId, totalSigningKeysCount - depositedSigningKeysCount); } } diff --git a/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol b/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol index 82b02a9c5..c8a313d26 100644 --- a/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol +++ b/contracts/0.4.24/test_helpers/NodeOperatorsRegistryMock.sol @@ -127,20 +127,16 @@ contract NodeOperatorsRegistryMock is NodeOperatorsRegistry { view returns ( uint256 totalSigningKeysCount, - uint256 vettedSigningKeysCount, + uint256 maxValidatorsCount, uint256 depositedSigningKeysCount, uint256 exitedSigningKeysCount ) { - uint256 nodeOperatorsCount = getNodeOperatorsCount(); - Packed64x4.Packed memory signingKeysStats; - for (uint i; i < nodeOperatorsCount; i++) { - signingKeysStats = _loadOperatorSigningKeysStats(i); - totalSigningKeysCount += signingKeysStats.get(TOTAL_KEYS_COUNT_OFFSET); - vettedSigningKeysCount += signingKeysStats.get(VETTED_KEYS_COUNT_OFFSET); - depositedSigningKeysCount += signingKeysStats.get(DEPOSITED_KEYS_COUNT_OFFSET); - exitedSigningKeysCount += signingKeysStats.get(EXITED_KEYS_COUNT_OFFSET); - } + Packed64x4.Packed memory summarySigningKeysStats = _loadSummarySigningKeysStats(); + totalSigningKeysCount = summarySigningKeysStats.get(SUMMARY_TOTAL_KEYS_COUNT_OFFSET); + maxValidatorsCount = summarySigningKeysStats.get(SUMMARY_MAX_VALIDATORS_COUNT_OFFSET); + depositedSigningKeysCount = summarySigningKeysStats.get(SUMMARY_DEPOSITED_KEYS_COUNT_OFFSET); + exitedSigningKeysCount = summarySigningKeysStats.get(SUMMARY_EXITED_KEYS_COUNT_OFFSET); } function testing_setBaseVersion(uint256 _newBaseVersion) external { diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index 1070b5e64..cb02fe719 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -237,7 +237,7 @@ contract('NodeOperatorsRegistry', (addresses) => { const exitedSigningKeysCount = NODE_OPERATORS.reduce((sum, c) => sum + c.exitedSigningKeysCount, 0) assert.equals(totalSigningKeysStatsAfter.totalSigningKeysCount.toNumber(), totalSigningKeysCount) - assert.equals(totalSigningKeysStatsAfter.vettedSigningKeysCount.toNumber(), vettedSigningKeysCount) + assert.equals(totalSigningKeysStatsAfter.maxValidatorsCount.toNumber(), vettedSigningKeysCount) assert.equals(totalSigningKeysStatsAfter.depositedSigningKeysCount.toNumber(), depositedSigningKeysCount) assert.equals(totalSigningKeysStatsAfter.exitedSigningKeysCount.toNumber(), exitedSigningKeysCount) }) @@ -1026,16 +1026,16 @@ contract('NodeOperatorsRegistry', (addresses) => { }) it('reduces total vetted validator keys count correctly if new value less than previous', async () => { - const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 30, { from: limitsManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysCountAfter.toNumber(), 20) }) it('increases total vetted validator keys count correctly if new value greater than previous', async () => { - const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.setNodeOperatorStakingLimit(firstNodeOperatorId, 100, { from: limitsManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter.toNumber() - vettedSigningKeysCountBefore.toNumber(), 50) }) @@ -1624,10 +1624,10 @@ contract('NodeOperatorsRegistry', (addresses) => { } }) - it('sets total vetted signing keys count & total signing keys count values to deposited signing keys count', async () => { + it('sets total max validators count & total validators count values to deposited validators count', async () => { const totalSigningKeysStatsBefore = await app.testing_getTotalSigningKeysStats() assert.notEquals( - totalSigningKeysStatsBefore.vettedSigningKeysCount, + totalSigningKeysStatsBefore.maxValidatorsCount, totalSigningKeysStatsBefore.depositedSigningKeysCount ) assert.notEquals( @@ -1637,7 +1637,7 @@ contract('NodeOperatorsRegistry', (addresses) => { await app.onWithdrawalCredentialsChanged({ from: stakingRouter }) const totalSigningKeysStatsAfter = await app.testing_getTotalSigningKeysStats() assert.equals( - totalSigningKeysStatsAfter.vettedSigningKeysCount, + totalSigningKeysStatsAfter.maxValidatorsCount, totalSigningKeysStatsBefore.depositedSigningKeysCount ) assert.equals( @@ -2669,9 +2669,9 @@ contract('NodeOperatorsRegistry', (addresses) => { it('correctly decreases global vetted signing keys 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 { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex assert.equals( vettedSigningKeysCountAfter.toNumber(), @@ -2679,55 +2679,36 @@ contract('NodeOperatorsRegistry', (addresses) => { ) }) - it.skip('correctly decreases global vetted signing keys and totalTargetStats count if key index is less then vetted keys counter of node operator', async () => { + it('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() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex assert.equals( vettedSigningKeysCountAfter.toNumber(), vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysDecrement ) - - const { - isTargetLimitActive: isTargetLimitActiveAfter, - targetValidatorsCount: targetValidatorsCountAfter, - excessValidatorsCount: excessValidatorsCountAfter, - } = await app.testing_getTotalTargetStats() - - assert.equals(isTargetLimitActiveAfter, isTargetLimitActiveBefore) - assert.equals( - targetValidatorsCountAfter, - targetValidatorsCountBefore.toNumber() - vettedSigningKeysCountBefore.toNumber() - vettedSigningKeysDecrement - ) - assert.equals(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 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) it("doesn't modify global vetted signing keys count if key index is greater than vettedSigningKeysCount", async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount + 1 assert.isTrue(keyIndex <= NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount) - const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.removeSigningKey(secondNodeOperatorId, keyIndex, { from: signingKeysManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) @@ -3033,9 +3014,9 @@ contract('NodeOperatorsRegistry', (addresses) => { it('correctly decreases global vetted signing keys count if fromIndex is less then vetted keys counter of node operator', async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - 1 const keysCount = 2 - const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() const vettedSigningKeysDecrement = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount - keyIndex assert.equals( vettedSigningKeysCountAfter.toNumber(), @@ -3046,18 +3027,18 @@ contract('NodeOperatorsRegistry', (addresses) => { it("doesn't modify global vetted signing keys count if fromIndex is equal to vettedSigningKeysCount", async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount const keysCount = NODE_OPERATORS[secondNodeOperatorId].totalSigningKeysCount - keyIndex - 1 - const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) it("doesn't modify global vetted signing keys count if fromIndex is greater than vettedSigningKeysCount", async () => { const keyIndex = NODE_OPERATORS[secondNodeOperatorId].vettedSigningKeysCount + 1 const keysCount = 1 - const { vettedSigningKeysCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountBefore } = await app.testing_getTotalSigningKeysStats() await app.removeSigningKeys(secondNodeOperatorId, keyIndex, keysCount, { from: signingKeysManager }) - const { vettedSigningKeysCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() + const { maxValidatorsCount: vettedSigningKeysCountAfter } = await app.testing_getTotalSigningKeysStats() assert.equals(vettedSigningKeysCountAfter, vettedSigningKeysCountBefore) }) From 563dfffae8ee591dbbafc247f2811d8acc305f55 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 14:55:43 +0200 Subject: [PATCH 210/236] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F:=20refactor=20wq?= =?UTF-8?q?=20`calculateFinalizationBatches`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 94 ++++++++++--------- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- ...drawal-queue-requests-finalization.test.js | 20 ++-- ...ithdrawal-queue-share-rate-changes.test.js | 30 ++++-- 6 files changed, 83 insertions(+), 67 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 060c76173..f44c5f9a3 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -20,10 +20,8 @@ abstract contract WithdrawalQueueBase { /// @notice precision base for share rate and discounting factor values in the contract uint256 internal constant E27_PRECISION_BASE = 1e27; - + /// @dev maximal length of the batches array that oracle should deliver on finalization uint256 internal constant MAX_BATCHES_LENGTH = 36; - uint256 internal constant MAX_REQUESTS_PER_CALL = 1000; - /// @dev return value for the `find...` methods in case of no result uint256 internal constant NOT_FOUND = 0; @@ -177,19 +175,21 @@ abstract contract WithdrawalQueueBase { /// @notice transient state that is used to pass intemediate results between several `calculateFinalizationBatches` // invokations - struct CalcState { + struct BatchesCalculationState { /// @notice amount of ether available in the protocol that can be used to finalize withdrawal requests /// Will decrease on each invokation and will be equal to the remainder when calculation is finished /// Should be set before the first invokation - uint256 ethBudget; + uint256 remainingEthBudget; /// @notice flag that is `true` if returned state is final and `false` if more invokations required bool finished; - /// @notice contains finalization batches once calculation is finished. Can't be used if finished is false. - uint256[] batches; + /// @notice static array to store all the batches ending request id + uint256[MAX_BATCHES_LENGTH] batches; + /// @notice length of the filled part of `batches` array + uint256 batchesLength; } - /// Offchain view for the oracle daemon that calculates how many requests can be finalized within the given budget - /// and timestamp and share rate limits. Returned requests are split into the batches. + /// @notice Offchain view for the oracle daemon that calculates how many requests can be finalized within + /// the given budget and timestamp and share rate limits. Returned requests are split into the batches. /// Each batch consist of the requests that all have the share rate below the `_maxShareRate` or above it. /// Below you can see an example how 14 requests with different share rates will be split into 5 batches by /// this algorithm @@ -206,39 +206,46 @@ abstract contract WithdrawalQueueBase { /// /// @param _maxShareRate current share rate of the protocol with 1e27 precision /// @param _maxTimestamp max timestamp of the request that can be finalized + /// @param _maxRequestsPerCall max request number that can be processed by the call. Better to me max possible + /// number for EL node to handle before hitting `out of gas`. More this number is less calls it will require to + /// calculate the result /// @param _state structure that accumulates the state across multiple invokations to overcome gas limits. - /// To start calculation you should pass `state.ethBudget` and `state.finished == false` and then invoke + /// To start calculation you should pass `state.remainingEthBudget` and `state.finished == false` and then invoke /// the function with returned `state` until it returns a state with `finished` flag set - /// @return state state that was changed dring this function invokation. - /// If (state.finished) than calculation is finished and you can use state.batches is ready to be used - function calculateFinalizationBatches(uint256 _maxShareRate, uint256 _maxTimestamp, CalcState memory _state) + /// @return state that was changed during this function invokation. + /// If (state.finished) than calculation is finished and returned `state` is ready to be used + function calculateFinalizationBatches( + uint256 _maxShareRate, + uint256 _maxTimestamp, + uint256 _maxRequestsPerCall, + BatchesCalculationState memory _state + ) external view - returns (CalcState memory state) + returns (BatchesCalculationState memory) { - if (_state.finished || _state.ethBudget == 0) revert InvalidState(); + if (_state.finished || _state.remainingEthBudget == 0) revert InvalidState(); - uint256 lastRequestId = getLastRequestId(); + uint256 currentId; + WithdrawalRequest memory prevRequest; + uint256 prevRequestShareRate; - uint256 start; - uint256 prevShareRate; + if (_state.batchesLength == 0) { + currentId = getLastFinalizedRequestId() + 1; - uint256 batchesLength; - if (_state.batches.length == 0) { - start = getLastFinalizedRequestId() + 1; - // we'll store batches as a array where [MAX_BATCHES_LENGTH] element is the array's length - _state.batches = new uint256[](MAX_BATCHES_LENGTH + 1); + prevRequest = _getQueue()[currentId - 1]; } else { - batchesLength = _state.batches[MAX_BATCHES_LENGTH]; - uint256 lastHandledRequestId = _state.batches[batchesLength - 1]; + uint256 lastHandledRequestId = _state.batches[_state.batchesLength - 1]; + currentId = lastHandledRequestId + 1; - start = lastHandledRequestId + 1; - (prevShareRate,,) = _calcBatch(_getQueue()[lastHandledRequestId - 1], _getQueue()[lastHandledRequestId]); + prevRequest = _getQueue()[lastHandledRequestId]; + (prevRequestShareRate,,) = _calcBatch(_getQueue()[lastHandledRequestId - 1], prevRequest); } - uint256 currentId = start; - WithdrawalRequest memory prevRequest = _getQueue()[currentId - 1]; - while (currentId <= lastRequestId && currentId < start + MAX_REQUESTS_PER_CALL) { + uint256 nextCallRequestId = currentId + _maxRequestsPerCall; + uint256 queueLength = getLastRequestId() + 1; + + while (currentId < queueLength || currentId < nextCallRequestId) { WithdrawalRequest memory request = _getQueue()[currentId]; if (request.timestamp > _maxTimestamp) break; // max timestamp break @@ -250,43 +257,40 @@ abstract contract WithdrawalQueueBase { ethToFinalize = (shares * _maxShareRate) / E27_PRECISION_BASE; } - if (ethToFinalize > _state.ethBudget) break; // budget break - _state.ethBudget -= ethToFinalize; + if (ethToFinalize > _state.remainingEthBudget) break; // budget break + _state.remainingEthBudget -= ethToFinalize; - if (batchesLength != 0 && ( + if (_state.batchesLength != 0 && ( // share rate of requests in the same batch can differ by 1-2 wei because of the rounding error // (issue: https://github.com/lidofinance/lido-dao/issues/442 ) // so we're counting requests that are placed during the same report day // as equal even if their actual share rate are different prevRequest.reportTimestamp == request.reportTimestamp || // both requests are below or - prevShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || + prevRequestShareRate <= _maxShareRate && requestShareRate <= _maxShareRate || // both are above the line - prevShareRate > _maxShareRate && requestShareRate > _maxShareRate + prevRequestShareRate > _maxShareRate && requestShareRate > _maxShareRate )) { - _state.batches[batchesLength - 1] = currentId; // extend the last batch + _state.batches[_state.batchesLength - 1] = currentId; // extend the last batch } else { // to be able to check batches on-chain we need it to have fixed max length - if (batchesLength == MAX_BATCHES_LENGTH) break; + if (_state.batchesLength == MAX_BATCHES_LENGTH) break; // create a new batch - _state.batches[batchesLength] = currentId; - batchesLength = ++_state.batches[MAX_BATCHES_LENGTH]; + _state.batches[_state.batchesLength] = currentId; + ++_state.batchesLength; } - prevShareRate = requestShareRate; + prevRequestShareRate = requestShareRate; prevRequest = request; unchecked{ ++currentId; } } - _state.finished = currentId < start + MAX_REQUESTS_PER_CALL || currentId == lastRequestId + 1; - - if (_state.finished) { - MemUtils.trimUint256Array(_state.batches, _state.batches.length - batchesLength); - } + _state.finished = currentId == queueLength || currentId < nextCallRequestId; return _state; } + /// @notice Checks the finalization batches, calculates required ether and the amount of shares to burn and /// @param _batches finalization batches calculated offchain using `calculateFinalizationBatches` /// @param _maxShareRate max possible share rate that will be used for request finalization with 1e27 precision diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index d6edf91d9..b2e6a347c 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index 74c901e63..620a19ec4 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index b6807e970..a838dfd28 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"ethBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[]","name":"batches","type":"uint256[]"}],"internalType":"struct WithdrawalQueueBase.CalcState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file diff --git a/test/0.8.9/withdrawal-queue-requests-finalization.test.js b/test/0.8.9/withdrawal-queue-requests-finalization.test.js index a382ba48f..494dd9d05 100644 --- a/test/0.8.9/withdrawal-queue-requests-finalization.test.js +++ b/test/0.8.9/withdrawal-queue-requests-finalization.test.js @@ -21,21 +21,23 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, } const finalizeRequests = async ({ finalizationShareRate, maxTimeStamp, budget, expectedBatches }) => { - const calculatedBatches = await withdrawalQueue.calculateFinalizationBatches(finalizationShareRate, maxTimeStamp, [ - budget, - false, - [], - ]) + const calculatedBatches = await withdrawalQueue.calculateFinalizationBatches( + finalizationShareRate, + maxTimeStamp, + 1000, + [budget, false, Array(36).fill(0), 0] + ) assert.isTrue(calculatedBatches.finished) - assert.equalsDelta(calculatedBatches.ethBudget, 0, 2) - assert.equals(calculatedBatches.batches, expectedBatches) + assert.equalsDelta(calculatedBatches.remainingEthBudget, 0, 2) + const batches = calculatedBatches.batches.slice(0, calculatedBatches.batchesLength) + assert.equals(batches, expectedBatches) - const batch = await withdrawalQueue.prefinalize.call(calculatedBatches.batches, finalizationShareRate) + const batch = await withdrawalQueue.prefinalize.call(batches, finalizationShareRate) assert.equalsDelta(batch.ethToLock, budget, 2) - await withdrawalQueue.finalize(calculatedBatches.batches, finalizationShareRate, { + await withdrawalQueue.finalize(batches, finalizationShareRate, { from: daoAgent, value: batch.ethToLock, }) diff --git a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js index c49716ff7..606c64e07 100644 --- a/test/0.8.9/withdrawal-queue-share-rate-changes.test.js +++ b/test/0.8.9/withdrawal-queue-share-rate-changes.test.js @@ -79,15 +79,20 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user, oracle]) => { let batches it(`both requests can be finalized with 2 ETH`, async () => { - const result = await queue.calculateFinalizationBatches(e27(1), MAX_UINT256, [e18(2), false, []]) + const result = await queue.calculateFinalizationBatches(e27(1), MAX_UINT256, 1000, [ + e18(2), + false, + Array(36).fill(0), + 0, + ]) assert.isTrue(result.finished) - assert.equals(result.batches, [1, 2]) + assert.equals(result.batchesLength, 2) + batches = result.batches.slice(0, result.batchesLength) + assert.equals(batches, [1, 2]) - const batch = await queue.prefinalize.call(result.batches, e27(1)) + const batch = await queue.prefinalize.call(batches, e27(1)) assert.equals(batch.ethToLock, e18(2)) assert.equals(batch.sharesToBurn, e18(2)) - - batches = result.batches }) let claimableEther @@ -145,15 +150,20 @@ contract('WithdrawalQueue', ([owner, daoAgent, finalizer, user, oracle]) => { const maxShareRate = e27(1.5) it(`both requests can be finalized with 2 ETH`, async () => { - const result = await queue.calculateFinalizationBatches(maxShareRate, MAX_UINT256, [e18(2.5), false, []]) + const result = await queue.calculateFinalizationBatches(maxShareRate, MAX_UINT256, 1000, [ + e18(2.5), + false, + Array(36).fill(0), + 0, + ]) assert.isTrue(result.finished) - assert.equals(result.batches, [1, 2]) + assert.equals(result.batchesLength, 2) + batches = result.batches.slice(0, result.batchesLength) + assert.equals(batches, [1, 2]) - const batch = await queue.prefinalize.call(result.batches, maxShareRate) + const batch = await queue.prefinalize.call(batches, maxShareRate) assert.equals(batch.ethToLock, e18(2.5)) assert.equals(batch.sharesToBurn, e18(2)) - - batches = result.batches }) let claimableEther From fbb3195ac2815066efe84cdab03434e8869300ac Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 9 Mar 2023 17:02:43 +0400 Subject: [PATCH 211/236] Fix _invalidateReadyToDepositKeysRange for node operators range --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 437d1ce96..0d32e63e4 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -693,32 +693,37 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { function _invalidateReadyToDepositKeysRange(uint256 _indexFrom, uint256 _indexTo) internal { _requireValidRange(_indexFrom <= _indexTo && _indexTo < getNodeOperatorsCount()); - Packed64x4.Packed memory summarySigningKeysStats = _loadSummarySigningKeysStats(); - uint64 summaryTotalKeysCount = summarySigningKeysStats.get(SUMMARY_TOTAL_KEYS_COUNT_OFFSET); - uint64 summaryDepositedKeysCount = summarySigningKeysStats.get(SUMMARY_DEPOSITED_KEYS_COUNT_OFFSET); - - if (summaryTotalKeysCount == summaryDepositedKeysCount) return; - - summarySigningKeysStats.set(SUMMARY_TOTAL_KEYS_COUNT_OFFSET, summaryDepositedKeysCount); - summarySigningKeysStats.set(SUMMARY_MAX_VALIDATORS_COUNT_OFFSET, summaryDepositedKeysCount); - _saveSummarySigningKeysStats(summarySigningKeysStats); - _increaseValidatorsKeysNonce(); - + uint64 trimmedKeysCount; + uint64 totalTrimmedKeysCount; Packed64x4.Packed memory signingKeysStats; + for (uint256 nodeOperatorId = _indexFrom; nodeOperatorId <= _indexTo; ++nodeOperatorId) { signingKeysStats = _loadOperatorSigningKeysStats(nodeOperatorId); - uint64 depositedSigningKeysCount = signingKeysStats.get(DEPOSITED_KEYS_COUNT_OFFSET); - uint64 totalSigningKeysCount = signingKeysStats.get(TOTAL_KEYS_COUNT_OFFSET); - if (depositedSigningKeysCount == totalSigningKeysCount) continue; + uint64 depositedSigningKeysCount = signingKeysStats.get(DEPOSITED_KEYS_COUNT_OFFSET); + trimmedKeysCount = signingKeysStats.get(TOTAL_KEYS_COUNT_OFFSET) - depositedSigningKeysCount; + if (trimmedKeysCount == 0) continue; + totalTrimmedKeysCount += trimmedKeysCount; signingKeysStats.set(TOTAL_KEYS_COUNT_OFFSET, depositedSigningKeysCount); signingKeysStats.set(VETTED_KEYS_COUNT_OFFSET, depositedSigningKeysCount); _saveOperatorSigningKeysStats(nodeOperatorId, signingKeysStats); - _applyNodeOperatorLimits(nodeOperatorId); + + _updateSummaryMaxValidatorsCount(nodeOperatorId); + emit TotalSigningKeysCountChanged(nodeOperatorId, depositedSigningKeysCount); emit VettedSigningKeysCountChanged(nodeOperatorId, depositedSigningKeysCount); - emit NodeOperatorTotalKeysTrimmed(nodeOperatorId, totalSigningKeysCount - depositedSigningKeysCount); + emit NodeOperatorTotalKeysTrimmed(nodeOperatorId, trimmedKeysCount); + } + + if (totalTrimmedKeysCount > 0) { + Packed64x4.Packed memory summarySigningKeysStats = _loadSummarySigningKeysStats(); + summarySigningKeysStats.set( + SUMMARY_TOTAL_KEYS_COUNT_OFFSET, + summarySigningKeysStats.get(SUMMARY_TOTAL_KEYS_COUNT_OFFSET) - totalTrimmedKeysCount + ); + _saveSummarySigningKeysStats(summarySigningKeysStats); + _increaseValidatorsKeysNonce(); } } From aa7d9f4e29941b84496e9a6434b56ea46c658c5a Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 15:06:23 +0200 Subject: [PATCH 212/236] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F:=20remove=20batch?= =?UTF-8?q?=20checks=20from=20prefinalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 14 ++------------ lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index f44c5f9a3..4798b19eb 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -105,7 +105,7 @@ abstract contract WithdrawalQueueBase { error InvalidRequestId(uint256 _requestId); error InvalidRequestIdRange(uint256 startId, uint256 endId); error InvalidState(); - error InvalidBatch(uint256 index); + error BatchesAreNotSorted(); error EmptyBatches(); error RequestNotFoundOrNotFinalized(uint256 _requestId); error NotEnoughEther(); @@ -310,23 +310,14 @@ abstract contract WithdrawalQueueBase { uint256 currentBatchIndex; uint256 prevBatchEndRequestId = getLastFinalizedRequestId(); WithdrawalRequest memory prevBatchEnd = _getQueue()[prevBatchEndRequestId]; - uint256 prevBatchShareRate; while (currentBatchIndex < _batches.length) { uint256 batchEndRequestId = _batches[currentBatchIndex]; - if (batchEndRequestId <= prevBatchEndRequestId) revert InvalidBatch(currentBatchIndex); + if (batchEndRequestId <= prevBatchEndRequestId) revert BatchesAreNotSorted(); WithdrawalRequest memory batchEnd = _getQueue()[batchEndRequestId]; (uint256 batchShareRate, uint256 stETH, uint256 shares) = _calcBatch(prevBatchEnd, batchEnd); - if (currentBatchIndex > 0) { - // - if shareRate(batch[i]) is below _maxShareRate => shareRate(batch[i+1]) is above and vice versa - // so, we can't have two batches in a row that is below... - if (prevBatchShareRate <= _maxShareRate && batchShareRate <= _maxShareRate) revert InvalidBatch(currentBatchIndex); - // .. or above the line - if (prevBatchShareRate > _maxShareRate && batchShareRate > _maxShareRate) revert InvalidBatch(currentBatchIndex); - } - if (batchShareRate > _maxShareRate) { // discounted ethToLock += shares * _maxShareRate / E27_PRECISION_BASE; @@ -336,7 +327,6 @@ abstract contract WithdrawalQueueBase { } sharesToBurn += shares; - prevBatchShareRate = batchShareRate; prevBatchEndRequestId = batchEndRequestId; prevBatchEnd = batchEnd; unchecked{ ++currentBatchIndex; } diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index b2e6a347c..cd7c17b61 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index 620a19ec4..1d8a9dd6d 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index a838dfd28..fab2a2a63 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.json @@ -1 +1 @@ -[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidBatch","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file +[{"inputs":[{"internalType":"address","name":"_stETH","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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","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":[],"name":"InvalidState","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":[{"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":[],"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file From b121a141c2d97dc77d7ce130e8aad4659d4fe7c1 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 15:13:13 +0200 Subject: [PATCH 213/236] =?UTF-8?q?=F0=9F=A7=B9:=20remove=20forgotten=20im?= =?UTF-8?q?ports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 4798b19eb..62250834a 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -6,8 +6,6 @@ pragma solidity 0.8.9; import "@openzeppelin/contracts-v4.4/utils/structs/EnumerableSet.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; -import {Math} from "./lib/Math.sol"; -import {MemUtils} from "../common/lib/MemUtils.sol"; /// @title Queue to store and manage WithdrawalRequests. /// @dev Use an optimizations to store max share rates for finalized requests heavily inspired From ec0063ce994a061dec272bd2e8a47f77fcc2cbb5 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 15:17:21 +0200 Subject: [PATCH 214/236] test: remove wq test that is not valid now --- test/0.8.9/withdrawal-queue.test.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 7a9ecbaa8..48b084eb0 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -345,20 +345,6 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, ) }) - it('Same discounts is squashed into one', async () => { - await steth.setTotalPooledEther(ETH(900)) - await steth.mintShares(user, shares(1)) - await steth.approve(withdrawalQueue.address, StETH(300), { from: user }) - - await withdrawalQueue.finalize([1], shareRate(10), { from: steth.address, value: ETH(10) }) - assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) - - await withdrawalQueue.requestWithdrawals([amount], owner, { from: user }) - await withdrawalQueue.finalize([2], shareRate(10), { from: steth.address, value: ETH(10) }) - - assert.equals(await withdrawalQueue.getLastCheckpointIndex(), 1) - }) - it('One can finalize a batch of requests at once', async () => { await steth.setTotalPooledEther(ETH(900)) await steth.mintShares(user, shares(1)) From 2e1c66cb3eeec478d03d48ff617e9f5307bd85ca Mon Sep 17 00:00:00 2001 From: Bogdan Kovtun Date: Thu, 9 Mar 2023 17:38:15 +0400 Subject: [PATCH 215/236] Add basic unit tests for invalidateReadyToDepositKeysRange() --- .../0.4.24/nos/NodeOperatorsRegistry.sol | 4 +- test/0.4.24/node-operators-registry.test.js | 90 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol index 0d32e63e4..82153ac11 100644 --- a/contracts/0.4.24/nos/NodeOperatorsRegistry.sol +++ b/contracts/0.4.24/nos/NodeOperatorsRegistry.sol @@ -684,7 +684,9 @@ contract NodeOperatorsRegistry is AragonApp, Versioned { } } - /// @notice Invalidates all unused validators keys for all node operators + /// @notice Invalidates all unused validators keys for node operators in the given range + /// @param _indexFrom the first index (inclusive) of the node operator to invalidate keys for + /// @param _indexTo the last index (inclusive) of the node operator to invalidate keys for function invalidateReadyToDepositKeysRange(uint256 _indexFrom, uint256 _indexTo) external { _auth(MANAGE_NODE_OPERATOR_ROLE); _invalidateReadyToDepositKeysRange(_indexFrom, _indexTo); diff --git a/test/0.4.24/node-operators-registry.test.js b/test/0.4.24/node-operators-registry.test.js index cb02fe719..d9d3e602a 100644 --- a/test/0.4.24/node-operators-registry.test.js +++ b/test/0.4.24/node-operators-registry.test.js @@ -1674,6 +1674,96 @@ contract('NodeOperatorsRegistry', (addresses) => { }) }) + describe('invalidateReadyToDepositKeysRange()', () => { + beforeEach(async () => { + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[0], { from: admin }) + await nodeOperators.addNodeOperator(app, NODE_OPERATORS[1], { from: admin }) + // node operator without unused keys + await nodeOperators.addNodeOperator( + app, + { + ...NODE_OPERATORS[2], + vettedSigningKeysCount: NODE_OPERATORS[2].totalSigningKeysCount, + depositedSigningKeysCount: NODE_OPERATORS[2].totalSigningKeysCount, + }, + { from: admin } + ) + }) + + it('reverts with "APP_AUTH_FAILED" error when called by sender without MANAGE_NODE_OPERATOR_ROLE role', async () => { + const hasPermission = await dao.hasPermission(nobody, app, 'MANAGE_NODE_OPERATOR_ROLE') + assert.isFalse(hasPermission) + const indexFrom = 0 + const indexTo = NODE_OPERATORS.length - 1 + await assert.reverts( + app.invalidateReadyToDepositKeysRange(indexFrom, indexTo, { from: nobody }), + 'APP_AUTH_FAILED' + ) + }) + + it('reverts with "OUT_OF_RANGE" error when called with indexFrom > indexTo', async () => { + const indexFrom = NODE_OPERATORS.length - 1 + const indexTo = 0 + await assert.reverts( + app.invalidateReadyToDepositKeysRange(indexFrom, indexTo, { from: nodeOperatorsManager }), + 'OUT_OF_RANGE' + ) + }) + + it('reverts with "OUT_OF_RANGE" error when called with indexTo >= node operators count', async () => { + const indexFrom = 0 + const indexTo = wei.int(await app.getNodeOperatorsCount()) + await assert.reverts( + app.invalidateReadyToDepositKeysRange(indexFrom, wei.str(indexTo), { from: nodeOperatorsManager }), + 'OUT_OF_RANGE' + ) + await assert.reverts( + app.invalidateReadyToDepositKeysRange(indexFrom, wei.str(indexTo + 1n), { from: nodeOperatorsManager }), + 'OUT_OF_RANGE' + ) + }) + + it('allows invalidate keys for one node operator', async () => { + const nodeOperatorIndex = 1 + const allNodeOperatorsBefore = await nodeOperators.getAllNodeOperators(app) + await app.invalidateReadyToDepositKeysRange(nodeOperatorIndex, nodeOperatorIndex, { from: nodeOperatorsManager }) + const allNodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) + const nodeOperatorBefore = allNodeOperatorsBefore[nodeOperatorIndex] + const nodeOperatorAfter = allNodeOperatorsAfter[nodeOperatorIndex] + assert.equals(nodeOperatorAfter.stakingLimit, nodeOperatorBefore.usedSigningKeys) + assert.equals(nodeOperatorAfter.totalSigningKeys, nodeOperatorBefore.usedSigningKeys) + }) + + it('sets totalSigningKeysCount and vettedSigningKeysCount equal to depositedSigningKeys for each node operator in range', async () => { + const indexFrom = 1 + const indexTo = NODE_OPERATORS.length - 1 + const allNodeOperatorsBefore = await nodeOperators.getAllNodeOperators(app) + await app.invalidateReadyToDepositKeysRange(indexFrom, indexTo, { from: nodeOperatorsManager }) + const allNodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) + for (let i = indexFrom; i <= indexTo; ++i) { + const nodeOperatorBefore = allNodeOperatorsBefore[i] + const nodeOperatorAfter = allNodeOperatorsAfter[i] + assert.equals(nodeOperatorAfter.stakingLimit, nodeOperatorBefore.usedSigningKeys) + assert.equals(nodeOperatorAfter.totalSigningKeys, nodeOperatorBefore.usedSigningKeys) + } + }) + + it("doesn't modify totalSigningKeysCount and vettedSigningKeysCount for all node operators not in range", async () => { + const indexFrom = 2 + const indexTo = NODE_OPERATORS.length - 1 + const allNodeOperatorsBefore = await nodeOperators.getAllNodeOperators(app) + await app.invalidateReadyToDepositKeysRange(indexFrom, indexTo, { from: nodeOperatorsManager }) + const allNodeOperatorsAfter = await nodeOperators.getAllNodeOperators(app) + for (let i = 0; i < indexTo; ++i) { + const nodeOperatorBefore = allNodeOperatorsBefore[i] + const nodeOperatorAfter = allNodeOperatorsAfter[i] + assert.equals(nodeOperatorAfter.stakingLimit, nodeOperatorBefore.stakingLimit) + assert.equals(nodeOperatorAfter.usedSigningKeys, nodeOperatorBefore.usedSigningKeys) + assert.equals(nodeOperatorAfter.totalSigningKeys, nodeOperatorBefore.totalSigningKeys) + } + }) + }) + describe('getSigningKeysAllocationData() with target limit', async () => { const firstNodeOperatorId = 0 const secondNodeOperatorId = 1 From c87d14adf7ff49736ae8a6078179474c62bbcb7a Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 15:43:34 +0200 Subject: [PATCH 216/236] test: fix some wq tests --- test/0.8.9/withdrawal-queue.test.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 48b084eb0..2c5912126 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -436,10 +436,9 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, }) it('works', async () => { - await withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }) - await withdrawalQueue.finalize([1], shareRate(1), { from: steth.address, value: ETH(1) }) + await withdrawalQueue.finalize([1], shareRate(300), { from: steth.address, value: ETH(1) }) - assert.equals(await withdrawalQueue.getClaimableEther([1], [1]), ETH(1)) + assert.almostEqual(await withdrawalQueue.getClaimableEther([1], [1]), ETH(1), 100) }) it('reverts if last hint checkpoint is ahead of requestId', async () => { @@ -874,8 +873,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, ) assert.equal(hints.length, 3) assert.equals(hints[0], 1) - assert.equals(hints[1], 1) - assert.equals(hints[2], 1) + assert.equals(hints[1], 2) + assert.equals(hints[2], 2) }) it('reverts with RequestIdsNotSorted error when request ids not in ascending order', async () => { @@ -916,7 +915,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const secondRequestAmount = ETH(10) await withdrawalQueue.requestWithdrawals([secondRequestAmount], owner, { from: owner }) const secondRequestId = await withdrawalQueue.getLastRequestId() - await withdrawalQueue.finalize([secondRequestId], shareRate(30), { from: steth.address, value: ETH(30) }) + await withdrawalQueue.finalize([secondRequestId], shareRate(300), { from: steth.address, value: ETH(30) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) const tx = await withdrawalQueue.claimWithdrawals([1, 2], [1, 1], { from: owner }) From a17a4e0c6fe766b92580791946be17ed14215acc Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 18:18:04 +0200 Subject: [PATCH 217/236] test: fixes --- test/0.4.24/legacy-oracle.test.js | 2 +- test/0.4.24/lido-handle-oracle-report.test.js | 10 +++++----- .../withdrawal-queue-requests-finalization.test.js | 4 ++-- test/0.8.9/withdrawal-queue.test.js | 2 +- test/helpers/reportData.js | 2 +- .../lido-wq-acct-oracle-integration-gas.test.js | 3 +-- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/test/0.4.24/legacy-oracle.test.js b/test/0.4.24/legacy-oracle.test.js index b248c7bfb..1f1df83b3 100644 --- a/test/0.4.24/legacy-oracle.test.js +++ b/test/0.4.24/legacy-oracle.test.js @@ -34,7 +34,7 @@ const getReportFields = (override = {}) => ({ withdrawalVaultBalance: e18(1), elRewardsVaultBalance: e18(2), sharesRequestedToBurn: e18(3), - lastFinalizableWithdrawalRequestId: 1, + withdrawalFinalizationBatches: [1], simulatedShareRate: e27(1), isBunkerMode: true, extraDataFormat: 0, 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 3f437d921..b432f090d 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -47,7 +47,7 @@ const DEFAULT_LIDO_ORACLE_REPORT = { withdrawalVaultBalance: ETH(0), // uint256, wei elRewardsVaultBalance: ETH(0), // uint256, wei sharesRequestedToBurn: StETH(0), // uint256, wad - lastFinalizableWithdrawalRequestId: 0, // uint256, index + withdrawalFinalizationBatches: [], // uint256, index simulatedShareRate: shareRate(0), // uint256, 10e27 } @@ -2018,7 +2018,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot postCLBalance: ETH(96.1), elRewardsVaultBalance: ETH(0.5), withdrawalVaultBalance: ETH(0.5), - lastFinalizableWithdrawalRequestId: 1, + withdrawalFinalizationBatches: [1], simulatedShareRate: tooLowSimulatedShareRate, }), { from: oracle, gasPrice: 1 } @@ -2038,7 +2038,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot postCLBalance: ETH(96.1), elRewardsVaultBalance: ETH(0.5), withdrawalVaultBalance: ETH(0.5), - lastFinalizableWithdrawalRequestId: 1, + withdrawalFinalizationBatches: [1], simulatedShareRate: tooHighSimulatedShareRate, }), { from: oracle, gasPrice: 1 } @@ -2055,7 +2055,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot postCLBalance: ETH(96.1), elRewardsVaultBalance: ETH(0.5), withdrawalVaultBalance: ETH(0.5), - lastFinalizableWithdrawalRequestId: 1, + withdrawalFinalizationBatches: [1], simulatedShareRate, }), { from: oracle, gasPrice: 1 } @@ -2145,7 +2145,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot elRewardsVaultBalance: ETH(0.25), withdrawalVaultBalance: ETH(0.5), sharesRequestedToBurn: sharesRequestedToBurn.toString(), - lastFinalizableWithdrawalRequestId: 1, + withdrawalFinalizationBatches: [1], simulatedShareRate: simulatedShareRate.toString(), }), { from: oracle, gasPrice: 1 } diff --git a/test/0.8.9/withdrawal-queue-requests-finalization.test.js b/test/0.8.9/withdrawal-queue-requests-finalization.test.js index 494dd9d05..89714a9b5 100644 --- a/test/0.8.9/withdrawal-queue-requests-finalization.test.js +++ b/test/0.8.9/withdrawal-queue-requests-finalization.test.js @@ -8,7 +8,7 @@ const { EvmSnapshot } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') -contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, oracle, anotherUser]) => { +contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { let withdrawalQueue, steth const snapshot = new EvmSnapshot(ethers.provider) @@ -33,7 +33,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const batches = calculatedBatches.batches.slice(0, calculatedBatches.batchesLength) assert.equals(batches, expectedBatches) - const batch = await withdrawalQueue.prefinalize.call(batches, finalizationShareRate) + const batch = await withdrawalQueue.prefinalize(batches, finalizationShareRate) assert.equalsDelta(batch.ethToLock, budget, 2) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 57d27172f..0c726b390 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -78,7 +78,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.pauseFor(100000000, { from: daoAgent }) assert(await withdrawalQueue.isPaused()) await assert.reverts(withdrawalQueue.requestWithdrawals([ETH(1)], owner, { from: user }), 'ResumedExpected()') - await assert.reverts(withdrawalQueue.finalize(1, 0, { from: owner }), 'ResumedExpected()') + await assert.reverts(withdrawalQueue.finalize([1], 0, { from: owner }), 'ResumedExpected()') }) it('cant resume if not paused', async () => { diff --git a/test/helpers/reportData.js b/test/helpers/reportData.js index 1a7cd998f..eb3537fa7 100644 --- a/test/helpers/reportData.js +++ b/test/helpers/reportData.js @@ -29,7 +29,7 @@ function getAccountingReportDataItems(r) { String(r.withdrawalVaultBalance), String(r.elRewardsVaultBalance), String(r.sharesRequestedToBurn), - String(r.withdrawalFinalizationBatches), + r.withdrawalFinalizationBatches.map(String), String(r.simulatedShareRate), r.isBunkerMode, String(r.extraDataFormat), diff --git a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js index 7efdd24e1..1f8331003 100644 --- a/test/scenario/lido-wq-acct-oracle-integration-gas.test.js +++ b/test/scenario/lido-wq-acct-oracle-integration-gas.test.js @@ -170,7 +170,6 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use withdrawalVaultBalance: 0, elRewardsVaultBalance: 0, sharesRequestedToBurn: 0, - lastFinalizableRequestId: 0, } const timestamp = await getSlotTimestamp(+refSlot, consensus) @@ -184,7 +183,7 @@ contract('Lido, AccountingOracle, WithdrawalQueue integration', ([depositor, use oracleReportFields.withdrawalVaultBalance, oracleReportFields.elRewardsVaultBalance, oracleReportFields.sharesRequestedToBurn, - 0, // lastFinalizableRequestId + [], 0, // simulatedShareRate { from: oracle.address } ) From a8bc887dd94c67cd66a9e96a4fee1f566fae86d8 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 18:38:09 +0200 Subject: [PATCH 218/236] =?UTF-8?q?=F0=9F=90=9B:=20fix=20wq=20batch=20calc?= =?UTF-8?q?ulation=20loop=20condition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 62250834a..ce51c5c99 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -6,6 +6,7 @@ pragma solidity 0.8.9; import "@openzeppelin/contracts-v4.4/utils/structs/EnumerableSet.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; +import "hardhat/console.sol"; /// @title Queue to store and manage WithdrawalRequests. /// @dev Use an optimizations to store max share rates for finalized requests heavily inspired @@ -243,7 +244,7 @@ abstract contract WithdrawalQueueBase { uint256 nextCallRequestId = currentId + _maxRequestsPerCall; uint256 queueLength = getLastRequestId() + 1; - while (currentId < queueLength || currentId < nextCallRequestId) { + while (currentId < queueLength && currentId < nextCallRequestId) { WithdrawalRequest memory request = _getQueue()[currentId]; if (request.timestamp > _maxTimestamp) break; // max timestamp break From 4b0170d35342c30d13a01e12eca8a93295a3a66d Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 18:46:05 +0200 Subject: [PATCH 219/236] test: fix another test --- test/0.8.9/withdrawal-queue.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 0c726b390..81b68d0f6 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -566,8 +566,8 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, for (let i = 1; i <= 20; i++) { assert.equals(await withdrawalQueue.getLastCheckpointIndex(), i) await withdrawalQueue.requestWithdrawals([StETH(1)], ZERO_ADDRESS, { from: user }) - const batch = await withdrawalQueue.prefinalize(i + 1, shareRate(i + 1)) - await withdrawalQueue.finalize(i + 1, shareRate(i + 1), { + const batch = await withdrawalQueue.prefinalize([i + 1], shareRate(i + 1)) + await withdrawalQueue.finalize([i + 1], shareRate(i + 1), { from: steth.address, value: batch.ethToLock, }) From de76fd18aa86f441825a594cd480cf7c8c5f0a32 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 9 Mar 2023 21:28:10 +0300 Subject: [PATCH 220/236] fix: revive tests --- test/0.4.24/lido.test.js | 4 ++-- test/0.8.9/oracle/accounting-oracle-deploy.test.js | 3 +++ test/helpers/oracle.js | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index ce0bb9de3..8929dd4df 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -111,8 +111,8 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody }) const pushReport = async (clValidators, clBalance) => { - const elRewards = await web3.eth.getBalance(elRewardsVault.address) - await pushOracleReport(consensus, oracle, clValidators, clBalance, elRewards) + const elRewardsVaultBalance = await web3.eth.getBalance(elRewardsVault.address) + await pushOracleReport(consensus, oracle, clValidators, clBalance, elRewardsVaultBalance) await advanceChainTime(SECONDS_PER_FRAME + 1000) } diff --git a/test/0.8.9/oracle/accounting-oracle-deploy.test.js b/test/0.8.9/oracle/accounting-oracle-deploy.test.js index 91459ef69..1815151c9 100644 --- a/test/0.8.9/oracle/accounting-oracle-deploy.test.js +++ b/test/0.8.9/oracle/accounting-oracle-deploy.test.js @@ -222,6 +222,9 @@ async function configureAccountingOracleSetup({ // this is done as a part of the protocol upgrade voting execution const frameConfig = await consensus.getFrameConfig() + // TODO: Double check it + await consensus.setTimeInEpochs(await legacyOracle.getLastCompletedEpochId()) + const initialEpoch = +(await legacyOracle.getLastCompletedEpochId()) + +frameConfig.epochsPerFrame const updateInitialEpochIx = await consensus.updateInitialEpoch(initialEpoch, { from: admin }) diff --git a/test/helpers/oracle.js b/test/helpers/oracle.js index 1a9d3a8ae..56bfb988d 100644 --- a/test/helpers/oracle.js +++ b/test/helpers/oracle.js @@ -95,8 +95,8 @@ async function reportOracle(consensus, oracle, reportFields) { } // FIXME: kept for compat, remove after refactoring tests -function pushOracleReport(consensus, oracle, numValidators, clBalance, elRewards) { - return reportOracle(consensus, oracle, { numValidators, clBalance, elRewards }) +function pushOracleReport(consensus, oracle, numValidators, clBalance, elRewardsVaultBalance) { + return reportOracle(consensus, oracle, { numValidators, clBalance, elRewardsVaultBalance }) } async function getSecondsPerFrame(consensus) { From 9b188bd7f3fbb54cca2b9f6a8f72cbc979a004e2 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 9 Mar 2023 21:35:18 +0300 Subject: [PATCH 221/236] fix: lido_reward_distribution_math test --- test/scenario/lido_rewards_distribution_math.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/scenario/lido_rewards_distribution_math.test.js b/test/scenario/lido_rewards_distribution_math.test.js index 4fb0ccf27..73d0dee29 100644 --- a/test/scenario/lido_rewards_distribution_math.test.js +++ b/test/scenario/lido_rewards_distribution_math.test.js @@ -69,7 +69,7 @@ contract('Lido: rewards distribution math', (addresses) => { } async function reportBeacon(validatorsCount, balance) { - const receipts = await pushOracleReport(consensus, oracle, validatorsCount, balance) + const receipts = await pushOracleReport(consensus, oracle, validatorsCount, balance, 0) await ethers.provider.send('evm_increaseTime', [SECONDS_PER_FRAME + 1000]) await ethers.provider.send('evm_mine') From 368d737fbd69ba5081bef7bd91ce651d3308716e Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Thu, 9 Mar 2023 21:40:24 +0300 Subject: [PATCH 222/236] fix: revive happy path --- test/scenario/lido_happy_path.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/scenario/lido_happy_path.test.js b/test/scenario/lido_happy_path.test.js index b83bfea19..e1736a53e 100644 --- a/test/scenario/lido_happy_path.test.js +++ b/test/scenario/lido_happy_path.test.js @@ -403,7 +403,7 @@ contract('Lido: happy path', (addresses) => { // Reporting 1.005-fold balance increase (64 => 64.32) to stay in limits - await pushOracleReport(consensus, oracle, 2, ETH(64.32)) + await pushOracleReport(consensus, oracle, 2, ETH(64.32), ETH(0)) // Total shares increased because fee minted (fee shares added) // shares = oldTotalShares + reward * totalFee * oldTotalShares / (newTotalPooledEther - reward * totalFee) From f0b29e1807d82ef4ae8209aadb51039a78d01495 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Thu, 9 Mar 2023 21:30:23 +0200 Subject: [PATCH 223/236] =?UTF-8?q?=F0=9F=A7=B9:=20remove=20unused=20impor?= =?UTF-8?q?t=20in=20wq?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueueBase.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index ce51c5c99..57232329d 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -6,7 +6,6 @@ pragma solidity 0.8.9; import "@openzeppelin/contracts-v4.4/utils/structs/EnumerableSet.sol"; import {UnstructuredStorage} from "./lib/UnstructuredStorage.sol"; -import "hardhat/console.sol"; /// @title Queue to store and manage WithdrawalRequests. /// @dev Use an optimizations to store max share rates for finalized requests heavily inspired From 3973de1ac599f04293f4e7eb05508ad0ccc529fb Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 10 Mar 2023 20:17:31 +0700 Subject: [PATCH 224/236] fix: gasPrice hack for coverage --- test/0.4.24/legacy-oracle.test.js | 7 +++++-- test/0.4.24/lido-handle-oracle-report.test.js | 2 +- ...drawal-queue-requests-finalization.test.js | 19 +++++++++++-------- test/0.8.9/withdrawal-queue.test.js | 3 ++- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/test/0.4.24/legacy-oracle.test.js b/test/0.4.24/legacy-oracle.test.js index 1f1df83b3..700ae3c3a 100644 --- a/test/0.4.24/legacy-oracle.test.js +++ b/test/0.4.24/legacy-oracle.test.js @@ -95,7 +95,7 @@ contract('LegacyOracle', ([admin, stranger]) => { legacyOracle.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7, { from: stranger }), 'SENDER_NOT_ALLOWED' ) - const tx = await legacyOracle.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7, { from: lido.address }) + const tx = await legacyOracle.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7, { from: lido.address, gasPrice: 0 }) assert.emits(tx, 'PostTotalShares', { postTotalPooledEther: 6, preTotalPooledEther: 4, @@ -115,7 +115,10 @@ contract('LegacyOracle', ([admin, stranger]) => { legacyOracle.handleConsensusLayerReport(refSlot, 2, 3, { from: stranger }), 'SENDER_NOT_ALLOWED' ) - const tx = await legacyOracle.handleConsensusLayerReport(refSlot, 2, 3, { from: accountingOracle.address }) + const tx = await legacyOracle.handleConsensusLayerReport(refSlot, 2, 3, { + from: accountingOracle.address, + gasPrice: 0, + }) const epochId = Math.floor((refSlot + 1) / SLOTS_PER_EPOCH) assert.emits(tx, 'Completed', { epochId, 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 b432f090d..6ff1e8a65 100644 --- a/test/0.4.24/lido-handle-oracle-report.test.js +++ b/test/0.4.24/lido-handle-oracle-report.test.js @@ -2167,7 +2167,7 @@ contract('Lido: handleOracleReport', ([appManager, , , , , , bob, stranger, anot // Checking that finalization of the previously placed withdrawal request completed assert.equals(await withdrawalQueue.getLastFinalizedRequestId(), toBN(1)) const strangerBalanceBeforeClaim = await getBalance(stranger) - await withdrawalQueue.claimWithdrawal(1, { from: stranger }) + await withdrawalQueue.claimWithdrawal(1, { from: stranger, gasPrice: 0 }) const strangerBalanceAfterClaim = await getBalance(stranger) // Happy-path: user receive ETH corresponding to the requested StETH amount assert.equals(strangerBalanceAfterClaim - strangerBalanceBeforeClaim, StETH(1)) diff --git a/test/0.8.9/withdrawal-queue-requests-finalization.test.js b/test/0.8.9/withdrawal-queue-requests-finalization.test.js index 89714a9b5..a350d1085 100644 --- a/test/0.8.9/withdrawal-queue-requests-finalization.test.js +++ b/test/0.8.9/withdrawal-queue-requests-finalization.test.js @@ -93,7 +93,8 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { await setShareRate(postFinalizationRate) const userBalanceBefore = await ethers.provider.getBalance(user) - await withdrawalQueue.claimWithdrawal(1, { from: user }) + // gasPrice:0 hack for coverage + await withdrawalQueue.claimWithdrawal(1, { from: user, gasPrice: 0 }) assert.equals(await ethers.provider.getBalance(user), userBalanceBefore.add(userRequestAmount)) assert.equals(await ethers.provider.getBalance(withdrawalQueue.address), 0) @@ -123,7 +124,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { await setShareRate(postFinalizationRate) const userBalanceBefore = await ethers.provider.getBalance(user) - await withdrawalQueue.claimWithdrawal(1, { from: user }) + await withdrawalQueue.claimWithdrawal(1, { from: user, gasPrice: 0 }) assert.equals(await ethers.provider.getBalance(user), userBalanceBefore.add(e18(0.5))) assert.equals(await ethers.provider.getBalance(withdrawalQueue.address), 0) @@ -152,7 +153,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { await setShareRate(postFinalizationRate) const userBalanceBefore = await ethers.provider.getBalance(user) - await withdrawalQueue.claimWithdrawal(1, { from: user }) + await withdrawalQueue.claimWithdrawal(1, { from: user, gasPrice: 0 }) assert.equals(await ethers.provider.getBalance(user), userBalanceBefore.add(e18(1))) assert.equals(await ethers.provider.getBalance(withdrawalQueue.address), 0) @@ -184,7 +185,9 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { await setShareRate(secondRequestRate) const anotherUserRequestAmount = e18(2) - await withdrawalQueue.requestWithdrawals([anotherUserRequestAmount], anotherUser, { from: anotherUser }) + await withdrawalQueue.requestWithdrawals([anotherUserRequestAmount], anotherUser, { + from: anotherUser, + }) const userExpectedEthAmount = finalizationRate >= firstRequestRate @@ -237,7 +240,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { await setShareRate(postFinalizationRate) const userBalanceBefore = await ethers.provider.getBalance(user) - await withdrawalQueue.claimWithdrawal(1, { from: user }) + await withdrawalQueue.claimWithdrawal(1, { from: user, gasPrice: 0 }) assert.equalsDelta( await ethers.provider.getBalance(user), toBN(userBalanceBefore).add(userExpectedEthAmount), @@ -245,7 +248,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { ) const anotherUserBalanceBefore = await ethers.provider.getBalance(anotherUser) - await withdrawalQueue.claimWithdrawal(2, { from: anotherUser }) + await withdrawalQueue.claimWithdrawal(2, { from: anotherUser, gasPrice: 0 }) assert.equalsDelta( await ethers.provider.getBalance(anotherUser), toBN(anotherUserBalanceBefore).add(anotherUserExpectedEthAmount), @@ -341,7 +344,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { await setShareRate(postFinalizationRate) const userBalanceBefore = await ethers.provider.getBalance(user) - await withdrawalQueue.claimWithdrawal(1, { from: user }) + await withdrawalQueue.claimWithdrawal(1, { from: user, gasPrice: 0 }) assert.equalsDelta( await ethers.provider.getBalance(user), toBN(userBalanceBefore).add(userExpectedEthAmount), @@ -349,7 +352,7 @@ contract('WithdrawalQueue', ([owner, daoAgent, user, anotherUser]) => { ) const anotherUserBalanceBefore = await ethers.provider.getBalance(anotherUser) - await withdrawalQueue.claimWithdrawal(2, { from: anotherUser }) + await withdrawalQueue.claimWithdrawal(2, { from: anotherUser, gasPrice: 0 }) assert.equalsDelta( await ethers.provider.getBalance(anotherUser), toBN(anotherUserBalanceBefore).add(anotherUserExpectedEthAmount), diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index d770d6692..a443e052c 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -88,6 +88,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, const [alice] = ACCOUNTS_AND_KEYS const amount = ETH(1) const deadline = MAX_UINT256 + await setBalance(alice, ETH(10)) await impersonate(ethers.provider, alice.address) const stETHDomainSeparator = await steth.DOMAIN_SEPARATOR() const wstETHDomainSeparator = await wsteth.DOMAIN_SEPARATOR() @@ -974,7 +975,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await withdrawalQueue.finalize([secondRequestId], shareRate(300), { from: steth.address, value: ETH(30) }) const balanceBefore = bn(await ethers.provider.getBalance(owner)) - const tx = await withdrawalQueue.claimWithdrawals([1, 2], [1, 1], { from: owner }) + const tx = await withdrawalQueue.claimWithdrawals([1, 2], [1, 1], { from: owner, gasPrice: 0 }) // tx.receipt.gasUsed is a workaround for coverage, because it ignores gasPrice=0 assert.almostEqual(await ethers.provider.getBalance(owner), balanceBefore.add(bn(ETH(30))), tx.receipt.gasUsed) }) From a4a29b6495ccf6f45f738d01e7a652d797bc2e0d Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Fri, 10 Mar 2023 13:07:09 +0200 Subject: [PATCH 225/236] stETH: support ERC-1271 signatures --- contracts/0.4.24/StETHPermit.sol | 60 ++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/contracts/0.4.24/StETHPermit.sol b/contracts/0.4.24/StETHPermit.sol index 6b7071746..5d4f04d4f 100644 --- a/contracts/0.4.24/StETHPermit.sol +++ b/contracts/0.4.24/StETHPermit.sol @@ -5,6 +5,7 @@ pragma solidity 0.4.24; import {UnstructuredStorage} from "@aragon/os/contracts/common/UnstructuredStorage.sol"; +import {Address} from "openzeppelin-solidity/contracts/utils/Address.sol"; import {ECDSA} from "../common/lib/ECDSA.sol"; import {IEIP712StETH} from "../common/interfaces/IEIP712StETH.sol"; @@ -54,6 +55,25 @@ interface IERC2612 { } +/** + * @dev Standard Signature Validation Method for Contracts, as defined in https://eips.ethereum.org/EIPS/eip-1271. + */ +interface IERC1271 { + /** + * @dev Should return whether the signature provided is valid for the provided hash. + * + * @param _hash Hash of the data to be signed. + * @param _signature Signature byte array associated with `_hash`. + * + * - MUST return the bytes4 magic value `0x1626ba7e` which is the function's selector, + * `bytes4(keccak256("isValidSignature(bytes32,bytes)")`, when function passes. + * - MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5). + * - MUST allow external calls. + */ + function isValidSignature(bytes32 _hash, bytes _signature) external view returns (bytes4); +} + + contract StETHPermit is IERC2612, StETH { using UnstructuredStorage for bytes32; @@ -102,9 +122,7 @@ contract StETHPermit is IERC2612, StETH { bytes32 hash = IEIP712StETH(getEIP712StETH()).hashTypedDataV4(address(this), structHash); - address signer = ECDSA.recover(hash, _v, _r, _s); - require(signer == _owner, "ERC20Permit: invalid signature"); - + require(_isValidSignature(_owner, hash, _v, _r, _s), "invalid signature"); _approve(_owner, _spender, _value); } @@ -172,4 +190,40 @@ contract StETHPermit is IERC2612, StETH { function getEIP712StETH() public view returns (address) { return EIP712_STETH_POSITION.getStorageAddress(); } + + /** + * @dev Checks signature validity. + * + * If the signer address doesn't contain any code, assumes that the address is externally owned + * and the signature is a ECDSA signature generated using its private key. Otherwise, issues a + * static call to the signer address to check the signature validity using the ERC-1271 standard. + */ + function _isValidSignature( + address _signer, + bytes32 _msgHash, + uint8 _v, + bytes32 _r, + bytes32 _s + ) internal returns (bool) { + if (Address.isContract(_signer)) { + bytes memory sig = abi.encodePacked(_r, _s, _v); + // Solidity <0.5 generates a regular CALL instruction even if the function being called + // is marked as `view`, and the only way to perform a STATICCALL is to use assembly + bytes memory data = abi.encodeWithSelector(IERC1271(0).isValidSignature.selector, _msgHash, sig); + bytes4 retval; + assembly { + // allocate memory for storing the return value + let outDataOffset := mload(0x40) + mstore(0x40, add(outDataOffset, 32)) + // issue a static call and load the result if the call succeeded + let success := staticcall(gas(), _signer, add(data, 32), mload(data), outDataOffset, 4) + if eq(success, 1) { + retval := mload(outDataOffset) + } + } + return retval == IERC1271(0).isValidSignature.selector; + } else { + return ECDSA.recover(_msgHash, _v, _r, _s) == _signer; + } + } } From b1a5735d8c57f5a093b9b744dc7559b7d944b486 Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Fri, 10 Mar 2023 14:44:17 +0200 Subject: [PATCH 226/236] stETH: pre-compute all hash constants in the 0.4.24 code --- contracts/0.4.24/StETH.sol | 5 ++++- contracts/0.4.24/StETHPermit.sol | 9 +++++++-- contracts/0.4.24/utils/Pausable.sol | 4 +++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index 0261fe377..6a3916dfa 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -79,8 +79,11 @@ contract StETH is IERC20, Pausable { * For reference types, conventional storage variables are used since it's non-trivial * and error-prone to implement reference-type unstructured storage using Solidity v0.4; * see https://github.com/lidofinance/lido-dao/issues/181#issuecomment-736098834 + * + * keccak256("lido.StETH.totalShares") */ - bytes32 internal constant TOTAL_SHARES_POSITION = keccak256("lido.StETH.totalShares"); + bytes32 internal constant TOTAL_SHARES_POSITION = + 0xe3b4b636e601189b5f4c6742edf2538ac12bb61ed03e6da26949d69838fa447e; /** * @notice An executed shares transfer from `sender` to `recipient`. diff --git a/contracts/0.4.24/StETHPermit.sol b/contracts/0.4.24/StETHPermit.sol index 5d4f04d4f..8c7bf2da2 100644 --- a/contracts/0.4.24/StETHPermit.sol +++ b/contracts/0.4.24/StETHPermit.sol @@ -89,14 +89,19 @@ contract StETHPermit is IERC2612, StETH { /** * @dev Storage position used for the EIP712 message utils contract + * + * keccak256("lido.StETHPermit.eip712StETH") */ - bytes32 internal constant EIP712_STETH_POSITION = keccak256("lido.StETHPermit.eip712StETH"); + bytes32 internal constant EIP712_STETH_POSITION = + 0x42b2d95e1ce15ce63bf9a8d9f6312cf44b23415c977ffa3b884333422af8941c; /** * @dev Typehash constant for ERC-2612 (Permit) + * + * keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)") */ bytes32 internal constant PERMIT_TYPEHASH = - keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, diff --git a/contracts/0.4.24/utils/Pausable.sol b/contracts/0.4.24/utils/Pausable.sol index 93da9bd0c..d74c708e3 100644 --- a/contracts/0.4.24/utils/Pausable.sol +++ b/contracts/0.4.24/utils/Pausable.sol @@ -12,7 +12,9 @@ contract Pausable { event Stopped(); event Resumed(); - bytes32 internal constant ACTIVE_FLAG_POSITION = keccak256("lido.Pausable.activeFlag"); + // keccak256("lido.Pausable.activeFlag") + bytes32 internal constant ACTIVE_FLAG_POSITION = + 0x644132c4ddd5bb6f0655d5fe2870dcec7870e6be4758890f366b83441f9fdece; function _whenNotStopped() internal view { require(ACTIVE_FLAG_POSITION.getStorageBool(), "CONTRACT_IS_STOPPED"); From 9b4b9ef3520fe21a60c8797dfdb3b3488099eb5d Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Fri, 10 Mar 2023 15:09:38 +0200 Subject: [PATCH 227/236] stETH: shorten error strings to save space --- contracts/0.4.24/StETH.sol | 22 ++++++++-------- contracts/0.4.24/StETHPermit.sol | 8 +++--- test/0.4.24/lido.test.js | 2 +- test/0.4.24/steth.test.js | 39 +++++++++-------------------- test/0.4.24/stethpermit.test.js | 22 ++++++++-------- test/0.8.9/burner.test.js | 5 +--- test/0.8.9/withdrawal-queue.test.js | 4 +-- 7 files changed, 42 insertions(+), 60 deletions(-) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index 6a3916dfa..f961e9456 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -235,7 +235,7 @@ contract StETH is IERC20, Pausable { */ function transferFrom(address _sender, address _recipient, uint256 _amount) external returns (bool) { uint256 currentAllowance = allowances[_sender][msg.sender]; - require(currentAllowance >= _amount, "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); + require(currentAllowance >= _amount, "ALLOWANCE_EXCEEDED"); _transfer(_sender, _recipient, _amount); _approve(_sender, msg.sender, currentAllowance.sub(_amount)); @@ -274,7 +274,7 @@ contract StETH is IERC20, Pausable { */ function decreaseAllowance(address _spender, uint256 _subtractedValue) external returns (bool) { uint256 currentAllowance = allowances[msg.sender][_spender]; - require(currentAllowance >= _subtractedValue, "DECREASED_ALLOWANCE_BELOW_ZERO"); + require(currentAllowance >= _subtractedValue, "ALLOWANCE_BELOW_ZERO"); _approve(msg.sender, _spender, currentAllowance.sub(_subtractedValue)); return true; } @@ -358,7 +358,7 @@ contract StETH is IERC20, Pausable { ) external returns (uint256) { uint256 currentAllowance = allowances[_sender][msg.sender]; uint256 tokensAmount = getPooledEthByShares(_sharesAmount); - require(currentAllowance >= tokensAmount, "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); + require(currentAllowance >= tokensAmount, "ALLOWANCE_EXCEEDED"); _transferShares(_sender, _recipient, _sharesAmount); _approve(_sender, msg.sender, currentAllowance.sub(tokensAmount)); @@ -399,8 +399,8 @@ contract StETH is IERC20, Pausable { * - `_spender` cannot be the zero address. */ function _approve(address _owner, address _spender, uint256 _amount) internal { - require(_owner != address(0), "APPROVE_FROM_ZERO_ADDRESS"); - require(_spender != address(0), "APPROVE_TO_ZERO_ADDRESS"); + require(_owner != address(0), "APPROVE_FROM_ZERO_ADDR"); + require(_spender != address(0), "APPROVE_TO_ZERO_ADDR"); allowances[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); @@ -431,12 +431,12 @@ contract StETH is IERC20, Pausable { * - the contract must not be paused. */ function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal { - require(_sender != address(0), "TRANSFER_FROM_THE_ZERO_ADDRESS"); - require(_recipient != address(0), "TRANSFER_TO_THE_ZERO_ADDRESS"); + require(_sender != address(0), "TRANSFER_FROM_ZERO_ADDR"); + require(_recipient != address(0), "TRANSFER_TO_ZERO_ADDR"); _whenNotStopped(); uint256 currentSenderShares = shares[_sender]; - require(_sharesAmount <= currentSenderShares, "TRANSFER_AMOUNT_EXCEEDS_BALANCE"); + require(_sharesAmount <= currentSenderShares, "BALANCE_EXCEEDED"); shares[_sender] = currentSenderShares.sub(_sharesAmount); shares[_recipient] = shares[_recipient].add(_sharesAmount); @@ -454,7 +454,7 @@ contract StETH is IERC20, Pausable { * - the contract must not be paused. */ function _mintShares(address _recipient, uint256 _sharesAmount) internal returns (uint256 newTotalShares) { - require(_recipient != address(0), "MINT_TO_THE_ZERO_ADDRESS"); + require(_recipient != address(0), "MINT_TO_ZERO_ADDR"); newTotalShares = _getTotalShares().add(_sharesAmount); TOTAL_SHARES_POSITION.setStorageUint256(newTotalShares); @@ -480,10 +480,10 @@ contract StETH is IERC20, Pausable { * - the contract must not be paused. */ function _burnShares(address _account, uint256 _sharesAmount) internal returns (uint256 newTotalShares) { - require(_account != address(0), "BURN_FROM_THE_ZERO_ADDRESS"); + require(_account != address(0), "BURN_FROM_ZERO_ADDR"); uint256 accountShares = shares[_account]; - require(_sharesAmount <= accountShares, "BURN_AMOUNT_EXCEEDS_BALANCE"); + require(_sharesAmount <= accountShares, "BALANCE_EXCEEDED"); uint256 preRebaseTokenAmount = getPooledEthByShares(_sharesAmount); diff --git a/contracts/0.4.24/StETHPermit.sol b/contracts/0.4.24/StETHPermit.sol index 8c7bf2da2..99e58e6e8 100644 --- a/contracts/0.4.24/StETHPermit.sol +++ b/contracts/0.4.24/StETHPermit.sol @@ -119,7 +119,7 @@ contract StETHPermit is IERC2612, StETH { function permit( address _owner, address _spender, uint256 _value, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external { - require(block.timestamp <= _deadline, "ERC20Permit: expired deadline"); + require(block.timestamp <= _deadline, "DEADLINE_EXPIRED"); bytes32 structHash = keccak256( abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, _useNonce(_owner), _deadline) @@ -127,7 +127,7 @@ contract StETHPermit is IERC2612, StETH { bytes32 hash = IEIP712StETH(getEIP712StETH()).hashTypedDataV4(address(this), structHash); - require(_isValidSignature(_owner, hash, _v, _r, _s), "invalid signature"); + require(_isValidSignature(_owner, hash, _v, _r, _s), "INVALID_SIGNATURE"); _approve(_owner, _spender, _value); } @@ -181,8 +181,8 @@ contract StETHPermit is IERC2612, StETH { * @dev Initialize EIP712 message utils contract for stETH */ function _initializeEIP712StETH(address _eip712StETH) internal { - require(_eip712StETH != address(0), "StETHPermit: zero eip712StETH"); - require(getEIP712StETH() == address(0), "StETHPermit: eip712StETH already set"); + require(_eip712StETH != address(0), "ZERO_EIP712STETH"); + require(getEIP712StETH() == address(0), "EIP712STETH_ALREADY_SET"); EIP712_STETH_POSITION.setStorageAddress(_eip712StETH); diff --git a/test/0.4.24/lido.test.js b/test/0.4.24/lido.test.js index 8929dd4df..92137d8c0 100644 --- a/test/0.4.24/lido.test.js +++ b/test/0.4.24/lido.test.js @@ -1638,7 +1638,7 @@ contract('Lido', ([appManager, , , , , , , , , , , , user1, user2, user3, nobody assert.equals(await app.sharesOf(user1), shares(0)) // voting can't continue burning if user already has no shares - await assert.reverts(app.burnShares(user1, 1, { from: voting }), 'BURN_AMOUNT_EXCEEDS_BALANCE') + await assert.reverts(app.burnShares(user1, 1, { from: voting }), 'BALANCE_EXCEEDED') }) context('treasury', () => { diff --git a/test/0.4.24/steth.test.js b/test/0.4.24/steth.test.js index b05e4f7a1..abb37ed4a 100644 --- a/test/0.4.24/steth.test.js +++ b/test/0.4.24/steth.test.js @@ -88,12 +88,12 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { context('transfer', async () => { it('reverts when recipient is the zero address', async () => { - await assert.reverts(stEth.transfer(ZERO_ADDRESS, tokens(1), { from: user1 }), 'TRANSFER_TO_THE_ZERO_ADDRESS') + await assert.reverts(stEth.transfer(ZERO_ADDRESS, tokens(1), { from: user1 }), 'TRANSFER_TO_ZERO_ADDR') }) it('reverts when the sender does not have enough balance', async () => { - await assert.reverts(stEth.transfer(user2, tokens(101), { from: user1 }), 'TRANSFER_AMOUNT_EXCEEDS_BALANCE') - await assert.reverts(stEth.transfer(user1, bn('1'), { from: user2 }), 'TRANSFER_AMOUNT_EXCEEDS_BALANCE') + await assert.reverts(stEth.transfer(user2, tokens(101), { from: user1 }), 'BALANCE_EXCEEDED') + await assert.reverts(stEth.transfer(user1, bn('1'), { from: user2 }), 'BALANCE_EXCEEDED') }) it('transfer all balance works and emits event', async () => { @@ -169,14 +169,14 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { it('reverts when recipient is zero address', async () => { await assert.reverts( stEth.transferFrom(user1, ZERO_ADDRESS, tokens(1), { from: user2 }), - 'TRANSFER_TO_THE_ZERO_ADDRESS' + 'TRANSFER_TO_ZERO_ADDR' ) }) it('reverts when sender is zero address', async () => { await assert.reverts( stEth.transferFrom(ZERO_ADDRESS, user3, tokens(0), { from: user2 }), - 'TRANSFER_FROM_THE_ZERO_ADDRESS' + 'TRANSFER_FROM_ZERO_ADDR' ) }) @@ -385,11 +385,11 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { }) it('reverts when burn from zero address', async () => { - await assert.reverts(stEth.burnShares(ZERO_ADDRESS, tokens(1), { from: user1 }), 'BURN_FROM_THE_ZERO_ADDRESS') + await assert.reverts(stEth.burnShares(ZERO_ADDRESS, tokens(1), { from: user1 }), 'BURN_FROM_ZERO_ADDR') }) it('reverts when burn amount exceeds balance', async () => { - await assert.reverts(stEth.burnShares(user1, tokens(101)), 'BURN_AMOUNT_EXCEEDS_BALANCE') + await assert.reverts(stEth.burnShares(user1, tokens(101)), 'BALANCE_EXCEEDED') }) it('burning zero value works', async () => { @@ -591,10 +591,7 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { assert.equals(await stEth.balanceOf(user1), tokens(69)) assert.equals(await stEth.balanceOf(nobody), tokens(30)) - await assert.reverts( - stEth.transferShares(nobody, tokens(75), { from: user1 }), - 'TRANSFER_AMOUNT_EXCEEDS_BALANCE' - ) + await assert.reverts(stEth.transferShares(nobody, tokens(75), { from: user1 }), 'BALANCE_EXCEEDED') await stEth.setTotalPooledEther(tokens(120)) @@ -623,10 +620,7 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { assert.equals(await stEth.balanceOf(user1), tokens(99)) assert.equals(await stEth.balanceOf(nobody), tokens(0)) - await assert.reverts( - stEth.transferSharesFrom(user1, nobody, tokens(30), { from: user2 }), - `TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE` - ) + await assert.reverts(stEth.transferSharesFrom(user1, nobody, tokens(30), { from: user2 }), `ALLOWANCE_EXCEEDED`) await stEth.approve(user2, tokens(30), { from: user1 }) receipt = await stEth.transferSharesFrom(user1, nobody, tokens(30), { from: user2 }) assert.emitsNumberOfEvents(receipt, 'Transfer', 1) @@ -637,22 +631,13 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { assert.equals(await stEth.balanceOf(user1), tokens(69)) assert.equals(await stEth.balanceOf(nobody), tokens(30)) - await assert.reverts( - stEth.transferSharesFrom(user1, nobody, tokens(75), { from: user2 }), - 'TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE' - ) + await assert.reverts(stEth.transferSharesFrom(user1, nobody, tokens(75), { from: user2 }), 'ALLOWANCE_EXCEEDED') await stEth.approve(user2, tokens(75), { from: user1 }) - await assert.reverts( - stEth.transferSharesFrom(user1, nobody, tokens(75), { from: user2 }), - 'TRANSFER_AMOUNT_EXCEEDS_BALANCE' - ) + await assert.reverts(stEth.transferSharesFrom(user1, nobody, tokens(75), { from: user2 }), 'BALANCE_EXCEEDED') await stEth.setTotalPooledEther(tokens(120)) - await assert.reverts( - stEth.transferSharesFrom(user1, nobody, tokens(70), { from: user2 }), - 'TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE' - ) + await assert.reverts(stEth.transferSharesFrom(user1, nobody, tokens(70), { from: user2 }), 'ALLOWANCE_EXCEEDED') await stEth.approve(user2, tokens(84), { from: user1 }) receipt = await stEth.transferSharesFrom(user1, nobody, tokens(69), { from: user2 }) diff --git a/test/0.4.24/stethpermit.test.js b/test/0.4.24/stethpermit.test.js index e5fca0088..6badd81a9 100644 --- a/test/0.4.24/stethpermit.test.js +++ b/test/0.4.24/stethpermit.test.js @@ -129,7 +129,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { s, { from: charlie } ), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) // check that msg is incorrect even if claim the approved amount - 1 @@ -144,7 +144,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { s, { from: charlie } ), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) }) @@ -160,7 +160,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie, }), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) // unlock bob account (allow transactions originated from bob.address) @@ -172,7 +172,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: bob.address, }), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) }) @@ -187,7 +187,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie, }), - 'ERC20Permit: expired deadline' + 'DEADLINE_EXPIRED' ) { @@ -214,7 +214,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie, }), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) }) @@ -231,7 +231,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie, }), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) // unlock bob account (allow transactions originated from bob.address) @@ -243,7 +243,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: alice.address, }), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) }) @@ -262,7 +262,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { // try to submit the permit again await assert.reverts( stEthPermit.permit(owner, spender, 1e6, deadline, permit2.v, permit2.r, permit2.s, { from: charlie }), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) }) @@ -278,7 +278,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie, }), - 'APPROVE_TO_ZERO_ADDRESS' + 'APPROVE_TO_ZERO_ADDR' ) }) @@ -303,7 +303,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { stEthPermit.permit(from, to, value, validBefore, v, r, s, { from: charlie, }), - 'ERC20Permit: invalid signature' + 'INVALID_SIGNATURE' ) }) }) diff --git a/test/0.8.9/burner.test.js b/test/0.8.9/burner.test.js index 42ea04ef7..88dcc6f6a 100644 --- a/test/0.8.9/burner.test.js +++ b/test/0.8.9/burner.test.js @@ -278,10 +278,7 @@ contract('Burner', ([deployer, _, anotherAccount]) => { it(`request shares burn for cover works`, async () => { // allowance should be set explicitly to request burning - await assert.reverts( - burner.requestBurnMyStETHForCover(StETH(8), { from: voting }), - `TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE` - ) + await assert.reverts(burner.requestBurnMyStETHForCover(StETH(8), { from: voting }), `ALLOWANCE_EXCEEDED`) // provide allowance and request burn for cover const sharesAmount8StETH = await lido.getSharesByPooledEth(StETH(8)) diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index d770d6692..573a8e8e4 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -298,7 +298,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, it('One cant request more than they have', async () => { await assert.reverts( withdrawalQueue.requestWithdrawals([StETH(400)], owner, { from: user }), - 'TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE' + 'ALLOWANCE_EXCEEDED' ) }) @@ -307,7 +307,7 @@ contract('WithdrawalQueue', ([owner, stranger, daoAgent, user, pauser, resumer, await assert.reverts( withdrawalQueue.requestWithdrawals([StETH(300)], owner, { from: user }), - 'TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE' + 'ALLOWANCE_EXCEEDED' ) }) From 9d664d70761c94ebb331fa47a3c19b3d981adc4f Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Fri, 10 Mar 2023 15:42:59 +0200 Subject: [PATCH 228/236] stETH: extract signature verification to a library --- contracts/0.4.24/StETHPermit.sol | 60 +---------------------- contracts/common/lib/SignatureUtils.sol | 65 +++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 58 deletions(-) create mode 100644 contracts/common/lib/SignatureUtils.sol diff --git a/contracts/0.4.24/StETHPermit.sol b/contracts/0.4.24/StETHPermit.sol index 99e58e6e8..b0105e58d 100644 --- a/contracts/0.4.24/StETHPermit.sol +++ b/contracts/0.4.24/StETHPermit.sol @@ -5,9 +5,8 @@ pragma solidity 0.4.24; import {UnstructuredStorage} from "@aragon/os/contracts/common/UnstructuredStorage.sol"; -import {Address} from "openzeppelin-solidity/contracts/utils/Address.sol"; -import {ECDSA} from "../common/lib/ECDSA.sol"; +import {SignatureUtils} from "../common/lib/SignatureUtils.sol"; import {IEIP712StETH} from "../common/interfaces/IEIP712StETH.sol"; import {StETH} from "./StETH.sol"; @@ -55,25 +54,6 @@ interface IERC2612 { } -/** - * @dev Standard Signature Validation Method for Contracts, as defined in https://eips.ethereum.org/EIPS/eip-1271. - */ -interface IERC1271 { - /** - * @dev Should return whether the signature provided is valid for the provided hash. - * - * @param _hash Hash of the data to be signed. - * @param _signature Signature byte array associated with `_hash`. - * - * - MUST return the bytes4 magic value `0x1626ba7e` which is the function's selector, - * `bytes4(keccak256("isValidSignature(bytes32,bytes)")`, when function passes. - * - MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5). - * - MUST allow external calls. - */ - function isValidSignature(bytes32 _hash, bytes _signature) external view returns (bytes4); -} - - contract StETHPermit is IERC2612, StETH { using UnstructuredStorage for bytes32; @@ -127,7 +107,7 @@ contract StETHPermit is IERC2612, StETH { bytes32 hash = IEIP712StETH(getEIP712StETH()).hashTypedDataV4(address(this), structHash); - require(_isValidSignature(_owner, hash, _v, _r, _s), "INVALID_SIGNATURE"); + require(SignatureUtils.isValidSignature(_owner, hash, _v, _r, _s), "INVALID_SIGNATURE"); _approve(_owner, _spender, _value); } @@ -195,40 +175,4 @@ contract StETHPermit is IERC2612, StETH { function getEIP712StETH() public view returns (address) { return EIP712_STETH_POSITION.getStorageAddress(); } - - /** - * @dev Checks signature validity. - * - * If the signer address doesn't contain any code, assumes that the address is externally owned - * and the signature is a ECDSA signature generated using its private key. Otherwise, issues a - * static call to the signer address to check the signature validity using the ERC-1271 standard. - */ - function _isValidSignature( - address _signer, - bytes32 _msgHash, - uint8 _v, - bytes32 _r, - bytes32 _s - ) internal returns (bool) { - if (Address.isContract(_signer)) { - bytes memory sig = abi.encodePacked(_r, _s, _v); - // Solidity <0.5 generates a regular CALL instruction even if the function being called - // is marked as `view`, and the only way to perform a STATICCALL is to use assembly - bytes memory data = abi.encodeWithSelector(IERC1271(0).isValidSignature.selector, _msgHash, sig); - bytes4 retval; - assembly { - // allocate memory for storing the return value - let outDataOffset := mload(0x40) - mstore(0x40, add(outDataOffset, 32)) - // issue a static call and load the result if the call succeeded - let success := staticcall(gas(), _signer, add(data, 32), mload(data), outDataOffset, 4) - if eq(success, 1) { - retval := mload(outDataOffset) - } - } - return retval == IERC1271(0).isValidSignature.selector; - } else { - return ECDSA.recover(_msgHash, _v, _r, _s) == _signer; - } - } } diff --git a/contracts/common/lib/SignatureUtils.sol b/contracts/common/lib/SignatureUtils.sol new file mode 100644 index 000000000..4fd309cc4 --- /dev/null +++ b/contracts/common/lib/SignatureUtils.sol @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: MIT + +/* See contracts/COMPILERS.md */ +// solhint-disable-next-line lido/fixed-compiler-version +pragma solidity >=0.4.24 <0.9.0; + +import {ECDSA} from "./ECDSA.sol"; + + +library SignatureUtils { + /** + * @dev The selector of the ERC1271's `isValidSignature(bytes32 hash, bytes signature)` function, + * serving at the same time as the magic value that the function should return upon success. + * + * See https://eips.ethereum.org/EIPS/eip-1271. + * + * bytes4(keccak256("isValidSignature(bytes32,bytes)") + */ + bytes4 internal constant ERC1271_IS_VALID_SIGNATURE_SELECTOR = 0x1626ba7e; + + /** + * @dev Checks signature validity. + * + * If the signer address doesn't contain any code, assumes that the address is externally owned + * and the signature is a ECDSA signature generated using its private key. Otherwise, issues a + * static call to the signer address to check the signature validity using the ERC-1271 standard. + */ + function isValidSignature( + address signer, + bytes32 msgHash, + uint8 v, + bytes32 r, + bytes32 s + ) internal view returns (bool) { + if (_hasCode(signer)) { + bytes memory sig = abi.encodePacked(r, s, v); + // Solidity <0.5 generates a regular CALL instruction even if the function being called + // is marked as `view`, and the only way to perform a STATICCALL is to use assembly + bytes memory data = abi.encodeWithSelector(ERC1271_IS_VALID_SIGNATURE_SELECTOR, msgHash, sig); + bytes4 retval; + /// @solidity memory-safe-assembly + assembly { + // allocate memory for storing the return value + let outDataOffset := mload(0x40) + mstore(0x40, add(outDataOffset, 32)) + // issue a static call and load the result if the call succeeded + let success := staticcall(gas(), signer, add(data, 32), mload(data), outDataOffset, 32) + if eq(success, 1) { + retval := mload(outDataOffset) + } + } + return retval == ERC1271_IS_VALID_SIGNATURE_SELECTOR; + } else { + return ECDSA.recover(msgHash, v, r, s) == signer; + } + } + + function _hasCode(address addr) internal view returns (bool) { + uint256 size; + /// @solidity memory-safe-assembly + assembly { size := extcodesize(addr) } + return size > 0; + } +} From 686558358148fcfca06bd3a5d862268da5b36e2e Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Sat, 11 Mar 2023 00:09:43 +0200 Subject: [PATCH 229/236] stETH: add basic tests for ERC1271 sig verification --- .../ERC1271MutatingSignerMock.sol | 14 ++ .../test_helpers/ERC1271SignerDumbMock.sol | 25 ++++ .../common/test_helpers/ERC1271SignerMock.sol | 29 ++++ .../SignatureUtilsConsumer_0_4_24.sol | 21 +++ .../SignatureUtilsConsumer_0_8_9.sol | 21 +++ test/0.4.24/helpers/permit_helpers.js | 3 +- test/0.4.24/helpers/sign_utils.js | 26 ---- test/0.4.24/stethpermit.test.js | 3 +- test/0.6.12/helpers/constants.js | 75 ---------- test/0.6.12/helpers/index.js | 52 ------- test/0.6.12/helpers/permit_helpers.js | 4 +- test/0.6.12/wsteth.permit.test.js | 5 +- test/0.8.9/withdrawal-queue.test.js | 2 +- test/common/lib/signature-utils.test.js | 129 ++++++++++++++++++ test/helpers/constants.js | 65 +++++++++ test/helpers/signatures.js | 12 +- test/helpers/signing-keys.js | 3 +- test/helpers/utils.js | 10 ++ 18 files changed, 336 insertions(+), 163 deletions(-) create mode 100644 contracts/common/test_helpers/ERC1271MutatingSignerMock.sol create mode 100644 contracts/common/test_helpers/ERC1271SignerDumbMock.sol create mode 100644 contracts/common/test_helpers/ERC1271SignerMock.sol create mode 100644 contracts/common/test_helpers/SignatureUtilsConsumer_0_4_24.sol create mode 100644 contracts/common/test_helpers/SignatureUtilsConsumer_0_8_9.sol delete mode 100644 test/0.4.24/helpers/sign_utils.js delete mode 100644 test/0.6.12/helpers/constants.js delete mode 100644 test/0.6.12/helpers/index.js create mode 100644 test/common/lib/signature-utils.test.js diff --git a/contracts/common/test_helpers/ERC1271MutatingSignerMock.sol b/contracts/common/test_helpers/ERC1271MutatingSignerMock.sol new file mode 100644 index 000000000..81d32685c --- /dev/null +++ b/contracts/common/test_helpers/ERC1271MutatingSignerMock.sol @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + + +contract ERC1271MutatingSignerMock { + uint256 public callCount_isValidSignature; + + function isValidSignature(bytes32 /* hash */, bytes memory /* sig */) external returns (bytes4) { + ++callCount_isValidSignature; + return 0x1626ba7e; + } +} diff --git a/contracts/common/test_helpers/ERC1271SignerDumbMock.sol b/contracts/common/test_helpers/ERC1271SignerDumbMock.sol new file mode 100644 index 000000000..5b02e2fa8 --- /dev/null +++ b/contracts/common/test_helpers/ERC1271SignerDumbMock.sol @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + + +contract ERC1271SignerDumbMock { + error InvalidSignature(); + + struct Config { + bytes4 retval; + bool reverts; + } + + Config internal _config; + + function configure(Config memory config) external { + _config = config; + } + + function isValidSignature(bytes32 /* hash */, bytes memory /* sig */) external view returns (bytes4) { + if (_config.reverts) revert InvalidSignature(); + return _config.retval; + } +} diff --git a/contracts/common/test_helpers/ERC1271SignerMock.sol b/contracts/common/test_helpers/ERC1271SignerMock.sol new file mode 100644 index 000000000..9e1a5b8ad --- /dev/null +++ b/contracts/common/test_helpers/ERC1271SignerMock.sol @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + + +contract ERC1271SignerMock { + struct Config { + bytes32 validHash; + bytes validSig; + bytes4 retvalOnValid; + bytes4 retvalOnInvalid; + } + + Config internal _config; + + function configure(Config memory config) external { + _config = config; + } + + function isValidSignature(bytes32 hash, bytes memory sig) external view returns (bytes4) { + Config memory cfg = _config; + + return hash == cfg.validHash && keccak256(sig) == keccak256(cfg.validSig) + ? cfg.retvalOnValid + : cfg.retvalOnInvalid; + } + +} diff --git a/contracts/common/test_helpers/SignatureUtilsConsumer_0_4_24.sol b/contracts/common/test_helpers/SignatureUtilsConsumer_0_4_24.sol new file mode 100644 index 000000000..a0bb017e1 --- /dev/null +++ b/contracts/common/test_helpers/SignatureUtilsConsumer_0_4_24.sol @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.4.24; + +import {SignatureUtils} from "../lib/SignatureUtils.sol"; + + +contract SignatureUtilsConsumer_0_4_24 { + + function isValidSignature( + address signer, + bytes32 msgHash, + uint8 v, + bytes32 r, + bytes32 s + ) external view returns (bool) { + return SignatureUtils.isValidSignature(signer, msgHash, v, r, s); + } + +} diff --git a/contracts/common/test_helpers/SignatureUtilsConsumer_0_8_9.sol b/contracts/common/test_helpers/SignatureUtilsConsumer_0_8_9.sol new file mode 100644 index 000000000..5a47d21fd --- /dev/null +++ b/contracts/common/test_helpers/SignatureUtilsConsumer_0_8_9.sol @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + +import {SignatureUtils} from "../lib/SignatureUtils.sol"; + + +contract SignatureUtilsConsumer_0_8_9 { + + function isValidSignature( + address signer, + bytes32 msgHash, + uint8 v, + bytes32 r, + bytes32 s + ) external view returns (bool) { + return SignatureUtils.isValidSignature(signer, msgHash, v, r, s); + } + +} diff --git a/test/0.4.24/helpers/permit_helpers.js b/test/0.4.24/helpers/permit_helpers.js index 948e36c0b..87a93a9c3 100644 --- a/test/0.4.24/helpers/permit_helpers.js +++ b/test/0.4.24/helpers/permit_helpers.js @@ -1,5 +1,6 @@ const { web3 } = require('hardhat') -const { ecSign, strip0x } = require('./sign_utils') +const { strip0x } = require('../../helpers/utils') +const { ecSign } = require('../../helpers/signatures') const transferWithAuthorizationTypeHash = web3.utils.keccak256( 'TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)' diff --git a/test/0.4.24/helpers/sign_utils.js b/test/0.4.24/helpers/sign_utils.js deleted file mode 100644 index f05e4a503..000000000 --- a/test/0.4.24/helpers/sign_utils.js +++ /dev/null @@ -1,26 +0,0 @@ -const { ecsign } = require('ethereumjs-util') - -function hexStringFromBuffer(buf) { - return '0x' + buf.toString('hex') -} - -function bufferFromHexString(hex) { - return Buffer.from(strip0x(hex), 'hex') -} - -function strip0x(v) { - return v.replace(/^0x/, '') -} - -function ecSign(digest, privateKey) { - const { v, r, s } = ecsign(bufferFromHexString(digest), bufferFromHexString(privateKey)) - - return { v, r: hexStringFromBuffer(r), s: hexStringFromBuffer(s) } -} - -module.exports = { - hexStringFromBuffer, - strip0x, - ecSign, - bufferFromHexString, -} diff --git a/test/0.4.24/stethpermit.test.js b/test/0.4.24/stethpermit.test.js index 6badd81a9..881c95b51 100644 --- a/test/0.4.24/stethpermit.test.js +++ b/test/0.4.24/stethpermit.test.js @@ -5,8 +5,7 @@ const crypto = require('crypto') const { ACCOUNTS_AND_KEYS, MAX_UINT256, ZERO_ADDRESS } = require('./helpers/constants') const { bn } = require('@aragon/contract-helpers-test') const { signPermit, signTransferAuthorization, makeDomainSeparator } = require('./helpers/permit_helpers') -const { hexStringFromBuffer } = require('./helpers/sign_utils') -const { ETH } = require('../helpers/utils') +const { ETH, hexStringFromBuffer } = require('../helpers/utils') const { EvmSnapshot } = require('../helpers/blockchain') const EIP712StETH = artifacts.require('EIP712StETH') diff --git a/test/0.6.12/helpers/constants.js b/test/0.6.12/helpers/constants.js deleted file mode 100644 index 2ab497f21..000000000 --- a/test/0.6.12/helpers/constants.js +++ /dev/null @@ -1,75 +0,0 @@ -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' - -const ZERO_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000' -const MAX_UINT256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' - -// derived from mnemonic: clarify final village pulse require old seek excite mushroom forest satoshi video -const ACCOUNTS_AND_KEYS = [ - { - address: '0x8e81C8f0CFf3d6eA2Fe72c1A5ee49Fc377401c2D', - key: '84132dd41f32804774a98647c308c0c94a54c0f3931128c0210b6f3689d2b7e7', - }, - { - address: '0x244A0A1d21f21167c17e04EBc5FA33c885990674', - key: '31a372c197c7c5d6856bfac311a66f179bdc3bda20e78030b0fef90e40cbc83f', - }, - { - address: '0x6966f881B3Ee9074b0783CC614e3864e380B8b27', - key: '58bdc54eb2aa3a92e5a36fae01d23b7626fa89116a41e01ca3c6cb18799aee3d', - }, - { - address: '0xaC5faE80468DcC49D404d0625609C031B9AF2cb7', - key: 'd14ca7a30bc2921ddb89ea2f6c52393f91e794cd9c3c994f547eb7edeb092fd1', - }, - { - address: '0x18C246058e9e4Ae1737387fA90cD69E39f78F73A', - key: '1c09baae4343b0a66567d56769b62537623389542480f30e9acdae0624612872', - }, - { - address: '0xc4dc5dAD36fF9b8cB694E79238ECbe76ab13BcEc', - key: '2048571627de761088f2f369306f9c231e6c7ab94be1f0a0c979776a2f424328', - }, - { - address: '0x75Bf6E76D3dB629f46da549D49C9ea821CE8e9A9', - key: '9a9afb6a8e2384e4cce14824d15162bba2eed7e31df846ff77d697fed8cba0c1', - }, - { - address: '0x55937b3ae7a34F551e5aFa5BA51Fba4eD9f8FeD7', - key: '9747a0294186b8fef20ec1e4341a10c87840b18a8930b84c4c5dcd97799ba0bc', - }, - { - address: '0x1eEEBc3900803a28ca6E68Eb98FDeCf98350D97B', - key: 'cdbaf218f6332bfa630ec2abc7a8bc450b2e8746133d84450dfc2234fdfb83ef', - }, - { - address: '0x8719beDE472E67642b88DbA9aD1b1b9dc05CC60e', - key: 'c08dbf2c9aaf5dc3cd5ce5349e754de086202a5f352a512851a4f174ac246198', - }, - { - address: '0xE03701ea2248C7ca2Fed1e655ff3C803C7267302', - key: '40566af8625c93f95c5e1ea9aa42642bcbdd64fe4fe7926283d04173cb842189', - }, - { - address: '0x10506aB975D36aa781B77C1Ce204F46e8f87dA57', - key: '55ef7a25bba3449344d8a1e525ba3ca4999bdc763be4efaf9e94a4de396f8370', - }, - { - address: '0xee11cdb1f9eEe2eB40D2CF99b4fa7D782aE582A6', - key: '985117805090656613ae19743879efe4cff76049de03516debf41926313e3629', - }, - { - address: '0xB9203C29E242d7a19AE6970cDf0d873048B99419', - key: '3a37d1ad3751e697c26dd05a71cd9263c023f3e8a1d1067215044032c62ee916', - }, - { - address: '0xcC03603436Bc0Edd1e0661379f3Aa289ae967597', - key: 'db81ac68891890ec33021264ce81f9b5f9296a9fd95cdc785655db3066db2c08', - }, -] - -module.exports = { - ZERO_ADDRESS, - ZERO_BYTES32, - MAX_UINT256, - ACCOUNTS_AND_KEYS, -} diff --git a/test/0.6.12/helpers/index.js b/test/0.6.12/helpers/index.js deleted file mode 100644 index 39f2c5dba..000000000 --- a/test/0.6.12/helpers/index.js +++ /dev/null @@ -1,52 +0,0 @@ -const { ecsign } = require('ethereumjs-util') -const { assert } = require('chai') - -async function expectRevert(promise, reason) { - let err - try { - await promise - } catch (e) { - err = e - } - - if (!err) { - assert.fail('Exception not thrown') - } - - const errMsg = err.hijackedMessage || err.message - assert.match(errMsg, /revert/i) - - if (reason) { - if (reason instanceof RegExp) { - assert.match(errMsg, reason) - } else { - assert.include(errMsg, reason) - } - } -} - -function hexStringFromBuffer(buf) { - return '0x' + buf.toString('hex') -} - -function strip0x(v) { - return v.replace(/^0x/, '') -} - -function ecSign(digest, privateKey) { - const { v, r, s } = ecsign(bufferFromHexString(digest), bufferFromHexString(privateKey)) - - return { v, r: hexStringFromBuffer(r), s: hexStringFromBuffer(s) } -} - -function bufferFromHexString(hex) { - return Buffer.from(strip0x(hex), 'hex') -} - -module.exports = { - expectRevert, - hexStringFromBuffer, - strip0x, - ecSign, - bufferFromHexString, -} diff --git a/test/0.6.12/helpers/permit_helpers.js b/test/0.6.12/helpers/permit_helpers.js index f083368ac..7d72cba2f 100644 --- a/test/0.6.12/helpers/permit_helpers.js +++ b/test/0.6.12/helpers/permit_helpers.js @@ -1,5 +1,7 @@ const { web3 } = require('hardhat') -const { ecSign, strip0x } = require('./index') + +const { strip0x } = require('../../helpers/utils') +const { ecSign } = require('../../helpers/signatures') const transferWithAuthorizationTypeHash = web3.utils.keccak256( 'TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)' diff --git a/test/0.6.12/wsteth.permit.test.js b/test/0.6.12/wsteth.permit.test.js index a29b1655b..4e9c8d28f 100644 --- a/test/0.6.12/wsteth.permit.test.js +++ b/test/0.6.12/wsteth.permit.test.js @@ -1,8 +1,9 @@ const { artifacts, contract } = require('hardhat') const crypto = require('crypto') const { expect } = require('chai') -const { ACCOUNTS_AND_KEYS, MAX_UINT256, ZERO_ADDRESS } = require('./helpers/constants') -const { expectRevert, hexStringFromBuffer } = require('./helpers') +const { expectRevert } = require('@openzeppelin/test-helpers') +const { ACCOUNTS_AND_KEYS, MAX_UINT256, ZERO_ADDRESS } = require('../helpers/constants') +const { hexStringFromBuffer } = require('../helpers/utils') const { signPermit, signTransferAuthorization, makeDomainSeparator } = require('./helpers/permit_helpers') const WstETH = artifacts.require('WstETHMock') diff --git a/test/0.8.9/withdrawal-queue.test.js b/test/0.8.9/withdrawal-queue.test.js index 573a8e8e4..1cf0587b8 100644 --- a/test/0.8.9/withdrawal-queue.test.js +++ b/test/0.8.9/withdrawal-queue.test.js @@ -3,8 +3,8 @@ const { bn, getEventArgument, ZERO_ADDRESS } = require('@aragon/contract-helpers const { ETH, StETH, shareRate, shares } = require('../helpers/utils') const { assert } = require('../helpers/assert') +const { MAX_UINT256, ACCOUNTS_AND_KEYS } = require('../helpers/constants') const { signPermit, makeDomainSeparator } = require('../0.6.12/helpers/permit_helpers') -const { MAX_UINT256, ACCOUNTS_AND_KEYS } = require('../0.6.12/helpers/constants') const { impersonate, EvmSnapshot, getCurrentBlockTimestamp, setBalance } = require('../helpers/blockchain') const { deployWithdrawalQueue } = require('./withdrawal-queue-deploy.test') diff --git a/test/common/lib/signature-utils.test.js b/test/common/lib/signature-utils.test.js new file mode 100644 index 000000000..2226589f0 --- /dev/null +++ b/test/common/lib/signature-utils.test.js @@ -0,0 +1,129 @@ +const { artifacts, ethers } = require('hardhat') + +const { assert } = require('../../helpers/assert') +const { toBN, hex, hexConcat } = require('../../helpers/utils') +const { EvmSnapshot } = require('../../helpers/blockchain') +const { ecSign } = require('../../helpers/signatures') +const { ACCOUNTS_AND_KEYS } = require('../../helpers/constants') + +const ERC1271SignerMock = artifacts.require('ERC1271SignerMock') +const ERC1271SignerDumbMock = artifacts.require('ERC1271SignerDumbMock') +const ERC1271MutatingSignerMock = artifacts.require('ERC1271MutatingSignerMock') +const SignatureUtilsConsumer_0_4_24 = artifacts.require('SignatureUtilsConsumer_0_4_24') +const SignatureUtilsConsumer_0_8_9 = artifacts.require('SignatureUtilsConsumer_0_8_9') + +testWithConsumer(SignatureUtilsConsumer_0_4_24, 'Solidity 0.4.24') +testWithConsumer(SignatureUtilsConsumer_0_8_9, 'Solidity 0.8.9') + +function testWithConsumer(SignatureUtilsConsumer, desc) { + const ERC1271_MAGIC_VALUE = '0x1626ba7e' + + contract(`SignatureUtils.isValidSignature, ${desc}`, () => { + const msgHash = `0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef` + let sigUtils, snapshot + + before(async () => { + sigUtils = await SignatureUtilsConsumer.new() + snapshot = new EvmSnapshot(ethers.provider) + await snapshot.make() + }) + + afterEach(async () => { + await snapshot.rollback() + }) + + context(`signer is a EOA`, () => { + const [alice, bob] = ACCOUNTS_AND_KEYS + + it(`returns true given a valid ECDSA signature`, async () => { + const sig = ecSign(msgHash, alice.key) + assert.isTrue(await sigUtils.isValidSignature(alice.address, msgHash, sig.v, sig.r, sig.s)) + }) + + it(`returns false given a valid ECDSA signature from another account`, async () => { + const sig = ecSign(msgHash, bob.key) + assert.isFalse(await sigUtils.isValidSignature(alice.address, msgHash, sig.v, sig.r, sig.s)) + }) + + it(`reverts on an invalid ECDSA signature`, async () => { + const sig = ecSign(msgHash, alice.key) + + const MAX_S = '0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0' + const INVALID_S = '0x' + hex(toBN(MAX_S).addn(1), 32) + + await assert.reverts( + sigUtils.isValidSignature(alice.address, msgHash, sig.v, sig.r, INVALID_S), + `ECDSA: invalid signature 's' value` + ) + + const INVALID_V = 1 + + await assert.reverts( + sigUtils.isValidSignature(alice.address, msgHash, INVALID_V, sig.r, sig.s), + `ECDSA: invalid signature 'v' value` + ) + }) + }) + + context(`signer is a contract (ERC1271)`, () => { + const v = '0xff' + const r = '0x8badf00d8badf00d8badf00d8badf00d8badf00d8badf00d8badf00d8badf00d' + const s = '0xc00010ffc00010ffc00010ffc00010ffc00010ffc00010ffc00010ffc00010ff' + + context(`checks the signer.isValidSignature call result`, () => { + let signerContract + + before(async () => { + signerContract = await ERC1271SignerDumbMock.new() + await snapshot.make() + }) + + it(`returns true when the call returns the magic value`, async () => { + await signerContract.configure({ reverts: false, retval: ERC1271_MAGIC_VALUE }) + assert.isTrue(await sigUtils.isValidSignature(signerContract.address, msgHash, v, r, s)) + }) + + it(`returns false when the call returns any other value`, async () => { + await signerContract.configure({ reverts: false, retval: '0x' + hex(toBN(ERC1271_MAGIC_VALUE).addn(1), 4) }) + assert.isFalse(await sigUtils.isValidSignature(signerContract.address, msgHash, v, r, s)) + + await signerContract.configure({ reverts: false, retval: '0x00000000' }) + assert.isFalse(await sigUtils.isValidSignature(signerContract.address, msgHash, v, r, s)) + + await signerContract.configure({ reverts: false, retval: '0x12345678' }) + assert.isFalse(await sigUtils.isValidSignature(signerContract.address, msgHash, v, r, s)) + }) + + it(`returns false when the call reverts`, async () => { + await signerContract.configure({ reverts: true, retval: ERC1271_MAGIC_VALUE }) + assert.isFalse(await sigUtils.isValidSignature(signerContract.address, msgHash, v, r, s)) + }) + }) + + context(`packs the signature when passing to signer.isValidSignature`, () => { + // + it(`the passed signature contains r, s, and then v`, async () => { + const signerContract = await ERC1271SignerMock.new() + + await signerContract.configure({ + validHash: msgHash, + validSig: hexConcat(r, s, v), + retvalOnValid: ERC1271_MAGIC_VALUE, + retvalOnInvalid: '0x00000000', + }) + + assert.isTrue(await sigUtils.isValidSignature(signerContract.address, msgHash, v, r, s)) + }) + }) + + context(`returns false when the signer contract misbehaves`, () => { + // + it(`signer contract attempts to modify the state`, async () => { + const signerContract = await ERC1271MutatingSignerMock.new() + assert.isFalse(await sigUtils.isValidSignature(signerContract.address, msgHash, v, r, s)) + assert.equals(await signerContract.callCount_isValidSignature(), 0) + }) + }) + }) + }) +} diff --git a/test/helpers/constants.js b/test/helpers/constants.js index ae016dacd..a0d76ef80 100644 --- a/test/helpers/constants.js +++ b/test/helpers/constants.js @@ -4,6 +4,70 @@ const INITIAL_HOLDER = '0x000000000000000000000000000000000000dead' const ZERO_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000' const MAX_UINT256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' +// derived from mnemonic: clarify final village pulse require old seek excite mushroom forest satoshi video +const ACCOUNTS_AND_KEYS = [ + { + address: '0x8e81C8f0CFf3d6eA2Fe72c1A5ee49Fc377401c2D', + key: '84132dd41f32804774a98647c308c0c94a54c0f3931128c0210b6f3689d2b7e7', + }, + { + address: '0x244A0A1d21f21167c17e04EBc5FA33c885990674', + key: '31a372c197c7c5d6856bfac311a66f179bdc3bda20e78030b0fef90e40cbc83f', + }, + { + address: '0x6966f881B3Ee9074b0783CC614e3864e380B8b27', + key: '58bdc54eb2aa3a92e5a36fae01d23b7626fa89116a41e01ca3c6cb18799aee3d', + }, + { + address: '0xaC5faE80468DcC49D404d0625609C031B9AF2cb7', + key: 'd14ca7a30bc2921ddb89ea2f6c52393f91e794cd9c3c994f547eb7edeb092fd1', + }, + { + address: '0x18C246058e9e4Ae1737387fA90cD69E39f78F73A', + key: '1c09baae4343b0a66567d56769b62537623389542480f30e9acdae0624612872', + }, + { + address: '0xc4dc5dAD36fF9b8cB694E79238ECbe76ab13BcEc', + key: '2048571627de761088f2f369306f9c231e6c7ab94be1f0a0c979776a2f424328', + }, + { + address: '0x75Bf6E76D3dB629f46da549D49C9ea821CE8e9A9', + key: '9a9afb6a8e2384e4cce14824d15162bba2eed7e31df846ff77d697fed8cba0c1', + }, + { + address: '0x55937b3ae7a34F551e5aFa5BA51Fba4eD9f8FeD7', + key: '9747a0294186b8fef20ec1e4341a10c87840b18a8930b84c4c5dcd97799ba0bc', + }, + { + address: '0x1eEEBc3900803a28ca6E68Eb98FDeCf98350D97B', + key: 'cdbaf218f6332bfa630ec2abc7a8bc450b2e8746133d84450dfc2234fdfb83ef', + }, + { + address: '0x8719beDE472E67642b88DbA9aD1b1b9dc05CC60e', + key: 'c08dbf2c9aaf5dc3cd5ce5349e754de086202a5f352a512851a4f174ac246198', + }, + { + address: '0xE03701ea2248C7ca2Fed1e655ff3C803C7267302', + key: '40566af8625c93f95c5e1ea9aa42642bcbdd64fe4fe7926283d04173cb842189', + }, + { + address: '0x10506aB975D36aa781B77C1Ce204F46e8f87dA57', + key: '55ef7a25bba3449344d8a1e525ba3ca4999bdc763be4efaf9e94a4de396f8370', + }, + { + address: '0xee11cdb1f9eEe2eB40D2CF99b4fa7D782aE582A6', + key: '985117805090656613ae19743879efe4cff76049de03516debf41926313e3629', + }, + { + address: '0xB9203C29E242d7a19AE6970cDf0d873048B99419', + key: '3a37d1ad3751e697c26dd05a71cd9263c023f3e8a1d1067215044032c62ee916', + }, + { + address: '0xcC03603436Bc0Edd1e0661379f3Aa289ae967597', + key: 'db81ac68891890ec33021264ce81f9b5f9296a9fd95cdc785655db3066db2c08', + }, +] + const SLOTS_PER_EPOCH = 32 const SECONDS_PER_SLOT = 12 const EPOCHS_PER_FRAME = 225 // one day @@ -17,6 +81,7 @@ module.exports = { ZERO_ADDRESS, ZERO_BYTES32, MAX_UINT256, + ACCOUNTS_AND_KEYS, SLOTS_PER_EPOCH, SECONDS_PER_SLOT, EPOCHS_PER_FRAME, diff --git a/test/helpers/signatures.js b/test/helpers/signatures.js index 200964dab..f51ca7be9 100644 --- a/test/helpers/signatures.js +++ b/test/helpers/signatures.js @@ -1,6 +1,13 @@ const BN = require('bn.js') +const { ecsign: ecSignBuf } = require('ethereumjs-util') const { keccak256 } = require('js-sha3') -const { ecSign, strip0x, bufferFromHexString, hexStringFromBuffer } = require('../0.6.12/helpers') + +const { strip0x, bufferFromHexString, hexStringFromBuffer } = require('./utils') + +function ecSign(digest, privateKey) { + const { v, r, s } = ecSignBuf(bufferFromHexString(digest), bufferFromHexString(privateKey)) + return { v, r: hexStringFromBuffer(r), s: hexStringFromBuffer(s) } +} // Converts a ECDSA signature to the format provided in https://eips.ethereum.org/EIPS/eip-2098. function toEip2098({ v, r, s }) { @@ -127,6 +134,9 @@ function hexToBytes(hex) { } module.exports = { + ecSign, + toEip2098, + keccak256, signDepositData, signPauseData, DSMPauseMessage, diff --git a/test/helpers/signing-keys.js b/test/helpers/signing-keys.js index db0e72266..1b7e16dc8 100644 --- a/test/helpers/signing-keys.js +++ b/test/helpers/signing-keys.js @@ -3,8 +3,7 @@ const SIGNATURE_LENGTH = 96 const EMPTY_PUBLIC_KEY = '0x' + '0'.repeat(2 * PUBKEY_LENGTH) const EMPTY_SIGNATURE = '0x' + '0'.repeat(2 * SIGNATURE_LENGTH) -const { pad, hexConcat, hexSplit } = require('./utils') -const { strip0x } = require('../0.6.12/helpers') +const { strip0x, pad, hexConcat, hexSplit } = require('./utils') class ValidatorKeys { constructor(publicKeys, signatures) { diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 5a903f1df..eeb3da60d 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -71,6 +71,14 @@ function strip0x(s) { return s.substr(0, 2) === '0x' ? s.substr(2) : s } +function bufferFromHexString(hex) { + return Buffer.from(strip0x(hex), 'hex') +} + +function hexStringFromBuffer(buf) { + return '0x' + buf.toString('hex') +} + // Divides a BN by 1e15 const div15 = (bn) => bn.div(new BN(1000000)).div(new BN(1000000)).div(new BN(1000)) @@ -170,6 +178,8 @@ module.exports = { toBN, hex, strip0x, + bufferFromHexString, + hexStringFromBuffer, div15, e9, e18, From 5db18bc8b2b6ca013b2d65b371cde212b52e837c Mon Sep 17 00:00:00 2001 From: Sam Kozin Date: Sun, 12 Mar 2023 18:53:02 +0200 Subject: [PATCH 230/236] stETH: include ERC-1271 sigs in permit() tests --- .../test_helpers/ERC1271PermitSignerMock.sol | 21 +++ test/0.4.24/helpers/permit_helpers.js | 36 +++-- test/0.4.24/stethpermit.test.js | 133 +++++++++++------- test/helpers/utils.js | 5 +- 4 files changed, 129 insertions(+), 66 deletions(-) create mode 100644 contracts/common/test_helpers/ERC1271PermitSignerMock.sol diff --git a/contracts/common/test_helpers/ERC1271PermitSignerMock.sol b/contracts/common/test_helpers/ERC1271PermitSignerMock.sol new file mode 100644 index 000000000..af2999616 --- /dev/null +++ b/contracts/common/test_helpers/ERC1271PermitSignerMock.sol @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 Lido +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity 0.8.9; + + +contract ERC1271PermitSignerMock { + bytes4 public constant ERC1271_MAGIC_VALUE = 0x1626ba7e; + + function sign(bytes32 hash) public view returns (bytes1 v, bytes32 r, bytes32 s) { + v = 0x42; + r = hash; + s = bytes32(bytes20(address(this))); + } + + function isValidSignature(bytes32 hash, bytes memory sig) external view returns (bytes4) { + (bytes1 v, bytes32 r, bytes32 s) = sign(hash); + bytes memory validSig = abi.encodePacked(r, s, v); + return keccak256(sig) == keccak256(validSig) ? ERC1271_MAGIC_VALUE : bytes4(0); + } +} diff --git a/test/0.4.24/helpers/permit_helpers.js b/test/0.4.24/helpers/permit_helpers.js index 87a93a9c3..c7fca8c7c 100644 --- a/test/0.4.24/helpers/permit_helpers.js +++ b/test/0.4.24/helpers/permit_helpers.js @@ -11,33 +11,39 @@ const permitTypeHash = web3.utils.keccak256( ) function signTransferAuthorization(from, to, value, validAfter, validBefore, nonce, domainSeparator, privateKey) { - return signEIP712( - domainSeparator, - transferWithAuthorizationTypeHash, - ['address', 'address', 'uint256', 'uint256', 'uint256', 'bytes32'], - [from, to, value, validAfter, validBefore, nonce], - privateKey - ) + const digest = calculateTransferAuthorizationDigest(from, to, value, validAfter, validBefore, nonce, domainSeparator) + return ecSign(digest, privateKey) } function signPermit(owner, spender, value, nonce, deadline, domainSeparator, privateKey) { - return signEIP712( + const digest = calculatePermitDigest(owner, spender, value, nonce, deadline, domainSeparator) + return ecSign(digest, privateKey) +} + +function calculatePermitDigest(owner, spender, value, nonce, deadline, domainSeparator) { + return calculateEIP712Digest( domainSeparator, permitTypeHash, ['address', 'address', 'uint256', 'uint256', 'uint256'], - [owner, spender, value, nonce, deadline], - privateKey + [owner, spender, value, nonce, deadline] ) } -function signEIP712(domainSeparator, typeHash, types, parameters, privateKey) { - const digest = web3.utils.keccak256( +function calculateTransferAuthorizationDigest(from, to, value, validAfter, validBefore, nonce, domainSeparator) { + return calculateEIP712Digest( + domainSeparator, + transferWithAuthorizationTypeHash, + ['address', 'address', 'uint256', 'uint256', 'uint256', 'bytes32'], + [from, to, value, validAfter, validBefore, nonce] + ) +} + +function calculateEIP712Digest(domainSeparator, typeHash, types, parameters) { + return web3.utils.keccak256( '0x1901' + strip0x(domainSeparator) + strip0x(web3.utils.keccak256(web3.eth.abi.encodeParameters(['bytes32', ...types], [typeHash, ...parameters]))) ) - - return ecSign(digest, privateKey) } function makeDomainSeparator(name, version, chainId, verifyingContract) { @@ -60,4 +66,6 @@ module.exports = { permitTypeHash, signTransferAuthorization, makeDomainSeparator, + calculatePermitDigest, + calculateTransferAuthorizationDigest, } diff --git a/test/0.4.24/stethpermit.test.js b/test/0.4.24/stethpermit.test.js index 881c95b51..c2dc30398 100644 --- a/test/0.4.24/stethpermit.test.js +++ b/test/0.4.24/stethpermit.test.js @@ -4,12 +4,18 @@ const { assert } = require('../helpers/assert') const crypto = require('crypto') const { ACCOUNTS_AND_KEYS, MAX_UINT256, ZERO_ADDRESS } = require('./helpers/constants') const { bn } = require('@aragon/contract-helpers-test') -const { signPermit, signTransferAuthorization, makeDomainSeparator } = require('./helpers/permit_helpers') -const { ETH, hexStringFromBuffer } = require('../helpers/utils') -const { EvmSnapshot } = require('../helpers/blockchain') +const { + calculatePermitDigest, + calculateTransferAuthorizationDigest, + makeDomainSeparator, +} = require('./helpers/permit_helpers') +const { ETH, hex, hexStringFromBuffer } = require('../helpers/utils') +const { ecSign } = require('../helpers/signatures') +const { EvmSnapshot, setBalance } = require('../helpers/blockchain') const EIP712StETH = artifacts.require('EIP712StETH') const StETHPermit = artifacts.require('StETHPermitMock') +const ERC1271PermitSignerMock = artifacts.require('ERC1271PermitSignerMock') contract('StETHPermit', ([deployer, ...accounts]) => { let stEthPermit, eip712StETH, chainId, domainSeparator @@ -26,25 +32,61 @@ contract('StETHPermit', ([deployer, ...accounts]) => { await snapshot.make() }) + const getAccountsEOA = async () => { + return { + alice: ACCOUNTS_AND_KEYS[0], + bob: ACCOUNTS_AND_KEYS[1], + } + } + + const getAccountsEIP1271 = async () => { + const alice = await ERC1271PermitSignerMock.new() + const bob = await ERC1271PermitSignerMock.new() + return { alice, bob } + } + + const signEOA = async (digest, acct) => { + return ecSign(digest, acct.key) + } + + const signEIP1271 = async (digest, acct) => { + const sig = await acct.sign(digest) + return { v: hex(sig.v), r: hex(sig.r), s: hex(sig.s) } + } + afterEach(async () => { await snapshot.rollback() }) - context('permit', () => { - const [alice, bob] = ACCOUNTS_AND_KEYS - const charlie = accounts[1] + const test = ({ getAccounts, sign, desc }) => { + let alice, bob + let permitParams + const charlie = accounts[3] + + before(async () => { + const accts = await getAccounts() + alice = accts.alice + bob = accts.bob + + permitParams = { + owner: alice.address, + spender: bob.address, + value: 6e6, + nonce: 0, + deadline: MAX_UINT256, + } - const initialTotalSupply = 100e6 - const initialBalance = 90e6 + await snapshot.make() + }) - const permitParams = { - owner: alice.address, - spender: bob.address, - value: 6e6, - nonce: 0, - deadline: MAX_UINT256, + const signPermit = async (owner, spender, value, nonce, domainSeparator, deadline, acct) => { + const digest = calculatePermitDigest(owner, spender, value, nonce, domainSeparator, deadline) + return await sign(digest, acct) } + const initialTotalSupply = 100e6 + const initialBalance = 90e6 + beforeEach(async () => { await stEthPermit.setTotalPooledEther(initialTotalSupply, { from: deployer }) await stEthPermit.mintShares(permitParams.owner, initialBalance, { from: deployer }) @@ -76,7 +118,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { // on behalf, and sign with Alice's key let nonce = 0 - let { v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key) + let { v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice) // check that the allowance is initially zero assert.equals(await stEthPermit.allowance(owner, spender), bn(0)) @@ -98,7 +140,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { // increment nonce nonce = 1 value = 4e5 - ;({ v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key)) + ;({ v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice)) // submit the permit const receipt2 = await stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie }) @@ -114,7 +156,7 @@ contract('StETHPermit', ([deployer, ...accounts]) => { it('reverts if the signature does not match given parameters', async () => { const { owner, spender, value, nonce, deadline } = permitParams // create a signed permit - const { v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key) + const { v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice) // try to cheat by claiming the approved amount + 1 await assert.reverts( @@ -151,20 +193,18 @@ contract('StETHPermit', ([deployer, ...accounts]) => { const { owner, spender, value, nonce, deadline } = permitParams // create a signed permit to grant Bob permission to spend // Alice's funds on behalf, but sign with Bob's key instead of Alice's - const { v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, bob.key) + const { v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, bob) // try to cheat by submitting the permit that is signed by a // wrong person await assert.reverts( - stEthPermit.permit(owner, spender, value, deadline, v, r, s, { - from: charlie, - }), + stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie }), 'INVALID_SIGNATURE' ) // unlock bob account (allow transactions originated from bob.address) await ethers.provider.send('hardhat_impersonateAccount', [bob.address]) - await web3.eth.sendTransaction({ to: bob.address, from: accounts[0], value: ETH(10) }) + await setBalance(bob.address, ETH(10)) // even Bob himself can't call permit with the invalid sig await assert.reverts( @@ -179,20 +219,18 @@ contract('StETHPermit', ([deployer, ...accounts]) => { const { owner, spender, value, nonce } = permitParams // create a signed permit that already invalid const deadline = (await stEthPermit.getBlockTime()).toString() - 1 - const { v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key) + const { v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice) // try to submit the permit that is expired await assert.reverts( - stEthPermit.permit(owner, spender, value, deadline, v, r, s, { - from: charlie, - }), + stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie }), 'DEADLINE_EXPIRED' ) { // create a signed permit that valid for 1 minute (approximately) const deadline1min = (await stEthPermit.getBlockTime()).toString() + 60 - const { v, r, s } = signPermit(owner, spender, value, nonce, deadline1min, domainSeparator, alice.key) + const { v, r, s } = await signPermit(owner, spender, value, nonce, deadline1min, domainSeparator, alice) const receipt = await stEthPermit.permit(owner, spender, value, deadline1min, v, r, s, { from: charlie }) assert.equals(await stEthPermit.nonces(owner), bn(1)) @@ -204,15 +242,13 @@ contract('StETHPermit', ([deployer, ...accounts]) => { const { owner, spender, value, deadline } = permitParams const nonce = 1 // create a signed permit - const { v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key) + const { v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice) // check that the next nonce expected is 0, not 1 assert.equals(await stEthPermit.nonces(owner), bn(0)) // try to submit the permit await assert.reverts( - stEthPermit.permit(owner, spender, value, deadline, v, r, s, { - from: charlie, - }), + stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie }), 'INVALID_SIGNATURE' ) }) @@ -220,22 +256,20 @@ contract('StETHPermit', ([deployer, ...accounts]) => { it('reverts if the permit has already been used', async () => { const { owner, spender, value, nonce, deadline } = permitParams // create a signed permit - const { v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key) + const { v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice) // submit the permit await stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie }) // try to submit the permit again await assert.reverts( - stEthPermit.permit(owner, spender, value, deadline, v, r, s, { - from: charlie, - }), + stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie }), 'INVALID_SIGNATURE' ) - // unlock bob account (allow transactions originated from bob.address) + // unlock alice account (allow transactions originated from alice.address) await ethers.provider.send('hardhat_impersonateAccount', [alice.address]) - await web3.eth.sendTransaction({ to: alice.address, from: accounts[0], value: ETH(10) }) + await setBalance(alice.address, ETH(10)) // try to submit the permit again from Alice herself await assert.reverts( @@ -249,14 +283,14 @@ contract('StETHPermit', ([deployer, ...accounts]) => { it('reverts if the permit has a nonce that has already been used by the signer', async () => { const { owner, spender, value, nonce, deadline } = permitParams // create a signed permit - const permit = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key) + const permit = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice) // submit the permit await stEthPermit.permit(owner, spender, value, deadline, permit.v, permit.r, permit.s, { from: charlie }) // create another signed permit with the same nonce, but // with different parameters - const permit2 = signPermit(owner, spender, 1e6, nonce, deadline, domainSeparator, alice.key) + const permit2 = await signPermit(owner, spender, 1e6, nonce, deadline, domainSeparator, alice) // try to submit the permit again await assert.reverts( @@ -270,13 +304,11 @@ contract('StETHPermit', ([deployer, ...accounts]) => { // create a signed permit that attempts to grant allowance to the // zero address const spender = ZERO_ADDRESS - const { v, r, s } = signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice.key) + const { v, r, s } = await signPermit(owner, spender, value, nonce, deadline, domainSeparator, alice) // try to submit the permit with invalid approval parameters await assert.reverts( - stEthPermit.permit(owner, spender, value, deadline, v, r, s, { - from: charlie, - }), + stEthPermit.permit(owner, spender, value, deadline, v, r, s, { from: charlie }), 'APPROVE_TO_ZERO_ADDR' ) }) @@ -286,24 +318,25 @@ contract('StETHPermit', ([deployer, ...accounts]) => { // create a signed permit for a transfer const validAfter = 0 const nonce = hexStringFromBuffer(crypto.randomBytes(32)) - const { v, r, s } = signTransferAuthorization( + const digest = calculateTransferAuthorizationDigest( from, to, value, validAfter, validBefore, nonce, - domainSeparator, - alice.key + domainSeparator ) + const { v, r, s } = await sign(digest, alice) // try to submit the transfer permit await assert.reverts( - stEthPermit.permit(from, to, value, validBefore, v, r, s, { - from: charlie, - }), + stEthPermit.permit(from, to, value, validBefore, v, r, s, { from: charlie }), 'INVALID_SIGNATURE' ) }) - }) + } + + context(`permit (ECDSA)`, () => test({ getAccounts: getAccountsEOA, sign: signEOA })) + context(`permit (EIP-1271)`, () => test({ getAccounts: getAccountsEIP1271, sign: signEIP1271 })) }) diff --git a/test/helpers/utils.js b/test/helpers/utils.js index eeb3da60d..ee296ec8b 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -63,8 +63,9 @@ const toBN = (obj) => { return str.startsWith('0x') ? new BN(str.substring(2), 16) : new BN(str, 10) } -function hex(n, byteLen) { - return n.toString(16).padStart(byteLen * 2, '0') +function hex(n, byteLen = undefined) { + const s = n.toString(16) + return byteLen === undefined ? s : s.padStart(byteLen * 2, '0') } function strip0x(s) { From fd13ecd4d88f30239d78a380bcec9c6c0d75a6df Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Mar 2023 10:36:59 +0300 Subject: [PATCH 231/236] chore: fix linter error --- test/common/lib/signature-utils.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common/lib/signature-utils.test.js b/test/common/lib/signature-utils.test.js index 2226589f0..ee06c0c1f 100644 --- a/test/common/lib/signature-utils.test.js +++ b/test/common/lib/signature-utils.test.js @@ -1,4 +1,4 @@ -const { artifacts, ethers } = require('hardhat') +const { artifacts, ethers, contract } = require('hardhat') const { assert } = require('../../helpers/assert') const { toBN, hex, hexConcat } = require('../../helpers/utils') From c81cce1aee3ad59934c26b98037af72f7c23b81e Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Mar 2023 10:59:44 +0300 Subject: [PATCH 232/236] chore: balance require->assert for initialHolder --- contracts/0.4.24/StETH.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index f961e9456..ede4e1386 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -512,11 +512,13 @@ contract StETH is IERC20, Pausable { * Allows to get rid of zero checks for `totalShares` and `totalPooledEther` * and overcome corner cases. * + * NB: reverts if the current contract's balance is zero. + * * @dev must be invoked before using the token */ function _bootstrapInitialHolder() internal returns (uint256) { uint256 balance = address(this).balance; - require(balance != 0, "EMPTY_INIT_BALANCE"); + assert(balance != 0); if (_getTotalShares() == 0) { // if protocol is empty bootstrap it with the contract's balance From 4ea55e29e8de82645619b17c29fc374d03042f95 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Mar 2023 11:10:48 +0300 Subject: [PATCH 233/236] feat: forbid stETH transfers to the contract itself --- contracts/0.4.24/StETH.sol | 3 ++- test/0.4.24/steth.test.js | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/contracts/0.4.24/StETH.sol b/contracts/0.4.24/StETH.sol index ede4e1386..771276090 100644 --- a/contracts/0.4.24/StETH.sol +++ b/contracts/0.4.24/StETH.sol @@ -426,13 +426,14 @@ contract StETH is IERC20, Pausable { * Requirements: * * - `_sender` cannot be the zero address. - * - `_recipient` cannot be the zero address. + * - `_recipient` cannot be the zero address or the `stETH` token contract itself * - `_sender` must hold at least `_sharesAmount` shares. * - the contract must not be paused. */ function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal { require(_sender != address(0), "TRANSFER_FROM_ZERO_ADDR"); require(_recipient != address(0), "TRANSFER_TO_ZERO_ADDR"); + require(_recipient != address(this), "TRANSFER_TO_STETH_CONTRACT"); _whenNotStopped(); uint256 currentSenderShares = shares[_sender]; diff --git a/test/0.4.24/steth.test.js b/test/0.4.24/steth.test.js index abb37ed4a..4cd0ca01e 100644 --- a/test/0.4.24/steth.test.js +++ b/test/0.4.24/steth.test.js @@ -91,6 +91,10 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { await assert.reverts(stEth.transfer(ZERO_ADDRESS, tokens(1), { from: user1 }), 'TRANSFER_TO_ZERO_ADDR') }) + it('reverts when recipient is the `stETH` contract itself', async () => { + await assert.reverts(stEth.transfer(stEth.address, tokens(1), { from: user1 }), 'TRANSFER_TO_STETH_CONTRACT') + }) + it('reverts when the sender does not have enough balance', async () => { await assert.reverts(stEth.transfer(user2, tokens(101), { from: user1 }), 'BALANCE_EXCEEDED') await assert.reverts(stEth.transfer(user1, bn('1'), { from: user2 }), 'BALANCE_EXCEEDED') @@ -173,6 +177,13 @@ contract('StETH', ([_, __, user1, user2, user3, nobody]) => { ) }) + it('reverts when recipient is the `stETH` contract itself', async () => { + await assert.reverts( + stEth.transferFrom(user1, stEth.address, tokens(1), { from: user2 }), + 'TRANSFER_TO_STETH_CONTRACT' + ) + }) + it('reverts when sender is zero address', async () => { await assert.reverts( stEth.transferFrom(ZERO_ADDRESS, user3, tokens(0), { from: user2 }), From e3e8b6daf7f397363d0d904c5625f4571ab534d1 Mon Sep 17 00:00:00 2001 From: Artyom Veremeenko Date: Mon, 13 Mar 2023 21:04:52 +0400 Subject: [PATCH 234/236] doc: StakingModule.lastDeposit{At,Block} of StakingModule change if 0 deposit --- contracts/0.8.9/StakingRouter.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/0.8.9/StakingRouter.sol b/contracts/0.8.9/StakingRouter.sol index 2d0f566a2..e47c09e46 100644 --- a/contracts/0.8.9/StakingRouter.sol +++ b/contracts/0.8.9/StakingRouter.sol @@ -77,8 +77,10 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version /// @notice name of staking module string name; /// @notice block.timestamp of the last deposit of the staking module + /// @dev NB: lastDepositAt gets updated even if the deposit value was 0 and no actual deposit happened uint64 lastDepositAt; /// @notice block.number of the last deposit of the staking module + /// @dev NB: lastDepositBlock gets updated even if the deposit value was 0 and no actual deposit happened uint256 lastDepositBlock; /// @notice number of exited validators uint256 exitedValidatorsCount; From 3b7b3848a8f637209eb8c2b65546a1e80f513762 Mon Sep 17 00:00:00 2001 From: Alexey Potapkin Date: Mon, 13 Mar 2023 21:53:24 +0200 Subject: [PATCH 235/236] =?UTF-8?q?=F0=9F=92=85(wq):=20public=20constant?= =?UTF-8?q?=20and=20arg=20renaming?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/0.8.9/WithdrawalQueue.sol | 10 +++++----- contracts/0.8.9/WithdrawalQueueBase.sol | 2 +- lib/abi/WithdrawalQueue.json | 2 +- lib/abi/WithdrawalQueueBase.json | 2 +- lib/abi/WithdrawalQueueERC721.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/0.8.9/WithdrawalQueue.sol b/contracts/0.8.9/WithdrawalQueue.sol index ee48452a8..162c5fed6 100644 --- a/contracts/0.8.9/WithdrawalQueue.sol +++ b/contracts/0.8.9/WithdrawalQueue.sol @@ -319,11 +319,11 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit /// @dev should be called by oracle /// /// @param _isBunkerModeNow is bunker mode reported by oracle - /// @param _sinceTimestamp timestamp of start of the bunker mode + /// @param _bunkerStartTimestamp timestamp of start of the bunker mode /// @param _currentReportTimestamp timestamp of the current report ref slot - function onOracleReport(bool _isBunkerModeNow, uint256 _sinceTimestamp, uint256 _currentReportTimestamp) external { + function onOracleReport(bool _isBunkerModeNow, uint256 _bunkerStartTimestamp, uint256 _currentReportTimestamp) external { _checkRole(ORACLE_ROLE, msg.sender); - if (_sinceTimestamp >= block.timestamp) revert InvalidReportTimestamp(); + if (_bunkerStartTimestamp >= block.timestamp) revert InvalidReportTimestamp(); if (_currentReportTimestamp >= block.timestamp) revert InvalidReportTimestamp(); _setLastReportTimestamp(_currentReportTimestamp); @@ -334,9 +334,9 @@ abstract contract WithdrawalQueue is AccessControlEnumerable, PausableUntil, Wit if (_isBunkerModeNow != isBunkerModeWasSetBefore) { // write previous timestamp to enable bunker or max uint to disable if (_isBunkerModeNow) { - BUNKER_MODE_SINCE_TIMESTAMP_POSITION.setStorageUint256(_sinceTimestamp); + BUNKER_MODE_SINCE_TIMESTAMP_POSITION.setStorageUint256(_bunkerStartTimestamp); - emit BunkerModeEnabled(_sinceTimestamp); + emit BunkerModeEnabled(_bunkerStartTimestamp); } else { BUNKER_MODE_SINCE_TIMESTAMP_POSITION.setStorageUint256(BUNKER_MODE_DISABLED_TIMESTAMP); diff --git a/contracts/0.8.9/WithdrawalQueueBase.sol b/contracts/0.8.9/WithdrawalQueueBase.sol index 57232329d..4e5dfd896 100644 --- a/contracts/0.8.9/WithdrawalQueueBase.sol +++ b/contracts/0.8.9/WithdrawalQueueBase.sol @@ -19,7 +19,7 @@ abstract contract WithdrawalQueueBase { /// @notice precision base for share rate and discounting factor values in the contract uint256 internal constant E27_PRECISION_BASE = 1e27; /// @dev maximal length of the batches array that oracle should deliver on finalization - uint256 internal constant MAX_BATCHES_LENGTH = 36; + uint256 public constant MAX_BATCHES_LENGTH = 36; /// @dev return value for the `find...` methods in case of no result uint256 internal constant NOT_FOUND = 0; diff --git a/lib/abi/WithdrawalQueue.json b/lib/abi/WithdrawalQueue.json index c1b83d496..ea968038c 100644 --- a/lib/abi/WithdrawalQueue.json +++ b/lib/abi/WithdrawalQueue.json @@ -1 +1 @@ -[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"name":"PauseUntilMustBeInFuture","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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"ORACLE_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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"AdminZeroAddress","type":"error"},{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[],"name":"InvalidContractVersionIncrement","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":[],"name":"PauseUntilMustBeInFuture","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":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[],"name":"ResumedExpected","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"received","type":"uint256"}],"name":"UnexpectedContractVersion","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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"}],"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":"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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BATCHES_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"ORACLE_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":"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":[],"name":"bunkerModeSinceTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_bunkerStartTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueBase.json b/lib/abi/WithdrawalQueueBase.json index 1d8a9dd6d..952b59cc8 100644 --- a/lib/abi/WithdrawalQueueBase.json +++ b/lib/abi/WithdrawalQueueBase.json @@ -1 +1 @@ -[{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","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"}] \ No newline at end of file +[{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","type":"error"},{"inputs":[{"internalType":"uint256","name":"_hint","type":"uint256"}],"name":"InvalidHint","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":[],"name":"InvalidState","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":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"RequestNotFoundOrNotFinalized","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"maxExpected","type":"uint256"}],"name":"TooMuchEtherToFinalize","type":"error"},{"inputs":[],"name":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroShareRate","type":"error"},{"inputs":[],"name":"ZeroTimestamp","type":"error"},{"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":"MAX_BATCHES_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"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":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"stateMutability":"view","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"}] \ No newline at end of file diff --git a/lib/abi/WithdrawalQueueERC721.json b/lib/abi/WithdrawalQueueERC721.json index 979d69eda..61bdc2836 100644 --- a/lib/abi/WithdrawalQueueERC721.json +++ b/lib/abi/WithdrawalQueueERC721.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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","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":[],"name":"InvalidState","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":"PauseUntilMustBeInFuture","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_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":"ORACLE_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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_sinceTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ 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":"ApprovalToOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BatchesAreNotSorted","type":"error"},{"inputs":[],"name":"CantSendValueRecipientMayHaveReverted","type":"error"},{"inputs":[],"name":"EmptyBatches","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":[],"name":"InvalidState","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":"PauseUntilMustBeInFuture","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":"RequestNotFoundOrNotFinalized","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":"TransferToThemselves","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":"ZeroAmountOfETH","type":"error"},{"inputs":[],"name":"ZeroMetadata","type":"error"},{"inputs":[],"name":"ZeroPauseDuration","type":"error"},{"inputs":[],"name":"ZeroRecipient","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"}],"name":"InitializedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftDescriptorAddress","type":"address"}],"name":"NftDescriptorAddressSet","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":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGE_TOKEN_URI_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BATCHES_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"ORACLE_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":"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":"_maxShareRate","type":"uint256"},{"internalType":"uint256","name":"_maxTimestamp","type":"uint256"},{"internalType":"uint256","name":"_maxRequestsPerCall","type":"uint256"},{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"_state","type":"tuple"}],"name":"calculateFinalizationBatches","outputs":[{"components":[{"internalType":"uint256","name":"remainingEthBudget","type":"uint256"},{"internalType":"bool","name":"finished","type":"bool"},{"internalType":"uint256[36]","name":"batches","type":"uint256[36]"},{"internalType":"uint256","name":"batchesLength","type":"uint256"}],"internalType":"struct WithdrawalQueueBase.BatchesCalculationState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"claimWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"claimWithdrawalsTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"payable","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":"_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":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_hints","type":"uint256[]"}],"name":"getClaimableEther","outputs":[{"internalType":"uint256[]","name":"claimableEthValues","type":"uint256[]"}],"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":[],"name":"getNFTDescriptorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getResumeSinceTimestamp","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":"address","name":"_owner","type":"address"}],"name":"getWithdrawalRequests","outputs":[{"internalType":"uint256[]","name":"requestsIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"}],"name":"getWithdrawalStatus","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":"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"}],"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":"bool","name":"_isBunkerModeNow","type":"bool"},{"internalType":"uint256","name":"_bunkerStartTimestamp","type":"uint256"},{"internalType":"uint256","name":"_currentReportTimestamp","type":"uint256"}],"name":"onOracleReport","outputs":[],"stateMutability":"nonpayable","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":"pauseFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pauseUntilInclusive","type":"uint256"}],"name":"pauseUntil","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_batches","type":"uint256[]"},{"internalType":"uint256","name":"_maxShareRate","type":"uint256"}],"name":"prefinalize","outputs":[{"internalType":"uint256","name":"ethToLock","type":"uint256"},{"internalType":"uint256","name":"sharesToBurn","type":"uint256"}],"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":"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":"address","name":"_nftDescriptorAddress","type":"address"}],"name":"setNFTDescriptorAddress","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"}] \ No newline at end of file From 4ec32dce6ed85758d9201a3df3352408f9f23cb0 Mon Sep 17 00:00:00 2001 From: Eugene Mamin Date: Mon, 13 Mar 2023 23:05:26 +0300 Subject: [PATCH 236/236] fix: sync ext interfaces in Lido --- contracts/0.4.24/Lido.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/0.4.24/Lido.sol b/contracts/0.4.24/Lido.sol index 52856d13f..852a8fed9 100644 --- a/contracts/0.4.24/Lido.sol +++ b/contracts/0.4.24/Lido.sol @@ -82,7 +82,7 @@ interface IWithdrawalVault { interface IStakingRouter { function deposit( - uint256 _maxDepositsCount, + uint256 _depositsCount, uint256 _stakingModuleId, bytes _depositCalldata ) external payable; @@ -108,7 +108,7 @@ interface IStakingRouter { uint16 modulesFee, uint16 treasuryFee ); - function getStakingModuleMaxDepositsCount(uint256 _stakingModuleId, uint256 _depositableEther) + function getStakingModuleMaxDepositsCount(uint256 _stakingModuleId, uint256 _maxDepositsValue) external view returns (uint256); @@ -117,6 +117,7 @@ interface IStakingRouter { interface IWithdrawalQueue { function prefinalize(uint256[] _batches, uint256 _maxShareRate) external + view returns (uint256 ethToLock, uint256 sharesToBurn); function finalize(uint256[] _batches, uint256 _maxShareRate) external payable; @@ -865,7 +866,7 @@ contract Lido is Versioned, StETHPermit, AragonApp { function _calculateWithdrawals( OracleReportContracts memory _contracts, OracleReportedData memory _reportedData - ) internal returns ( + ) internal view returns ( uint256 etherToLock, uint256 sharesToBurn ) { IWithdrawalQueue withdrawalQueue = IWithdrawalQueue(_contracts.withdrawalQueue);