Missing post-unwind leverage validation allows ineffective force unwinds to complete silently
finalizeForceUnwind computes the new leverage but never verifies it meets the targetLeverageBps specified in forceUnwind, so an ineffective unwind completes and emits success events while the position remains over-leveraged.
Description
In finalizeForceUnwind, after the waterfall runs the actual new leverage is computed at L1464:
computedLeverageBps = uint32((computedNotionalUsdcUnits * Types.BPS_BASE) / collateralUsdcUnits);
However, there is no check that computedLeverageBps is at or below the targetLeverageBps specified in forceUnwind. The result is stored and the function completes regardless of whether the unwind achieved its deleveraging goal.
This is possible because tokenUnitsToSell and targetLeverageBps are validated independently in forceUnwind, the contract never checks that they are consistent with each other. An admin could pass targetLeverage = 2x but sell too few tokens, producing a waterfall that barely returns any capital. The position returns to Opened at nearly the same leverage as before, and the contract emits events as if the unwind succeeded.
Other finalize functions in the contract validate computed results against expectations (e.g., isWithinBounds sanity checks on proceeds vs notional). The absence of a similar post-hoc check here is an inconsistency in the contract's defense-in-depth posture.
Recommendation
Add a post-unwind sanity check after the leverage is computed at L1464:
require(computedLeverageBps <= storedTargetLeverageBps + TOLERANCE, "Unwind did not achieve target leverage");
Additionally, as a backend verification item: validate that the computed tokenUnitsToSell is consistent with targetLeverageBps before submitting the forceUnwind transaction.
Resolution
Mitigated off-chain. Backend VaultEventAlertService.checkFinalizeEvent raises a Sentry alert on leverage drift beyond tolerance.

