Dripster · Smart Contract Security AssessmentDripster Client Hub

Dripster Leveraged Prediction Vault

Zealynx audited the Dripster Leveraged Prediction Vault, a custodial EVM smart contract suite that opens leveraged positions on Polymarket Conditional Token Framework markets. The 1,825 nSLOC review across seven Solidity files identified 17 issues (2 Medium, 7 Low, 8 Informational) with zero Critical or High findings, reflecting an iteratively-hardened codebase. Nine findings were fixed and eight acknowledged.

PolygonSoliditySmart Contract Code Review2026-04-28github.com/bloom-art/dripster-lendZealynx methodology
Total findings
17
9 fixed · 8 acknowledged
Critical
00
High
00
Medium
02
Low + Info
15
02

Scope

7 files · 1,825 SLOC
Repository
Initial commit
4b5dd35ed922
Platform
Polygon · Solidity
Methodology
Out of scope
frontend / UI, ML models, third-party dependencies, off-chain infrastructure, API / backend (audited separately)
File
LeveragedPredictionVaultV1.sol
PositionLib.sol
SignatureLib.sol
CloseLib.sol
Events.sol
Types.sol
Errors.sol
03

Findings

click any row for the full write-up
Severity
ID
Finding
Status
mediumF-2026-0001Emergency mode blocks escape-hatch refund paths, trapping user fundsAckmediumF-2026-0002Incorrect storage slot annotations create high-risk reference hazard for V2 upgradeFixedlowF-2026-0003cancelPosition() escape hatch is inaccessible to the user whose funds are lockedFixedlowF-2026-0004USDC sent directly to the vault is permanently irrecoverableAcklowF-2026-0005createPosition accepts user funds without checking capital availability or limitsAcklowF-2026-0006Missing revert mechanism for pending states allows permanent position lockup on backend failureAcklowF-2026-0007Incomplete rescueERC1155 guard allows extraction of active position tokens after full deleverageFixedlowF-2026-0008Force unwind unconditionally resets position state to Opened, discarding user's prior CloseRequested intentFixedlowF-2026-0009finalizeLiquidate leaves actualNotionalUsdcUnits stale post-liquidation, creating a latent fee-computation bug and inconsistent off-chain readsFixedinfoF-2026-0010cancelDelaySeconds changes apply retroactively to existing positionsFixedinfoF-2026-0011No update path creates a chicken-and-egg risk with Timelock address being immutableFixedinfoF-2026-0012Coarse-grained emergency mode forces all position exits through liquidation path, causing users to pay unwarranted liquidation feesAckinfoF-2026-0013Missing post-unwind leverage validation allows ineffective force unwinds to complete silentlyAckinfoF-2026-0014Invariant suite handler uses legacy EIP-191 signatures, silently reverts every position creation, yields zero security signalFixedinfoF-2026-0015EIP-191 personal-sign instead of EIP-712 typed data reduces wallet transparencyFixedinfoF-2026-0016No on-chain cumulative bad-debt trackingAckinfoF-2026-0017Partial fill can result in leverage below MIN_LEVERAGE_BPSAck
04

Key Findings

  • Emergency mode blocks escape-hatch refund paths, trapping user funds. The whenNotEmergencyOnly modifier is applied to cancelPosition, revertOpen, and finalizeClose, the very functions that exist to refund funds caught in transitional states during incidents. The team agreed to add a self-cancel path gated by the existing serverHalted flag, preserving the conservative posture during normal operation while giving users a non-custodial exit during a declared incident.
  • Storage slot annotations off, creating a V2 upgrade hazard. All 28 inline slot annotations in the contract assumed OpenZeppelin v4 sequential base storage rather than v5 ERC-7201 namespaced storage. A V2 author trusting the comments could place a new variable at "slot 0", overwriting globalAdmin after upgradeToAndCall and corrupting governance.
  • Incomplete rescueERC1155 guard allows draining tokens from active positions. The original guard used tokenTotalBorrowedUsdcUnits[tokenId] > 0 as a proxy for "active position holds this tokenId". After a force-unwind drains borrowed capital to zero while the position retains its conditional tokens, the proxy reads zero and globalAdmin can rescue tokens out from under the position, bricking every subsequent close, settle, or liquidate. The same surface was independently flagged by the Krait pre-audit from the inverse angle, confirming the rescue guard as the correct remediation site.
05

Architectural Security Observations

  • Graduated four-tier operational controls. Pause mechanisms are tiered (newPositionsPaused to userActionsPaused to emergencyOnlyMode to serverHalted), allowing scoped incident response rather than a binary kill switch.
  • Asymmetric admin authority with timelock gating. Four-role separation plus a TimelockController on every high-risk operation. emergencyAdmin can pause but only globalAdmin can unpause, preventing a hot key from re-enabling the protocol after a halt.
  • Two-step backend-coordinated lifecycle. Position transitions split into on-chain initiation, off-chain Polymarket execution (Fill-Or-Kill, no resting-order windows), and on-chain finalization, with explicit *Pending states.
  • EIP-712 typed-data signatures with chain-bound domain. Position payloads are signed via EIP-712 with the OpenZeppelin v5 namespaced domain separator: wallet-side transparency plus cross-chain replay prevention via chainid() and address(this).
  • Concurrent unwind plus liquidate state isolation. Separate pendingTokenUnits and pendingUnwindTokenUnits fields permit a force-unwind and liquidation to interleave without data corruption; terminal finalizeForceUnwind from Liquidated avoids double-decrementing capital tracking.
  • Contract-wide invariant enforcement. _assertPositionInvariants runs at every state-mutating exit, locking in core position identities.
06

Security Strengths Observed

  • Iteratively-hardened codebase. Extensive AUDIT-FIX annotations reflect multiple prior security review iterations. The Krait pre-audit (1 Low fixed, 4 Informational acknowledged) predated manual review, showing automated tooling is part of the development loop.
  • Deferred fee accrual eliminates create-to-open race. Origination fees are reserved as pendingOriginationFeesUsdcUnits at createPosition and only realized into accumulatedFeesUsdcUnits at finalizeOpen, with refund on partial fills.
  • Modern Solidity practices. Custom errors, SafeERC20, nonReentrant on every state-mutating entry point, strict CEI ordering, and OpenZeppelin v5 upgradeable patterns with _disableInitializers() in the implementation constructor.
  • Defense-in-depth on backend trust. Soft sanity checks (isWithinBounds at 5x/10x tolerance) catch inconsistent submissions; off-chain VaultEventAlertService monitors every finalize event with automatic circuit-breaker tripping at 5,000 USDC bad debt.
  • High test-suite sensitivity. Mutation testing yielded a 99% high-severity catch rate. Surviving mutants were classified as equivalent or covered by the calibrated invariant layer added during this audit.
07

Team & approval

Lead Auditor
Carlos (Bloqarl)
@TheBlockChainer
Auditor
Bobby_Petrov
@0x_bob_0x
08

Disclaimer

This audit is not an endorsement and does not constitute investment advice. Zealynx reviewed the codebase at the commits listed in section 02 over the engagement window. Findings are limited to issues identified within that scope and do not preclude the existence of other vulnerabilities. Subsequent code changes are not covered by this report unless the engagement is explicitly extended.

Download PDF (51p)
ZEALYNX SECURITY · published 2026-04-28
17 findings · Solidity

oog
zealynx

Smart Contract Security Digest

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

© 2026 Zealynx