Skip to content

Providing liquidity

Liquidity providers (LPs) deposit USDCUSDC and receive LP shares representing their proportional claim on the pool reserves. Every trade's swap fee grows yesReserve × noReserve without changing share supply, so each share is worth slightly more after each trade — that is how LPs earn yield.


addLiquidity

Contract function: addLiquidity(usdcAmount) → returns shares

Deposits usdcAmount USDC and adds it symmetrically to both reserves (same amount to each side). Shares are minted proportional to the contributor's fraction of total collateral.

+ USDCdepositequal split+ n YESinto yesReserve+ n NOinto noReserveLP shares
Adding liquidity is symmetric: your USDC mints an equal amount of YES and NO straight into the two reserves — like adding both tokens to a Uniswap pool — and you receive LP shares in proportion to the pool you now own.

Formula

Bootstrap (first deposit, totalLpShares == 0):

shares      = usdcAmount
yesReserve  = usdcAmount
noReserve   = usdcAmount

Subsequent deposits:

shares     = usdcAmount × totalLpShares / totalCollateral
yesReserve += usdcAmount
noReserve  += usdcAmount

totalCollateral += usdcAmount in both cases.

Why symmetric injection?

Adding the same USDC to both reserves keeps the pool imbalance ratio stable when the pool is balanced (P(YES) = 50 %). For an imbalanced pool it nudges the price very slightly toward 50/50, but the effect is small and the gain in depth outweighs it. The key guarantee is that no LP can move the price dramatically just by adding liquidity.

Numerical example

Step 1 — Bootstrap

LP1 sends 1 000 USDC:

shares = 1 000
yesReserve = 1 000,  noReserve = 1 000
totalCollateral = 1 000,  totalLpShares = 1 000
P(YES) = 50 %

Step 2 — After some trading (user bought YES with 300 USDC, see AMM & pricing):

yesReserve = 769.23,  noReserve = 1 300
totalCollateral = 1 300,  totalLpShares = 1 000
P(YES) ≈ 62.8 %

Step 3 — LP2 adds 260 USDC:

shares = 260 × 1 000 / 1 300 = 200

yesReserve   += 260  →  1 029.23
noReserve    += 260  →  1 560
totalCollateral += 260  →  1 560
totalLpShares   += 200  →  1 200

P(YES) = 1 560 / (1 029.23 + 1 560) = 1 560 / 2 589.23 ≈ 60.25 %

LP2 received 200 shares (16.67 % of the pool) for 260 USDC (16.67 % of 1 560 collateral). ✓


removeLiquidity

Contract function: removeLiquidity(shares)

Burns shares LP tokens and pays out the proportional pool claim. Because the reserves may be imbalanced (one side larger than the other after trading), the payout splits into:

  • USDC (symmetric portion): the min(yesOut, noOut) amount that can be pair-redeemed immediately.
  • Outcome tokens (asymmetric remainder): whichever reserve was larger returns its excess as raw YES or NO tokens.

Formula

yesOut  = yesReserve × shares / totalLpShares
noOut   = noReserve  × shares / totalLpShares
sym     = min(yesOut, noOut)          ← redeemed 1:1 for USDC

yesReserve  -= yesOut
noReserve   -= noOut
totalLpShares -= shares
totalCollateral -= sym                ← only the redeemed portion leaves collateral

USDC returned      = sym
YES tokens extra   = yesOut − sym
NO tokens extra    = noOut  − sym

Exactly one of yesExtra or noExtra will be zero (the symmetric side cancels). The surplus tokens go into the LP's yesBalanceOf / noBalanceOf.

Numerical example

State: yesReserve = 769.23, noReserve = 1 300, totalCollateral = 1 300, totalLpShares = 1 000. LP1 holds 1 000 shares (100 %).

LP1 removes 500 shares (50 % of pool):

yesOut  = 769.23 × 500 / 1 000 = 384.615
noOut   = 1 300  × 500 / 1 000 = 650

sym     = min(384.615, 650) = 384.615   ← redeemed for USDC

yesReserve    -= 384.615  →  384.615
noReserve     -= 650      →  650
totalCollateral -= 384.615  →  915.385
totalLpShares   -= 500    →  500

USDC returned  = 384.615
YES extra      = 384.615 − 384.615 = 0
NO extra       = 650 − 384.615     = 265.385 NO tokens

LP1 walks away with 384.615 USDC + 265.385 NO tokens.

Invariant check after removal:

userYes(user A) + lpYes(0) + yesReserve(384.615)     = 915.385  ✓
userNo(user A)  + lpNo(265.385) + noReserve(650)      = 915.385  ✓

The 265.385 NO tokens represent the LP's directional inventory. Options:

ActionEffect
Hold until settlementRedeem at netUsdcPerNoToken if NO wins
sellNo(265.385)Swap them back to USDC through the AMM (incurs swap fee)
redeemPairOnly if the LP also holds matching YES tokens

Fee types

There are two distinct fee mechanisms, both expressed in basis points (1 bp = 0.01 %):

Each tradeswap fee ≤ 1%stays in pool → LPsAt settlementsettlement fee ≤ 5%creator · 30%platform · 70%
Two separate fees: the per-trade swap fee compounds into the pool for LPs; the one-time settlement fee is split between the market creator and the platform.

1. Swap fee (lpSwapFeeBps)

Charged on every buyYes, buyNo, sellYes, sellNo call. The fee is taken on the input token before the CPMM formula runs:

effectiveIn = amountIn × (10 000 − lpSwapFeeBps) / 10 000

The full amountIn is added to the reserve, but only effectiveIn is used to compute the output. The shortfall stays in the pool and grows k = yesReserve × noReserve. Because LP shares remain unchanged, each share now represents a larger fraction of a larger k — the fee accrues automatically, no harvest needed.

Example (lpSwapFeeBps = 30):

Buy YES with 100 USDC:
  effectiveIn  = 100 × 9 970 / 10 000 = 99.70
  noReserve adds 100 (full)
  yesReserve pays out 90.66 (computed on 99.70)

  Fee retained in pool = value of 0.30 USDC added to k

2. Protocol & creator fees (platformFeeBps + creatorFeeBps)

Collected once at settlement from totalCollateral before computing per-token redemption rates. These are separate from swap fees and are taken regardless of which side wins.

platformFee = totalCollateral × platformFeeBps / 10 000
creatorFee  = totalCollateral × creatorFeeBps  / 10 000
remaining   = totalCollateral − platformFee − creatorFee

The per-token rates exposed after settlement:

netUsdcPerYesToken  (1e18-scaled)
netUsdcPerNoToken   (1e18-scaled)

In a normal resolution one rate is remaining × 1e18 / totalCollateral and the other is 0. In the emergency refund fallback (see Resolution) both are non-zero, proportional to the AMM's implied probabilities at the time of the refund.


LP payout at settlement

After the market settles, LPs call claimLpPayout() (once per address) to receive their share of the pool at the settlement prices:

yesShare = yesReserve × lpShares[caller] / totalLpShares
noShare  = noReserve  × lpShares[caller] / totalLpShares

usdcOut  = yesShare × netUsdcPerYesToken / 1e18
         + noShare  × netUsdcPerNoToken  / 1e18

Numerical example

After settlement (YES wins):yesReserve = 384.615, noReserve = 650, totalLpShares = 500

Platform + creator fee = 1.5 % of 915.385 = 13.73 USDC taken from collateral.

remaining           = 915.385 − 13.73 = 901.655
netUsdcPerYesToken  = 901.655 × 1e18 / 915.385 ≈ 0.985 USDC per YES (1e18-scaled)
netUsdcPerNoToken   = 0

LP (holds 500 shares of 500 total = 100 %):

yesShare = 384.615 × 500 / 500 = 384.615
noShare  = 650     × 500 / 500 = 650

usdcOut  = 384.615 × 0.985  +  650 × 0
         ≈ 378.85 USDC

The LP's NO inventory (650 in reserve) is worthless since NO lost. The LP's YES reserve (384.615) redeems at ~0.985 cents, not 1.00, because the protocol fee was deducted.

Onchain prediction markets, priced by an AMM and settled in USDC.