Failure Modes
Vessel is unaudited testnet software. This page lists the ways it can break, one component at a time. For each: the signal that says it is breaking, the response the design specifies, and the thing you can check without trusting the dashboard.
Two facts frame everything below. First, the shortfall ordering is fixed: Ballast NAV absorbs losses first, then the Reserve, and only then is Hull principal impaired. Second, the public repository contains only a README and a LICENSE as of 2026-08-29. Contract names, function signatures, and deployed addresses are therefore design-stage and are marked as such. Where this page says "designed response", it means the litepaper's specification, not reviewed code.
The hedge venue today is SimVenue SIMVENUE — SIMULATED, a simulated venue with an owner-settable funding rate behind the IVenue interface. Several failure modes below (venue halt, funding inversion) are exercised on testnet by setting that rate, not by a real market. Behaviour against Perpl is not yet observable.
Venue down or halted
What it looks like. The perp venue stops accepting orders or stops settling funding. The short leg is frozen where it was. Funding stops accruing. Spot keeps moving, so net delta drifts away from zero and out of the 1% band the engine is meant to hold.
Detection. Rebalance attempts against IVenue fail or revert; the 4-hour timer fires with no executed rebalance; the delta band is breached and stays breached.
Designed response. The engine holds a 10% idle USDC buffer unhedged for margin maintenance. A buffer breach triggers automatic de-risking, never added leverage. With the venue unreachable, de-risking means reducing the spot leg toward whatever the frozen short can still cover. Losses from the drift land on Ballast NAV first. Hull's rate is a contract parameter, r_H = clamp(EWMA_30d(net funding APR) × (1 − h), 0, r_cap) with h = 40% and r_cap = 15% APR, so a halt lowers the next series' rate through the EWMA rather than changing a live series.
The exact de-risk path when the venue is unreachable (partial spot sale, full unwind, or hold) is not specified in the litepaper UNVERIFIED — PENDING GATE-0.
What you can check. On SimVenue SIMVENUE — SIMULATED, the funding rate is owner-settable; the value it is set to is readable on-chain once the address is published. The address is not yet published UNVERIFIED — PENDING GATE-0. When Perpl is wired, the venue's own public context endpoint (GET /api/v1/pub/context, no auth) tells you whether the market is open independently of Vessel.
Router path down
What it looks like. The spot leg is routed through two paths: a UniswapV2-compatible route (the IUniswapV2Router02 interface, with PuddleSwap as the venue actually called on testnet) and an on-chain CLOB route via Kuru. The CLOB route is in development and no deployed Kuru route is publicly verifiable. If the V2 route fails, the spot leg cannot be adjusted through that path.
Detection. Spot-side rebalance transactions revert at the router; delta drifts on the spot side while the short leg is intact.
Designed response. With one path down, the other carries. The litepaper names both, but the fallback ordering between them is not specified UNVERIFIED — PENDING GATE-0. With both down, spot cannot be resized, so the only lever is the short leg: the engine reduces short notional toward the spot it actually holds, moving back toward neutral. That is the same principle as the buffer rule (de-risk, never add leverage), applied from the other side. The litepaper does not describe the both-paths-down case explicitly. UNVERIFIED — PENDING GATE-0
What you can check. PuddleSwap publishes its testnet UniswapV2Router02 at 0x430c23895c8D44883526e3E0B09327dAD8766660 (chain 10143). These addresses are project-published only; no third-party registry vouches for them. Confirm code is present with:
cast code 0x430c23895c8D44883526e3E0B09327dAD8766660 --rpc-url https://testnet-rpc.monad.xyz
An empty result means the route Vessel would call does not exist at that address.
Keeper stalled
What it looks like. Nothing rebalances. The 4-hour timer passes without a rebalance transaction. A band breach goes unanswered. Margin top-ups and funding harvests stop.
Detection. Time since last rebalance exceeds 4 hours; delta outside 1% of gross notional with no corrective transaction.
Designed response. Keeper functions (margin top-ups, rebalancing, funding harvest) are permissionless. Anyone can call them. A stalled operator keeper is a liveness problem, not a safety problem, for as long as someone else is willing to pay gas.
The likeliest stall cause is gas configuration. Monad charges gas on the gas limit, not gas used: gas_paid = gas_limit × price_per_gas. A keeper that sets a large safety margin on its limit pays the whole limit on every call. A keeper whose wallet falls back to a huge limit when eth_estimateGas reverts pays that entire limit. Either drains a keeper wallet faster than its operator planned for. Keep the estimation buffer at or under about 10%. Note also the reserve balance rule: a 10 MON floor per EOA, with low-balance accounts limited to roughly one transaction per 1.2 seconds. A keeper near the floor is throttled.
The keeper function names and the exact crank entry point are not yet published UNVERIFIED — PENDING GATE-0.
What you can check. Once addresses are published, the timestamp of the last rebalance is on-chain and the explorer at testnet.monadscan.com shows it. If it is older than 4 hours, the keeper has stalled. If you hold MON, you can crank it yourself.
Indexer down
What it looks like. The dashboard shows stale NAV, stale delta, stale positions. Numbers stop moving.
Detection. Dashboard timestamps lag the chain head. On Monad, blocks are 300ms apart, so a lag of more than a few seconds is a real lag.
Designed response. None needed at the protocol level. The chain is the source of truth; the indexer is a read cache. The indexing design uses Envio HyperIndex, which requires the contract to be deployed and verified on a Monad explorer before it can import the ABI. That prerequisite is not met as of 2026-08-29 UNVERIFIED — PENDING GATE-0, since no contracts are published.
What you can check. Verifying the hedge does not go through the indexer. Read the spot balance and the short position directly against testnet-rpc.monad.xyz or the venue's public API. If the two agree with each other and disagree with the dashboard, the dashboard is the thing that is wrong.
Oracle bad input
What it looks like. A price feed returns a stale, zero, or wildly wrong value. Anything that consumes that value (NAV computation, delta computation) inherits the error.
Detection. Feed timestamp older than expected; price outside a sanity range relative to the last accepted value.
Designed response. The litepaper does not specify NAV input sanity bounds, an oracle provider, or a fallback. UNVERIFIED — PENDING GATE-0 What the design does say is structural: solvency is determined by the shortfall ordering and the conservation invariant, ΔNAV_Hull + ΔNAV_Ballast + ΔReserve + fees = G for every epoch, not by any single feed. A bad price can misreport NAV; it cannot by itself move funds between tranches. The short-leg liquidation price sits at least 40% above mark, so a feed error would need to be large before it threatened the short.
What you can check. Monad's docs list seven oracle providers as supported on testnet and mainnet: Chainlink, Chronicle, Pyth, Redstone, Stork, Supra, Switchboard. Which one Vessel reads, if any, is not published UNVERIFIED — PENDING GATE-0. Until it is, compare Vessel's reported mark against the venue's own mark; they should agree.
L1 degradation
What it looks like. Monad slows, forks briefly, or stalls. Transactions that appeared included disappear or reorder.
Detection. The gap between speculative and finalized state widens. Under normal conditions Monad gives speculative finality at 300ms and full finality at 600ms. (The Vessel litepaper still cites 400ms and 800ms; those figures predate the current network.)
Designed response. Monad exposes three block states through the standard tags: latest (speculative, proposed), safe (validator-backed, voted), and finalized (irreversible). The rule for anything irreversible, including Hull maturity redemption, Ballast withdrawal after cooldown, and keeper-triggered de-risking, is to act on finalized state. Whether the deployed contracts and keeper follow this rule is not verifiable until code is published UNVERIFIED — PENDING GATE-0. One further Monad-specific detail: consensus validates against a state view three blocks behind, so a freshly funded account cannot send until its funding is three blocks old (about 1.2 seconds). A keeper topped up mid-incident may appear stalled for a moment when it is not.
What you can check. Query eth_getBlockByNumber with finalized and with latest against testnet-rpc.monad.xyz. The difference in block numbers is the finality lag. If it is much larger than two blocks, the L1 is degraded. Network status is published at docs.monad.xyz.
Subordination floor breached
What it looks like. The ratio B / (H + B) falls below θ_min = 20%. This happens when Ballast NAV shrinks (losses absorbed) or when Hull grows faster than Ballast.
Detection. The ratio, computed from the two tranche NAVs, is below 20%.
Designed response. The floor is enforced at all times and constrains two actions: new Hull issuance and Ballast withdrawals. Both freeze until the ratio is back above 20%. Ballast withdrawals are already subject to a 48-hour cooldown; a floor breach extends that indefinitely. Restoring the floor happens through positive accrual to Ballast, new Ballast deposits, or Hull series maturing and not being reissued. Nothing about a floor breach touches Hull principal.
What you can check. Both NAVs are on-chain once contracts are published. The ratio is arithmetic. If the app shows Hull issuance or Ballast withdrawals as unavailable, the floor is the first thing to check.
Reserve exhausted in sustained inversion
What it looks like. Funding goes negative and stays negative. Each daily accrual has G below zero. Ballast NAV absorbs the loss first. When Ballast is exhausted, the Reserve absorbs it. The Reserve's target is 2% of TVL, funded from half the 10% protocol fee until the target is met. When the Reserve is gone, the next thing in line is Hull principal. That is the credit event.
Detection. Sustained negative G; Ballast NAV at or near zero; Reserve balance at or near zero; the subordination floor long since breached.
Designed response. Before this point, several things should already have happened: the floor breach froze Hull issuance, so no new senior claims were created into the drawdown; the EWMA rate would clamp toward zero for any new series; the buffer rule de-risked rather than leveraged. If inversion persists through all of that, the design does not promise Hull is whole. Hull holders of the affected series would redeem less than principal plus fixed yield at maturity. Whether the impairment is pro rata across a series, and whether an impaired series can be redeemed early, is not specified in the litepaper UNVERIFIED — PENDING GATE-0.
On testnet, this scenario is producible by setting the SimVenue SIMVENUE — SIMULATED funding rate negative and leaving it there.
What you can check. The conservation invariant holds through a credit event: ΔNAV_Hull + ΔNAV_Ballast + ΔReserve + fees = G. If Hull NAV fell, the sum of the other terms should account for exactly the loss. If it does not, the failure is a bug, not funding.
Summary
| Mode | Loss lands on | Freezes | Reader check |
|---|---|---|---|
| Venue halt | Ballast | Hedge adjustments | Venue status, on-chain delta |
| Router down | Ballast | Spot adjustments | cast code on the router |
| Keeper stall | Ballast (drift) | Nothing; crank it yourself | Last rebalance timestamp |
| Indexer down | Nobody | Dashboard only | RPC vs dashboard |
| Oracle bad input | Nobody directly | Depends on consumer | Vessel mark vs venue mark |
| L1 degradation | Nobody | Irreversible actions wait | finalized vs latest |
| Floor breach | Already landed | Hull issuance, Ballast withdrawals | B / (H + B) |
| Reserve exhausted | Hull principal | Issuance already frozen | Conservation invariant |
The litepaper is at vessel.wtf/litepaper. The testnet app is reached from vessel.wtf; the testnet subdomain does not resolve as of 2026-08-29.