Dekant

Protocol constants

Every constant the protocol relies on, what it controls, and why it has the value it does. All are baked into the on-chain program; many can be changed by superadmin redeploy, none by users.

The full table

ConstantValueWhat it controls
SCALE10⁹Fixed-point precision. All probabilities, weights, and bin allocations are integers scaled by this factor.
INVARIANT_TOL256Maximum allowed drift `
MAX_BINS256Hard cap on the number of bins per market.
Z_CUTOFF5Bins with `
MIN_LIQUIDITY1 USDCMinimum initial liquidity at market creation.
MIN_TRADE_AMOUNT0.001 USDCMinimum size for any single trade.
MAX_FEE_BPS5000 (50%)Hard cap on any fee. Superadmin can lower; cannot raise above.

Why fixed-point and not floats

The Solana runtime supports floating-point in some contexts, but using floats in financial code is a category error: floats are not associative ((a + b) + c ≠ a + (b + c) in general), so the same trade computed in different orders produces different results. For an AMM, this means the on-chain state and the off-chain simulation disagree, which produces failed trades and angry users.

Fixed-point is exact. u64 and u128 arithmetic always agrees with itself. The protocol uses u64 for token amounts and u128 for intermediate products that could overflow a single multiplication.

SCALE = 10⁹ was picked because it gives nine decimal places of precision (more than USDC's six) while keeping SCALE × max_amount inside u128. Probability values that should sum to 1.0 are stored as integers summing to 10⁹.

Why the invariant tolerance is 256

After many integer-arithmetic operations, the L₂ invariant can drift by a few units. The tolerance is intentionally tight: 256 units against (which for a $1M-liquidity market is 10²⁴) is a relative slack on the order of 10⁻²². This is far below USDC's smallest unit and below human-noticeable amounts.

If a trade would push |Σxᵢ² − k²| above 256, the trade reverts. This is the on-chain mechanism that prevents accumulated rounding from becoming a real economic exploit.

Why Z_CUTOFF = 5σ

A standard Normal distribution has more than 99.9999% of its mass within 5σ of the mean. Bins beyond that contribute virtually nothing to the integral but cost compute units to evaluate. Clipping to |z| ≤ 5 saves cycles without observable change in the trade outcome.

A side effect: extremely wide bets (σ so wide that even bins at the edges of the range have |z| > 5) effectively have no weight at the edges. This is intentional - a "spread me across the whole range" bet is still a Normal distribution, not a true uniform.

Why MAX_BINS = 256

This bounds the linear pass over bins inside each instruction. With Solana's compute-unit budget per transaction:

  • Distribution buy on 256 bins: Σⱼ wⱼ Wⱼ + Σⱼ x²ⱼ + the outer quadratic ≈ ~120k CU, comfortably inside the per-instruction limit.
  • Distribution buy on 1024 bins (hypothetical): ≈ ~480k CU, would force splitting across multiple transactions.

256 was picked as the largest power of 2 that keeps every market operation in a single transaction.

Why MIN_LIQUIDITY = 1 and MIN_TRADE_AMOUNT = 0.001

Below MIN_LIQUIDITY = 1 USDC, k = 1 and k² = 1 produces invariant slack that exceeds the actual market state - meaningless trades. Below MIN_TRADE_AMOUNT = 0.001 USDC, integer-arithmetic rounding on per-bin allocation produces zero tokens for some bins, so the trade is a no-op for parts of the curve.

These minimums protect against dust positions that would round to zero and could be used to grief other operations.

Configurable vs hard-coded

Constants split into two groups:

Hard-coded (require redeploy)Configurable (superadmin can change)
SCALE, INVARIANT_TOL, MAX_BINS, Z_CUTOFF, MIN_LIQUIDITY, MIN_TRADE_AMOUNTAll fee bps (creation, trade, redemption, LP share), capped at MAX_FEE_BPS = 5000

The hard-coded numbers are baked into the math and changing them changes the protocol's behavior in non-obvious ways (e.g., raising MAX_BINS past 256 risks failed trades from CU exhaustion). Configurable fees are administrative dials.