Introduce Redeems Reserve#1746
Conversation
Hardhat Unit Tests Coverage SummaryDetailsDiff against masterResults for commit: 8b27fc4 Minimum allowed coverage is ♻️ This comment has been updated with latest results |
b13aec7 to
972e610
Compare
972e610 to
7f748f7
Compare
| reserveManager: HardhatEthersSigner, | ||
| opts: { | ||
| deposit: bigint; | ||
| ratioBP: bigint; |
There was a problem hiding this comment.
Consider naming it redeemsReserveTarget, similar to depositsReserveTarget
| /** Validates reserve-related state derived from total pooled ether */ | ||
| export function assertReserveState(state: ProtocolState, ratioBP: bigint) { | ||
| expect(state.reserveTarget).to.equal(expectedReserveTarget(state.internalEther, ratioBP)); | ||
| expect(state.reserve).to.equal(state.reserveTarget); |
There was a problem hiding this comment.
Seems like it works only when the reserve wasn't used and buffer has enough eth
There was a problem hiding this comment.
Yes, in cases where reserve drained/not replenished it uses explicit check
| await assertReserveAllocationInvariant(lido); | ||
| assertReserveState(protocol0, DEFAULT_RATIO_BP); | ||
|
|
||
| // --- Request withdrawals exceeding unreserved buffer --- |
There was a problem hiding this comment.
Consider adding an assert which checks that withdrawable ether actually less than the total withdrawals amount
| const sharedAllocationBefore = beforeReport.withdrawalsReserve + getUnreserved(beforeReport); | ||
|
|
||
| // --- Path A: report with growthShare = 0 --- | ||
| await doReport(ctx, { skipWithdrawals: true, excludeVaultsBalances: true }); |
There was a problem hiding this comment.
Maybe it would make sense to simulate rewards in this test, to verify that withdrawalsReserve grows while the redeem reserve stays unchanged after the report.
| } | ||
|
|
||
| /** Advances chain time past the oracle requestTimestampMargin */ | ||
| export async function advanceToReportableTime(ctx: ProtocolContext) { |
There was a problem hiding this comment.
Nitpick: the naming is a bit misleading. It suggests that this helper advances time to the point where the oracle can report, while it actually advances time to the point where all withdrawal requests satisfy the creation-time sanity check.
|
|
||
| await redeemExact(lido, holder, fix, REDEEM_AMOUNT); | ||
|
|
||
| await doReport(ctx, { clDiff: CL_LOSS }); |
There was a problem hiding this comment.
Consider adding an assertion to verify that the share rate decreased, confirming that the report was indeed negative
| // --- Internalize bad debt, process report --- | ||
| const badDebtShares = | ||
| (await dashboard.liabilityShares()) - (await lido.getSharesByPooledEth(await dashboard.totalValue())); | ||
| const internalizedBadDebtShares = await vaultHub |
There was a problem hiding this comment.
Consider adding check, internalizedBadDebtShares is not zero
| await doReport(ctx, { excludeVaultsBalances: false, reportElVault: true }); | ||
|
|
||
| const state2: ProtocolState = await captureState(lido); | ||
| const deferredRewards = await ethers.provider.getBalance(elVaultAddr); |
There was a problem hiding this comment.
Needed a check, that deferred rewards are not zero
| // --- Path A: report without redeem (via snapshot) --- | ||
| const simSnapshot = await Snapshot.take(); | ||
|
|
||
| await doReport(ctx, { excludeVaultsBalances: false, reportElVault: true }); |
There was a problem hiding this comment.
It seems the current implementation of accounting.report() always calls simulateReport() internally. That may violate the requirement that redeem happens after refSlot. Worth double-checking that, in this test, simulatedShareRate is actually calculated from the pre-redeem state.
| const overrideBatches = [...batchesState.batches].filter((x) => x > 0n); | ||
|
|
||
| // --- Process report with override batches --- | ||
| await report(ctx, { |
There was a problem hiding this comment.
Consider adding an assertion for the redeem reserve: before the report, it should match the corresponding share of the protocol, and after the report, it should be zero.
No description provided.