F-2026-0001·missing-escape-hatch

Emergency mode blocks escape-hatch refund paths, trapping user funds

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

The whenNotEmergencyOnly modifier is applied to the very refund and recovery functions designed to free user funds, so an emergency leaves users without an on-chain exit while the cold-wallet multisig coordinates.

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

Description

The protocol implements a multi-tiered pause system where emergencyOnlyMode acts as a circuit breaker for exceptional situations. The design correctly allows risk-reduction operations (forceUnwind, liquidatePosition, settlePosition and their finalize counterparts) to bypass emergency mode so the protocol can continue shedding risk during incidents.

However, the whenNotEmergencyOnly modifier is also applied to cancelPosition, revertOpen, openPosition, finalizeOpen, closePosition, and finalizeClose, the very functions that serve as escape hatches for positions caught mid-lifecycle.

This creates a contradiction: cancelPosition was specifically implemented as an escape hatch to prevent permanent fund locks when the admin is delayed (up to cancelDelaySeconds). revertOpen is the designated failure path to refund users when a Polymarket exchange order fails. During an active emergency such as a backend crash, database outage, or exchange API failure, the system is most likely to suffer from the exact delays and failed orders that these functions were built to resolve.

Vulnerable scenario:

  1. User calls createPosition, transferring collateral plus origination fee to the vault. Position enters Created state.
  2. An incident occurs (backend crash, exchange outage) and emergencyAdmin (hot wallet) activates emergencyOnlyMode.
  3. The user's position is stuck in Created. cancelPosition is blocked by whenNotEmergencyOnly, so neither the user nor the admin can refund the escrowed funds.
  4. Similarly, positions in OpenPending cannot be refunded via revertOpen, and positions in ClosePending cannot be completed via finalizeClose.
  5. The only recovery is for globalAdmin (2-of-3 cold-wallet multisig) to disable emergency mode entirely via setEmergencyOnlyMode(false), which could take hours to coordinate and forces a binary choice between maintaining emergency posture and returning user funds.

The asymmetry is illogical: if the protocol trusts admins to finalize liquidations, force unwinds, and settlements during emergency mode, there is no security benefit to preventing those same admins from issuing simple refunds for stuck positions.

03Section · Impact

Impact

User USDC (collateral plus origination fee) is locked in Created, OpenPending, or ClosePending states with no on-chain recovery path while emergency mode is active. Recovery requires the cold-wallet multisig to fully disable the protocol's emergency defenses, defeating the purpose of the circuit breaker during the incident window when it is needed most.

04Section · Recommendation

Recommendation

Exempt the refund/recovery functions from the whenNotEmergencyOnly modifier while keeping it on position-initiation functions:

  • Remove whenNotEmergencyOnly from cancelPosition, revertOpen, and finalizeClose. These are fund-recovery paths that pose no new risk during emergencies (they only return escrowed funds or complete already-initiated operations).
  • Keep whenNotEmergencyOnly on createPosition, openPosition, and closePosition. These initiate new lifecycle transitions that should remain blocked during emergencies.

Alternatively, create dedicated emergency-exempt recovery functions (emergencyCancelPosition, emergencyRevertOpen) that bypass the modifier while preserving the existing function signatures for non-emergency use.

05Section · Resolution

Resolution

Acknowledged. Team agreed to add a self-cancel path on cancelPosition gated by the existing serverHalted flag, with tests covering (a) self-cancel reverts when the flag is unset, (b) self-cancel succeeds and refunds collateral plus origination fee when the flag is set, and (c) the flag itself is admin-gated. The remaining emergency-mode asymmetry on revertOpen and finalizeClose is accepted by design.

F-2026-0001

oog
zealynx

Smart Contract Security Digest

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

© 2026 Zealynx