How it works
The full path a trading fee takes before it becomes something you can claim.
The vault
Each pool gets one vault. The vault owns a single full-range Uniswap v4 position — liquidity spread across every possible price, so it never falls out of range and never needs rebalancing.
When you deposit, the vault adds your tokens to that position and mints you ERC-20 shares. Your shares are a pro-rata claim on the whole position. If the position holds 100 USDC and 100 tokens and you own 10% of the shares, you can withdraw 10 USDC and 10 tokens.
Harvesting
Trading fees accrue inside the Uniswap position. harvest() collects them. It is permissionless — anyone can call it, and it also runs automatically at the start of every deposit, withdrawal and compound.
Fees arrive in both tokens. The vault splits them three ways:
| Portion | Where it goes |
|---|---|
| Protocol fee | 1% of the harvest, accrued for the treasury to collect separately. |
| Stream share | Converted to USDC and paid out to stakers over seven days. |
| Compound share | Queued, then added back as liquidity — raising every share's backing. |
The split between streaming and compounding is a per-vault setting. At the default of 100% streaming, everything goes to stakers as claimable USDC.
Converting the token side
Half the fees arrive as the pool's token rather than USDC. The vault swaps that side into USDC through the same pool, so everything it pays out is denominated in one asset.
That swap is bounded. The vault keeps its own time-weighted average price and refuses to trade if the current price has drifted too far from it. If the price looks manipulated — or if the vault has not gathered enough price history yet — it simply defers the conversion and tries again next time.
Streaming, not dumping
A harvest is a lump of value arriving at one instant. If it were added straight to what your shares are worth, anyone could deposit in the block before a harvest, withdraw in the block after, and walk off with fees earned during a week they were not there for.
So the proceeds are paid out linearly over seven days instead. To capture a meaningful amount you have to actually hold the position for a meaningful time — which is the same thing honest liquidity providers are doing.
deposit ──► shares ──► rewards accrue every second ──► claim()
│
└─ transferring shares carries your
unclaimed rewards with you, not themCompounding
Whatever is not streamed goes into a queue. Calling compound() takes that USDC, swaps half into the token, and adds both sides back into the position as new liquidity.
No new shares are minted, so the extra liquidity is spread across existing holders. Your share count stays the same; what each share is worth goes up.
Who runs it
Anyone can. poke(), harvest(), compound() and collectProtocolFees() are all callable by anyone, and none of them let the caller redirect funds: the conditions decide whether a call is valid, not who made it. They exist as buttons on every vault page.
Permissionless is a statement about who may run it, not about whether anything needs running. Two things genuinely depend on somebody calling in:
poke()records a price observation. The vault keeps its own thirty-minute average, built from the last 32 observations, and will only swap while the current price sits close to that average. Single-sided deposits and the conversion of token-side fees both need it. A pool with nobody trading through the vault does not refresh it by itself, so a keeper pokes every vault roughly every ninety seconds. Slice runs one; it covers every vault the factory knows about, including pools listed by strangers, and it skips empty ones.harvest()collects fees and starts the stream. Deposits and withdrawals call it on the way through, so a busy pool keeps itself current; a quiet one is harvested by the same keeper.compound()turns the queue into liquidity, once the oracle can price it.
What never depends on any of this: two-sided deposits, withdrawals and claims. None of them swap, so none of them consult the price. If every keeper in the world stopped, you could still get in with both sides and out with everything.
On a token that moves several percent a minute, the price may sit outside the band most of the time however often it is poked. The vault page says so when that is the case, and single-sided deposits pause rather than execute at a price the vault cannot verify. More on the stream →