Dekant

Resolution & solvency

How a market closes, who can resolve it, and why the protocol is provably solvent at every step.

The resolution flow

Markets move through a small state machine:

Active → PendingResolution → Resolved → (claims open forever)
  1. Active - the deadline has not yet passed. Trades, distribution buys, LP adds, and LP removes are all permitted.
  2. PendingResolution - the deadline has passed. The first instruction that touches the market after the deadline lazily transitions it to PendingResolution. New trades are rejected; LP removes still work at the current state.
  3. Resolved - the assigned oracle (a role-gated PDA) called resolve_market with the outcome value. From this point, holders can claim payouts forever.

There is no expiry on claims. Forgotten positions are not seized.

Continuous market: bin mapping

For a continuous market with range [a, b] and N bins, the resolved value v maps to a bin index:

bin = floor((v − a) · N / (b − a))

clamped to [0, N−1]. Holders of tokens_bin for the winning bin redeem $1 per token (less the redemption fee).

A worked example: range [2000, 4000], N = 5, oracle reports v = 3150.

bin = floor((3150 − 2000) · 5 / (4000 − 2000))
    = floor(1150 · 5 / 2000)
    = floor(2.875)
    = 2

Bin 2 covers [2800, 3200), which contains 3150. ✓

Tokens in bins 0, 1, 3, and 4 redeem for zero. Tokens in bin 2 redeem at $1 each.

Solvency theorem

The protocol is solvent at every state.

Because the AMM enforces Σ xᵢ² = k², we have xᵢ² ≤ k² for every outcome, and therefore:

|xᵢ| ≤ k

The vault is required to hold collateral equal to k at all times (this is the LP-deposit equality that initialization and every operation maintains). When the market resolves, the maximum claim against the vault is the total winning tokens outstanding, which is at most x_{win} (since each winning token redeems at $1, capped by the supply of winning tokens). And:

max_claim ≤ x_{win} ≤ k = vault_collateral

so the vault always has enough to honor every winning claim. There is no liquidation cascade to worry about, no margin call, no clawback. Either you get paid or the market hasn't resolved yet.

Lazy deadline enforcement

The state transition Active → PendingResolution is lazy by design. There is no cron job; the first user instruction (a trade, an LP add, a claim attempt, anything) that arrives after now > deadline does the transition before its main logic runs.

This keeps the protocol cheap. Markets that no one interacts with sit dormant, and resolution is paid for by whoever shows up first - typically the oracle calling resolve_market.

Claim mechanics

After resolution, a token holder calls claim_payout:

  1. The protocol burns the holder's winning-bin tokens.
  2. Computes the gross payout: tokens_held × $1.
  3. Subtracts the redemption fee: gross × (1 − redemption_fee_bps / 10000).
  4. Transfers the net payout in USDC to the holder's wallet.

The frontend automatically calls claim_payout when you visit a resolved market in your portfolio. You do not need to remember to claim.

Edge cases

SituationWhat happens
Resolution value lands exactly on a bin boundary (e.g., v = 3200)The floor operation places it in the upper bin. Bin 3 wins, not bin 2.
Oracle reports a value outside [a, b]The bin mapping clamps to the nearest boundary bin. Designers should pick [a, b] to bracket all plausible outcomes.
No one calls resolve_marketThe market sits in PendingResolution indefinitely. There is no auto-resolve fallback.
Market is resolved but no one claimsThe vault holds the unclaimed collateral. LPs can still withdraw their pro-rata share including the unclaimed portion.

The clamping behavior is the main reason designers should set [a, b] generously - a market for "what will SOL be on July 1?" with range [80, 100] will resolve at the boundary if SOL hits $120 and pay out badly. Wide ranges with more bins are safer than tight ranges, even though they reduce the per-bin granularity.