F-2026-0008·state-machine-incorrect-transition

Force unwind unconditionally resets position state to Opened, discarding user's prior CloseRequested intent

Fixedvaultleveragedprediction-marketgithub.com/bloom-art/dripster-lend
TL;DR

finalizeForceUnwind always reverts non-terminal positions to Opened, silently discarding any prior CloseRequested intent and forcing the user to re-signal after every unwind cycle.

Severity
LOW
Impact
LOW
Likelihood
MEDIUM
Method
MManual review
CAT.
Complexity
LOW
Exploitability
MEDIUM
02Section · Description

Description

When finalizeForceUnwind completes a non-terminal unwind, it unconditionally resets the position state to Opened:

solidity
// LeveragedPredictionVaultV1.sol:L1487-1488
positionStates[positionKey] =
currentState == Types.PositionState.UnwindPending ? Types.PositionState.Opened : currentState;

At finalization time, currentState is always UnwindPending (set by forceUnwind), so the ternary always evaluates to Opened. If the position was in CloseRequested before the unwind was initiated, that state is silently discarded. There is no mechanism to preserve or restore it through the unwind cycle.

The user must discover off-chain that their close request was dropped and re-submit requestClose. In a multi-unwind scenario, this can happen repeatedly, each unwind cycle erases the close intent, requiring the user to re-signal after every cycle with no on-chain notification.

03Section · Recommendation

Recommendation

Store the pre-unwind state before transitioning to UnwindPending and restore it after finalization. For example, add a preUnwindState field to the position struct:

solidity
// In forceUnwind:
position.preUnwindState = currentState; // save CloseRequested or Opened
// In finalizeForceUnwind:
positionStates[positionKey] =
currentState == Types.PositionState.UnwindPending ? position.preUnwindState : currentState;

This ensures a user's close intent survives unwind cycles without requiring them to re-signal.

04Section · Resolution

Resolution

Fixed. New preUnwindState field records pre-unwind state; non-terminal finalizeForceUnwind restores it.

Status
Fixed
F-2026-0008

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx