Skip to content

Commit 842956b

Browse files
committed
Friendly revert when validators decreased #179
Fixes unobvious revert reason with `MATH_SUB_UNDERFLOW` when oracle pushes decreased number of beacon validators.
1 parent 9db7845 commit 842956b

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

contracts/0.4.24/Lido.sol

+7-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,13 @@ contract Lido is ILido, IsContract, Pausable, AragonApp {
239239
uint256 depositedValidators = DEPOSITED_VALIDATORS_VALUE_POSITION.getStorageUint256();
240240
require(_beaconValidators <= depositedValidators, "REPORTED_MORE_DEPOSITED");
241241

242-
uint256 appearedValidators = _beaconValidators.sub(BEACON_VALIDATORS_VALUE_POSITION.getStorageUint256());
242+
uint256 beaconValidators = BEACON_VALIDATORS_VALUE_POSITION.getStorageUint256();
243+
// Since the calculation of funds in the ingress queue is based on the number of validators
244+
// that are in a transient state (deposited but not seen on beacon yet), we can't decrease the previously
245+
// reported number (we'll be unable to figure out who is in the queue and count them).
246+
// See LIP-1 for details https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-1.md
247+
require(_beaconValidators >= beaconValidators, "REPORTED_LESS_VALIDATORS");
248+
uint256 appearedValidators = _beaconValidators.sub(beaconValidators);
243249

244250
// RewardBase is the amount of money that is not included in the reward calculation
245251
// Just appeared validators * 32 added to the previously reported beacon balance

test/0.4.24/lidoPushBeacon.test.js

+24-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ contract('Lido pushBeacon', ([appManager, voting, user1, user2, user3, nobody])
204204
assertBn(await app.totalRewards(), ETH(1))
205205
})
206206

207-
it('report BcnValidators:3 = revert', async () => {
207+
it('report BcnValidators:3 = revert with REPORTED_MORE_DEPOSITED', async () => {
208208
await assertRevert(oracle.reportBeacon(110, 3, ETH(65), { from: user2 }), 'REPORTED_MORE_DEPOSITED')
209209
checkStat({ depositedValidators: 2, beaconValidators: 1, beaconBalance: ETH(30) })
210210
assertBn(await app.getBufferedEther(), ETH(5))
@@ -213,4 +213,27 @@ contract('Lido pushBeacon', ([appManager, voting, user1, user2, user3, nobody])
213213
assertBn(await app.totalRewards(), 0)
214214
})
215215
})
216+
217+
context('with depositedVals=5, beaconVals=4, bcnBal=1, bufferedEth=0', async () => {
218+
beforeEach(async function () {
219+
await app.setDepositedValidators(5)
220+
await app.setBeaconBalance(ETH(1))
221+
await app.setBufferedEther({ from: user1, value: ETH(0) })
222+
await app.setBeaconValidators(4)
223+
})
224+
225+
// See LIP-1 for explanation
226+
// https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-1.md
227+
it('report decreased BcnValidators:3 = revert with REPORTED_LESS_VALIDATORS', async () => {
228+
await assertRevert(oracle.reportBeacon(123, 3, ETH(1), { from: user2 }), 'REPORTED_LESS_VALIDATORS')
229+
await assertRevert(oracle.reportBeacon(321, 2, ETH(10), { from: user2 }), 'REPORTED_LESS_VALIDATORS')
230+
await assertRevert(oracle.reportBeacon(12345, 1, ETH(123), { from: user2 }), 'REPORTED_LESS_VALIDATORS')
231+
// values stay intact
232+
checkStat({ depositedValidators: 5, beaconValidators: 4, beaconBalance: ETH(1) })
233+
assertBn(await app.getBufferedEther(), ETH(0))
234+
assertBn(await app.getTotalPooledEther(), ETH(33))
235+
assert.equal(await app.distributeRewardsCalled(), false)
236+
assertBn(await app.totalRewards(), 0)
237+
})
238+
})
216239
})

0 commit comments

Comments
 (0)