Skip to main content
The floor limit used to be a number written once at enrolment. It is now bought:
computed at redemption, not at enrolment.

Three properties, each a test

Sublinear

4× the stake buys the uplift, not 4×. Trust cannot simply be purchased.

Capped

No merchant creates unbounded exposure, whatever they stake and whatever reputation is published.

Saturating

Past the point where the limit covers their largest basket, more collateral buys nothing.
That last one is correct behaviour for a collateral system — an over-collateralised merchant is wasting money — and it is exactly why the earning side of the Trust Stake has to be a separate mechanism rather than the same dial.

k is a number you can reason about

The raw formula has a problem: k carries units of 1/√value, which makes it impossible to sanity-check. So the curve normalises against a reference:
Now k_bps = 10_000 means one reference unit of stake doubles the base limit. That is a sentence a person can argue with.
Integer throughout. isqrt is Newton’s method entered from above so it descends monotonically, starting at 2^ceil(bits/2) — a handful of iterations instead of the ~128 a naive start would cost, because compute budget is not free on chain.
The whole function is saturating rather than checked. Every path ends in min(.., hard_cap), so an overflow can only clamp to the cap — and a merchant held at their ceiling is the right answer to absurd inputs. A checked_* here would instead fail the redemption of a legitimate voucher.

Valued at redemption, with a visible haircut

SKR moves. A collateral model that pretends its collateral is stable is not a collateral model.
Both inputs are read live from RiskConfig at redemption, so a stake posted at a high price is revalued when the claim is actually made. The haircut is stored separately from the price rather than folded into it, so the discount is auditable instead of invisible.

Requested stake leaves the curve immediately

request_unstake removes the amount from the curve at request time, not at collection.Otherwise the cooldown hands the payer a free window: request the whole stake, keep trading at the ceiling that stake was buying, and collect it at the end. The cooldown would be buying them the attack instead of preventing it.
The cooldown floor is pinned to the settlement horizon for the same reason — vouchers signed before the request have not been presented yet:
And a frozen vault cannot unstake at all. First-loss capital that can leave after the loss is not first-loss capital.

The parameters are configuration, not constants

base, k, the hard cap, the haircut and the cooldown live in a RiskConfig account under a risk authority held separately from the program upgrade authority. That separation is the point: publishing a price is routine and frequent, and it must not need the key that can replace the program. They are configuration because they fall out of the reserve model, and that model is a commercial artefact rather than a code one. Baking in three plausible-looking numbers would be inventing the answer to the question the model exists to settle.

What the model says about these parameters

The model now exists — and it has opinions. See the reserve model in full, but the two that land directly here:
The curve raises required reserve below ~$250 of staked value. Staking lifts the limit, the limit is multiplied by every merchant the payer can reach, and √ has an unbounded slope at zero — so a small stake adds more exposure than it absorbs.The crossover is s* = (M·base·k/2)² / ref. It moves as , so halving k quarters it. Either require a minimum stake, or lower k.
The hard cap currently binds nothing. At base 50andk=1.0,reachinga50 and `k = 1.0`, reaching a 500 cap takes $81,000 of staked value. The cap and k have to be set together.
Both are RiskConfig updates rather than redeploys — which is why they were left as configuration in the first place.

Reputation

Published by the risk authority from settled volume, dispute rate and tenure — none of which the program can see. Bounded on chain at REPUTATION_MAX_BPS = 20_000 so a wrong or compromised authority cannot lift every merchant at once, and a vault opens at REPUTATION_NEUTRAL_BPS = 10_000 so the curve is a no-op until someone has something to say. Reputation decays with inactivity. The decay is applied by republishing, which is why set_reputation exists as an instruction rather than the value being set once at enrolment.

The migration property

A vault that has never staked behaves exactly as it did before the curve existed: stake 0, reputation neutral → limit == vault.floor_limit. That is what made the curve safe to add to a program that was already deployed, and it is a committed test.