Lottery personal boost v2
Lottery personal boost v2
Product lock (2026-09-03). This page is the normative personal-boost formula for when LotteryManager4626 sets boostManager after the boost-source timelock. It is not live.
v1 (live): boostManager and vaultGaugeVoting stay address(0). Personal multiplier is identity 1.0×. Gauge add is 0. Do not treat Share-coverage comments in current LM bytecode as the v2 product rule.
Reader path: LotteryManager4626 · ve4626. Curve kernel bounds: 2.5× proof (Lean proved [1.0, 2.5]; this page locks D, coverage, and the epoch budget).
Locked formula
BasePPM is unchanged: min(swapUSD / 250_000, baseCeilingPPM) (default ceiling 40,000 PPM / 4% at $10,000). Solana then scales odds by 400 / 690. Stake USD stays gross venue notional.
swapEff = min(swapUSD, 10_000) # same ceiling as base PPM
boost = Curve(swapEff, D=100_000, ve/Ve)
cover = min(1, veUSD / swapUSD)
veUSD = locked■4626_amount × markPrice(■4626)
FinalPPM = BasePPM × (1 + (boost - 1) × cover)
ve / Ve are effective veLottery for the beneficiary and live total ve4626 power. boost is the Curve rate. cover is how much of this fill's USD that rate may touch. On the consume path, substitute remaining for veUSD (remaining starts at veUSD each epoch).
Classic Curve (α = 0.4)
l in Curve is swapEff, not coverage USD and not creator Share supply.
working = min(l, 0.4·l + 0.6·D·(ve/Ve)) # D = 100_000; l = swapEff
boost = min(2.5, working / (0.4·l)) # ∈ [1.0, 2.5]
| Symbol | Meaning |
|---|---|
l / swapEff | min(swapUSD, 10_000) |
D | Protocol constant 100,000 (not creator ShareOFT supply USD) |
ve / Ve | Beneficiary veLottery / live total ve power |
veUSD | Locked 4626 principal × |
cover | min(1, remaining / swapUSD) on the epoch budget; see consume below |
veUSD is not decaying ve-units × price. Decay changes ve/Ve (the rate). Lock size × mark changes cover (how much of the ticket that rate applies to).
Why swapEff matches the $10k base ceiling
Uncapped Curve(l = swap) after BasePPM is already capped makes personal EV+ non-monotonic for tickets above $10k: more USD can lower the Curve rate faster than base PPM grows. Cap Curve’s l at the same $10,000 as baseCeilingPPM.
2.5× threshold
Full 2.5× requires working = l, which is ve/Ve >= swapEff / D:
Ticket (swapEff) | ve share for 2.5× |
|---|---|
| $100 | 0.1% of Ve |
| $1,000 | 1% of Ve |
| $10,000 (full base ceiling) | 10% of Ve |
Small covered retail tickets reach 2.5× with a small ve share. A full $10k ticket needs a real slice of total ve. Whales do not mint 2.5× on large tickets by locking dust.
Cover vs rate
boost and cover are independent knobs:
| Position | Rate (boost) | Cover | Effective personal mult |
|---|---|---|---|
| Thin lock, fat ve | High (near 2.5×) | Small | Close to 1.0×: almost none of the ticket is covered |
| Fat lock, tiny ve | Low (near 1.0×) | Full | Close to 1.0×: covered, but the Curve rate is weak |
| Fat lock, enough ve | High | Full | Up to 2.5× on swapEff |
Worked cover: $2,000 swap, $500 remaining veUSD → cover = 0.25. If boost = 2.5, effective multiplier is 1 + 1.5 × 0.25 = 1.375×.
Epoch boost budget (wash control)
Each beneficiary (canonical CSW / wallet) holds a remaining coverage budget for the epoch. Base, Solana, and every other venue share one consume ledger. No per-chain double spend.
- Start / refresh:
remainingstarts at currentveUSDeach epoch. A live-mark refresh is allowed only through the same fail-closed oracle asveUSD(below). - Each fill:
cover = min(1, remaining / swapUSD), thenused = min(swapUSD, remaining), thenremaining -= used. Use remaining (not a second snapshot ofveUSD) for that fill'scover. - Unlock / lock decrease mid-epoch:
remaining = min(remaining, live veUSD). Remaining never exceeds live lock USD. - AMOE: attested points, not a venue swap. This budget is for venue fills only unless a later spec extends consume to attested USD.
Wash intent: one unit of lock USD cannot cover more than one unit of swap USD per epoch across all venues.
Oracle
uses the same fail-closed staleness and deviation posture as other lottery USD notionals (venue quote × feed). Missing, stale, or out-of-band price → no personal boost for that fill (identity 1.0×). Never silently default the mark to 1. Ticket USD stays venue spend, not this mark: LotteryManager4626, CreatorOracle.
Out of scope
These stay separate from personal Curve boost. Do not fold them into FinalPPM above.
Gauge lottery pot (additive)
Global pot 6.942% (69,420 PPM). Per-vault cap:
C(n) = 35_000 - 25_000 / n
n is the number of vaults sharing the pot. 1% at n = 1 (10,000 PPM), 3.5% asymptote (35,000 PPM). Added after personal boost; maxWinChance still caps the envelope.
Fees-on-vote / bribes
Solidly-style gauge loop (vote, bribe, stream). Not an input to boost, cover, or veUSD.
Rejected alternative (blend B)
Do not implement:
l = min(swapUSD, veUSD) # coverage inside Curve
boost = Curve(l, D=100_000, ve/Ve)
FinalPPM = BasePPM × (1 + (boost - 1) × (l / swapUSD))
Why it is wrong (unsaturated): when working < l,
boost = 1 + 1.5 · D · (ve/Ve) / l
uplift = (boost - 1) · (l / swapUSD)
= 1.5 · D · (ve/Ve) / swapUSD
Coverage l cancels. Locking more past the saturation threshold does not raise EV in that regime; only ve/Ve and swapUSD remain. The locked formula keeps Curve’s l on swapEff and applies coverage outside Curve, so extra lock USD can still raise cover until 1.
Why uncapped l = swap is also wrong: past the $10k base ceiling, BasePPM is flat while Curve’s l keeps growing, so EV+ is non-monotonic. That is the swapEff cap above.
July 2026 LM comments (l = min(creatorShareUSD, swapUSD), L = creator Share supply USD) are the unarmed v1 door plus FriendKey-era coverage. They are not this lock. FriendKey stays out of lottery.
v1 vs v2 arming
| Mode | v1 live | v2 (this spec) |
|---|---|---|
boostManager | address(0) | Set after propose → 24h → commit → timelock arm |
| Personal mult | 1.0× | 1 + (boost - 1) × cover ∈ [1.0, 2.5] |
| Gauge PPM | 0 | Additive pot above; still optional / separate window |
| Coverage | n/a | Lock 4626 USD budget, unified per beneficiary per epoch |
Keep LM pointers at zero until an implementation matches this page. Arming today’s Share-coverage _applyBoost is not v2.
See also
- LotteryManager4626 — live win-chance, venue stake, v1 dark pointers
- ve4626, ve33, and veLottery — lock asset vs utility
- Curve 2.5× (Lean) — kernel bounds, not this blend
- Addresses — live LM pin