Dekant

Trading math

Two trade primitives: discrete (buy or sell a single outcome) and distribution (allocate across many outcomes via a Gaussian). Both preserve the L₂ invariant.

Discrete buy

A trader spends c units of collateral to buy outcome i. The protocol mints a complete set of tokens (one of each outcome at $1) using the collateral, then executes the buy by moving along the hypersphere:

k' = k + c
x'ᵢ = √(k'² − Σⱼ≠ᵢ xⱼ²)
tokens_out = x'ᵢ − xᵢ

After the trade, all outcomes other than i are unchanged in x. Only xᵢ increases. The new norm is k', larger than before because new collateral was added.

Discrete sell

A trader returns t tokens of outcome i and receives collateral:

x'ᵢ = xᵢ − t
k' = √(Σⱼ x'ⱼ²)
collateral_out = k − k'

Same shape as the buy, just inverted. The norm shrinks; the difference is what the trader walks away with.

Distribution buy (the "draw a curve" trade)

This is the new primitive. The trader specifies a Gaussian (μ, σ) over a continuous range [a, b] divided into N bins. The system computes weights Wⱼ for each bin from the Normal PDF, then buys all N outcomes simultaneously in proportion to those weights.

Step 1: bin discretization

The center of bin j (zero-indexed) is:

centerⱼ = a + (2j+1)(b − a) / (2N)

The standardized z-score is:

zⱼ = (centerⱼ − μ) / σ

The unnormalized weight is the Normal PDF evaluated at zⱼ:

wⱼ = exp(−zⱼ² / 2)

Bins where |zⱼ| > 5 are clipped to weight 0. Then weights are scaled so they sum to a fixed integer S = 10⁹ (the protocol's fixed-point scale):

Wⱼ = wⱼ · S / Σ wⱼ

This gives an integer weight vector W with Σ Wⱼ = S - no floating point on-chain.

Step 2: solve for the trade size

Given total spend c, the protocol moves along the hypersphere from k to k' = k + c while distributing the trade across all bins in proportion to W. Define:

XW = Σⱼ xⱼ Wⱼ
W² = Σⱼ Wⱼ²

Solve the quadratic that comes from the L₂ invariant for the scalar λ:

λ = √(XW² + W²·(k'² − k²)) − XW

Tokens received per bin:

tokens_outⱼ = λ · Wⱼ / W²

The bin nearest the trader's μ gets the largest slice; bins in the tails get less. After the trade, the new state x'ⱼ = xⱼ + tokens_outⱼ lies exactly on the new hypersphere of radius k', preserving the invariant.

The full derivation of λ from the hypersphere constraint is in Appendix A of the math model.

Distribution sell

The trader returns T total tokens, allocated across bins in proportion to the same weight vector W:

tⱼ = T · Wⱼ / S

Capped at the trader's actual holding in each bin (tⱼ ← min(tⱼ, holdingⱼ)).

The new AMM state and refunded collateral:

x'ⱼ = xⱼ − tⱼ
k' = √(Σⱼ x'ⱼ²)
collateral_out = k − k'

Sanity check: invariant preserved

After every trade:

Σ x'ⱼ² = k'²    (within INVARIANT_TOL = 256, see Constants)

A small slack of 256 absorbs rounding error from integer arithmetic. Trades that would exceed this slack revert.

Round-trip cost

Two trade fees of 30 bps each plus AMM slippage means a round-trip (buy + sell) costs at least 60 bps. This creates a natural bid-ask spread without an order book.

Where this is implemented

Closed-form solutions for all three operations live in the on-chain Rust program. The frontend uses the same formulas in TypeScript for the bet preview. Both sides use u64/u128 integer arithmetic - no floating point.