The hedge: harvest & breathing
A coin's capital is never entirely in one place. Part of it is visible depth in the pool, the WETH that absorbs sells. Part of it is perp margin on Lighter, the exposure that makes the coin a leveraged bet. The split between the two isn't fixed — it moves with the coin's size and with what traders are doing, and that motion is the breathing.
Harvest — pool to hedge
When a coin's pool holds more WETH than it needs as depth, the keeper harvests the excess: it pulls that WETH out of the LP position, swaps it to USDG, mints the coin's backing LT, and the value bridges to Lighter as perp margin. The coin freed on the sell side by that removal is redeployed as a fresh range just above spot, so depth follows the price up instead of being left behind at the launch price.
How much counts as excess depends on the coin's size. The protocol targets a keep percentage that starts around 70% at roughly $5k of pool capital, passes through 60% at $15k and 45% at $50k, and settles on a 35% floor above $150k. A young coin keeps most of its capital as depth because a thin round-trip kills a fresh launch; a mature coin can afford a smaller percentage while its absolute depth still climbs.
Expand — hedge to pool
The reverse leg. When sells thin the pool below its keep target, the keeper redeems backing LT, recalls the margin from Lighter, and adds it back as WETH depth positioned just below spot — a floor that buys the coin if the price dips into it.
This is why depth on a perp.fun coin recovers after a sell-off instead of staying gutted. Nobody has to top it up; the coin's own treasury refills it.
The hedge doesn't need to be instant. A margin round-trip through the bridge takes minutes while your trades take one block. The design keeps that asymmetry harmless by never letting the hedge stand between you and your exit.
Reanchor
As the price moves, a fixed range drifts away from where trading actually happens. reanchor() re-centres the coin's single-sided ladder on the current price.
This matters for a non-obvious reason: any gap between the live price and the protocol's ladder is an opening for a third party to LP into and capture the coin's entire order flow. On the current stack the pools are LP-gated, which removes that vector at the root, but the ladder still needs to track spot for the depth to be usable at all.
Why it batches
Every harvest, expand and reanchor is an on-chain transaction with gas and swap costs, and the bridge to Lighter has hard minimums — a $5 deposit floor and a $3 fee. Reacting to each individual trade would burn more value than it captures, and a stream of tiny liquidity events makes a chart look broken.
So the keeper works on a deadband: it holds until the pool drifts meaningfully from its keep target, then makes one move. Every knob rides the same maturity signal, the coin's size. A young coin around $15k FDV gets a wide 20% deadband, clips capped at 35% of position liquidity, and lazy reanchoring — few, proportionate liquidity events, a clean chart, no churn. A mature coin around $4M gets a tight 5% band, 12% clips and snappy reanchoring — a precise hedge whose adjustments are tiny relative to its market cap. Below a $25 minimum nothing fires at all, because the two swaps, the mint and the bridge would eat the whole slice.
Calibration lives in keeper/hood10l/single_harvest.py as pure functions with no chain access, unit-tested in isolation: target_deploy_bps(quote_tvl) sets the keep percentage, DEFAULT_BAND_CURVE and DEFAULT_CLIP_CURVE interpolate the deadband and clip on log10(TVL), DEFAULT_MIN_HARVEST_USD = 25.0, and DEFAULT_MAX_CLIP_BPS = 5000 caps any single sweep at 50% of position liquidity.
On-chain, harvest(), expand() and reanchor() are all onlyKeeper and reentrancy-guarded. Margin transport goes through Relay, journaled exactly-once with crash-resume, with opposite flows netted over a rolling window so only the net crosses the bridge and sub-$5 dust batched rather than sent.
