Each caper's profile page has a buy/sell panel against the curve. Slippage is implicit in the curve shape: every trade nudges circulation along the price curve, so large trades pay (or receive) progressively worse marginal prices the further they push toward fully sold. The Max button computes the exact gateway-decimal string for your full balance, so rounding matches what the ledger accepts.
The curve vault is permanent — tokens you sell return to the inventory vault and become available to the next buyer. There is no external liquidity provider and no separate AMM pool.
How a trade moves the vaults
Every caper holds two vaults behind its curve. A buy moves your XRD into the curve vault (the reserve that backs the token) and hands you tokens out of the inventory vault. A sell reverses both: your tokens go back into the inventory vault, and the curve vault pays you the XRD the curve's closed-form integral says you're owed for the tokens it retires. A slice of what you hand in goes to the founder and the Commons instead of retiring, and the skim's XRD part, for the caper's treasury and the founder, comes off the payout; both shrink as the caper's circulation grows. Because there is a single curve in both directions — no separate buy and sell curve, no bid–ask spread — the price you sell at is exactly the price the next buyer would have paid to reach that point. Neither direction pays a trade fee: the skim is the only charge, and 49.5% of it goes to the treasury of the caper you trade (see Raising funds). The skim's peak rate is a stored field on the shared logic component, collateralization_peak, rather than a constant of the contract, written once at init and never assigned again, because the deployed CaperMain exposes no fee setter at all: twenty-one public methods and one instantiation function, and not one of them writes it. The previous component's update_fees did not survive the August 2026 redeploy (see the FAQ). That absence closes the runtime route and only the runtime route. Every logic upgrade re-runs init and writes the field again from the new package's own literal, and moving the platform onto that package repoints the registry's current_main, either through an UPGRADE proposal in the $CAPER caper or through the operator backstop the protocol admin badge holds (propose_main, then activate_main) – so “never assigned again” is a claim about the life of one component, not about the platform. The component serving trades today is none of those. Five genesis redeploys have replaced every tier at once. The one on 11 September 2026 retired the 7 September component that put the governance baseline on a price-time integral, the 5 September one that first carried the debate option kind, and the August state tier underneath both. The one on 15 September 2026 retired the 11 September set in turn and put the founder skim on both legs; its logic was upgraded once, activated at 06:07:10Z on 18 September, to a skim that kept falling with circulation instead of stopping. The one on 18 September 2026 retired the 15 September set to remove the $XRD caper and the trade fee on sells, and went up inside twenty-six seconds: the state package at 09:00:20.983Z, the registry at 09:00:28.637Z, its CaperMain set on the registry at 09:00:43.861Z, and the $CAPER caper at 09:00:46.937Z. That set's logic was upgraded three times before the next redeploy, each time by a new logic package, a new CaperMain instantiated from it, and the protocol admin badge proposing it to the registry and activating it: at 15:25:00Z the same day, to price the skim along the curve and drop two address reads, and on 19 September 2026 at 16:32:11Z, to component_tdx_2_1cqadjtv…, and again that evening at 22:03:11Z to component_tdx_2_1czqsy8n…. The one thing that last upgrade changed for a trader is the founder skim: a peak of 100% that falls to 1% by 10.8% of the supply sold and halves again with every further tenth sold (see Raising funds), and it carried into the next set unchanged. The one on 21 September 2026 retired the 18 September set to bind an exit's vote tokens to the account it pays (see Leaving a caper): its registry, component_tdx_2_1czpmphaq…, at 14:43:41Z, and its CaperMain, component_tdx_2_1czmc8h0…, at 14:43:55Z. For a trader that component added one method, exit_open, which an exit calls first in the same transaction. The one on 25 September 2026 retired the 21 September set to remove the trade fee and give each caper's treasury 49.5% of the skim: its registry, component_tdx_2_1cpndqmgr…, at 06:28:10Z, and its CaperMain, component_tdx_2_1cr40xf3h…, at 06:28:33Z. That set's logic was upgraded twice. The second upgrade, on 1 October 2026 at 12:21:12Z, to component_tdx_2_1cpltlrz…, which is what current_main resolves to and what serves the buy/sell panel now, slowed the skim's fall by half: both halvings take twice the supply, so the rate is half the peak by 1.99% sold, 1% by 21.4%, and halves every 20% sold after that. The first, on 30 September 2026 at 16:41:33Z, was to component_tdx_2_1cqma5fh…, and the one thing it changed for a trader is how the skim is read: one rate per trade – a buy's where it starts, a sell's at the bottom it would reach if every token handed in retired – in place of the integral along the curve, so a trade pays at least what the same trade cut into pieces would (see Bonding curve). Every time above is the first transaction to touch that entity, or the registry call itself, read off the Gateway rather than off a changelog.
That is the difference between the two ways this platform moves, and it is worth keeping straight when reading anything dated. A governed UPGRADE repoints current_main at a freshly published logic package and leaves the state beneath it standing, so every caper, treasury and proposal survives the change. A genesis redeploy publishes the state tier too and bootstraps the system capers again from nothing, so the ledger record starts over and addresses quoted from before it resolve to components no longer wired to anything. The second kind happened on 11, 15, 18, 21 and 25 September. The first kind happened on 18 September before that day's redeploy, once after it, on 19 September 2026, on 30 September 2026 and on 1 October 2026, and none of it carried a caper, treasury or proposal past 21 September, when the record started over again. Re-read from the live component’s on-ledger state on 25 September 2026: there is no trade_fee field, collateralization_peak is 1, and its blueprint publishes twenty-one methods and the one init function, with no fee setter among them. The missing setter survived all five redeploys and every upgrade, and the trade fee survived four; the components carrying them did not. Read them off the ledger rather than off this page.
The two directions are not symmetric
The curve's cumulative-reserve function X(s) = K·N·[ln((1+√s)/(1−√s)) − 2√s] has a closed form, so a sell prices out exactly: the payout is X(s_before) − X(s_after), two evaluations and a subtraction, with no approximation in it anywhere. A buy is the inverse problem — given an amount of XRD, find the circulation that consumes it — and that inverse has no closed form. The contract solves it numerically instead, with a Newton iteration capped at 16 steps against a tolerance of 0.0000001 XRD — and then checks the answer it got, because sixteen steps are not always enough.
The convergence test is deliberately lopsided. The loop accepts an answer only when the residual sits no more than the tolerance below zero and no more than 0.0000000001 XRD above it, so an answer the loop accepts consumes at most a ten-billionth of an XRD more than was paid, and usually slightly less. Rounding falls to the curve rather than the buyer. The loop also stops when a Newton step no longer moves the circulation at all, because every step left would price the same point again, and it accepts that point if the residual is within the tolerance either side of zero. So a mint can come up short, and it can run over by at most 0.0000001 XRD.
That asymmetry is not a rounding footnote — it has already produced a real defect. Newton's method on a convex function approaches the root from above, and the seed the solver used to start from landed far above the true answer for a small payment on a mature curve: at half the supply sold, a 100 XRD buy seeded at s ≈ 0.649 against a true s ≈ 0.5000007. In that region the lopsided break could not fire, so the iteration had to reach the root inside its 16 steps or finish still above it. An earlier version damped every step to at most one halving toward the domain floor, which was slow enough to exhaust the budget while still high. The damping was replaced with a hard floor, and the seed now starts lower as well: the solver takes the smaller of that estimate and the point where the curve’s tangent at the current circulation reaches the payment, which convexity keeps at or above the root and which lands close to it for any buy small against the curve. The case is pinned by a regression test named for it, tokens_bought_converges_for_small_payments_on_mature_curve, sweeping four circulation levels against payments from 0.01 to 10,000 XRD.
Exhausting the budget is no longer the same thing as over-minting, and that is the part of the solver a description by its iteration count leaves out. After the loop ends the contract evaluates the integral once more at the answer it reached. If that answer still consumes more than the payment, it throws the answer away and bisects instead — up to 64 halvings, downward from s_min, a circulation the solver already knows undershoots — so a mint that leaves the loop more than the tolerance over the payment is replaced by one short of it, by construction rather than by convergence. The guard is what makes the bound above a guarantee instead of a hope: a normal buy converges inside the loop and pays for the guard with a single extra evaluation, while the pathological case — a very large payment against a young curve, where the seed overshoots the domain and the throttled ascent runs out of steps below the root — is the only one that ever bisects. Read off compute_tokens_bought_inner in contracts/logic/src/lib.rs.
A round trip cannot pay out more than it took in
Because a single curve serves both directions, buying and immediately selling the same tokens returns the curve to exactly the point it started from. The question that matters for a numerically-solved buy is whether that round trip can ever hand back more XRD than it consumed. It cannot, and the contract pins it rather than assuming it: roundtrip_buy_then_sell_does_not_overshoot buys in seven cases across six circulation levels, sells the same tokens straight back, and asserts the signed difference never lands in the seller's favour by more than a dust bound of payment × 10−13 + 0.000001 XRD.
Both halves of that bound earn their place, and quoting only the constant makes the test sound tighter than it is. The flat 0.000001 XRD is the floor; the proportional term is there because near the s → 1 clamp the exact integral carries a few atto of symmetric logarithm-and-square-root noise that scales with trade size, and a flat floor alone was too tight to hold there. On the largest case in the sweep — 100,000,000 XRD against a curve already 99.99% sold — the bound the test actually enforces is about eleven times the floor. Two of the seven cases were added for the other direction entirely: they sit in the over-mint band a young curve opens to a very large payment, and they are the cases the post-solve undershoot guard exists to catch. The third late addition is the near-clamp case above, which tests the logarithm noise rather than the solver.
That bound holds before the skim, which comes off both legs, so a real round trip always ends down. An instant buy-and-sell is the cheapest probe anyone can run at a solver that approximates in one direction, and the guarantee is that it extracts nothing.
Trading no longer mints v
It used to, and this is the most consequential thing to know about trading that a reader arriving from older material will have wrong. Until 11 September 2026 every buy and sell minted the trader vote tokens, written v, at a flat rate the logic component held as vote_rate. The redeploy of that date removed the trade-side mint outright and took the field with it: the deployed component's state carries no vote_rate, and a ranked ballot is now the only way a member earns v.
The reason is worth stating plainly, because it is a change that makes trading less rewarding on purpose. A buy minted the v in the same transaction that opened the position, so one transaction could acquire a stake, mint the record that prices the exit, and redeem on both. The exit right was purchasable and the trade fee was its price. Pricing it in ballots instead puts it out of reach of capital alone: the vote fee is sunk and a ballot is one per account per proposal.
What follows for a trader is narrow but real. Buying into a caper is still how you take a position, and selling back on the curve still needs nothing but the tokens. What a position no longer carries with it is a claim on the treasury – that now requires having voted at least once. v still does both of its jobs once you hold it: compute_vote_weight sizes how far a ballot moves a tally and what you take out of the treasury when you leave. Read VOTE_MINT and the vote path in contracts/logic/src/lib.rs, and mint_vote_to in contracts/core/src/caper_dao.rs.
Swapping and exiting
Two variants build on the same primitive. A swap sells one caper's token and buys another in a single transaction — you never touch XRD in between — letting you rotate a position from one caper to another directly. And beyond selling on the curve, holders have a second way out: the exit right lets you burn your tokens to redeem a participation-weighted share of the caper's treasury, sized by the exit weight (t·v)/(V·T) and consuming both your governance tokens and your vote tokens — a claim on what the treasury has accumulated from the skim, fees and investments, separate from the curve reserve. Between the curve and the exit, a caper holder is never locked in — though the two routes are open on different terms. The curve will always buy your tokens back. The exit asserts a non-zero vote-token amount, withdrawn from the holder’s own account, before it pays anything, and since 11 September 2026 vote tokens are minted on exactly one member-facing surface – a ballot – so a position that arrived any other way – a buy on the curve, a transfer, a migration – cannot exit at all until its holder has voted. The curve will still buy those tokens back; only the treasury share is out of reach (leaving a caper).
What a swap actually costs
A swap looks like one action and is priced as two. The contract sells your tokens against the origin caper's curve, then hands the XRD it pays out into a buy on the destination caper's curve. Each leg pays the skim to its own caper:
- Sell leg – the skim takes part of the tokens you hand in and part of the XRD the origin curve pays out, for the origin caper's treasury, its founder and the Commons.
- Buy leg – the skim takes part of the XRD arriving at the destination curve and part of the tokens it mints, for that caper's treasury, its founder and the Commons.
There is no trade fee on either leg. You walk two curves, down the origin's and up the destination's, and the skim applies to each leg on its own curve's terms: to the sell at the origin caper's current rate and to the buy at the destination's, exactly as on two direct trades. A swap saves you holding XRD in between and a second signature; it is a convenience, not a discount.
A sale nobody placed
Not every sale on a caper's feed comes from a holder. A caper's treasury can hold other capers' tokens — an INVEST proposal buys them on the target's curve — and a DIVEST proposal runs that trade backwards. Execution withdraws the voted-on amount of the target's token from this treasury, sells it into that caper's curve, and deposits the XRD back into this treasury, entirely inside the contract's own call frame, so the tokens never reach the worktop for an executor to skim.
From the receiving curve's side it is an ordinary sale in every observable respect: the same single curve, the same closed-form payout, the same skim and no trade fee, and the same SellToken event on the trade feed carrying no divest-specific field. A holder watching the chart cannot tell one from a retail exit — the identifying record is the ProposalExecutedDivest event on the selling caper, not anything on the curve that absorbed the sale. Price impact is likewise unexceptional: a divest walks the curve down exactly as a same-size holder sale would.
Two guards matter to anyone pricing around it. The trade is frozen at settlement — execution withdraws exactly the amount the winning option named, and aborts outright if the treasury's holding has fallen below it since, because filling a smaller trade than the one that passed would break the frozen-winner contract. And $XRD is refused by name as a divest target, for the same reason it cannot be sold at all: it has no curve to sell into.
Read off execute_proposal_divest and sell_token_raw in contracts/logic/src/lib.rs, and treasury_withdraw / treasury_deposit on the state tier.
Everything above is read off buy_token_raw, sell_token_raw, swap, compute_tokens_bought_inner and compute_xrd_received in contracts/logic/src/lib.rs, and the vault and solvency invariants off buy_apply and sell_apply in contracts/core/src/caper_dao.rs.
Price impact, and how it compares to an AMM
A caper's price is a deterministic function of how many tokens are in circulation, so the cost of a trade is knowable before you sign it rather than discovered on execution — exactly for a sell, which prices off the curve's closed-form integral, and to within 0.0000001 XRD for a buy, which inverts that same integral numerically (see The two directions are not symmetric above). That is a different liquidity model from a constant-product AMM such as Uniswap, where price emerges from a reserve ratio (x·y=k) maintained by external liquidity providers. Three practical consequences follow:
- No liquidity to pull. The curve reserve is a permanent inventory vault owned by the caper, not third-party LP deposits that can be withdrawn — so depth never vanishes and there is no impermanent-loss risk borne by outside providers.
- No bid–ask spread. A single curve serves both directions, so the price you sell at is exactly the price the next buyer pays to reach that point — the wedge is the skim on both legs, largest on a young caper, not a market-maker's spread.
- Predictable slippage. Large orders still walk the curve and pay progressively worse marginal prices, but that impact is a fixed property of the curve shape rather than a function of who happens to be providing liquidity that block.
The comparison runs deeper than price impact. A constant-product pool quotes from a closed-form formula, a Curve or Balancer pool cannot, and a caper's buy side cannot either – so all three reach for a different numerical method to produce a number a trader can sign. Numerical pricing in AMMs and bonding curves reads those methods out of the deployed source of each.