This chapter lists what Levee charges, who receives it and how a referrer earns a share. Levee charges on what you put in or what a position earns, not on what you take out, with one exception for structured notes. Bounties, which pay for public upkeep calls, come last.
What you pay
| Action | Fee | Taken from | Referrer credited |
|---|---|---|---|
| Swap in a Levee pool | the pool's fee, 20 % of which is the protocol share | your input | none: the share goes straight to the FeeCollector |
| Swap through the Levee Router | no Levee fee beyond the pools' | - | - |
| Spot trade on the Uniswap path (Trade) | 25 bps | the output | nobody, see below |
| Zap into a Uniswap range | 25 bps | the input | yours |
| Keeper harvest or rebalance | 10 % | the fees collected | the position owner's |
| Range order fill or cancel | 10 % | the fees the order earned | the order owner's |
| LP or hedged vault harvest or rebalance | 10 % | the fees collected | none: the vault names itself |
| Structured note exit before maturity | 50 bps | the gross amount withdrawn | none: the note names itself |
| Pre-market perp open, close or liquidation | 30 bps | the notional | the trader's |
Levee pool fees depend on the pool. A DAMM pool charges a base fee of 5 to 100 bps plus a volatility surcharge, at most 500 bps in total, and a new pool may add an anti-snipe fee that starts as high as 5000 bps and falls to the base fee within an hour. Stock pools charge 30 bps while the market is open, 150 bps while it is closed and 500 bps when the price feed is stale (deploy values; the owner can set each asset up to 1000 bps). A DLMM pair charges a base fee plus a variable fee, capped at 10 %. Levee pools has the detail.
Some actions pay no Levee fee at all: a deposit into any vault, a withdrawal from an LP, hedged, DLMM or stock vault, a DLMM limit order, and a launch's pre-launch vault. Some fees are not Levee's: a Pons curve charges its own fee and creator tax, and Lighter charges its own trading fees. The signer can tag Lighter orders with an integrator account (INTEGRATOR_ACCOUNT_INDEX, unset by default) for Lighter's fee-share attribution.
Fees come out of earnings
When a keeper, a vault or a range order closes or re-centres a Uniswap position, the contract compares two numbers: decreaseLiquidity reports the principal alone, and collect pays out principal plus fees. The 10 % and any bounty apply only to the difference, so a position that has earned nothing pays nothing and no harvest reaches the liquidity itself.
Inside one split the order is fixed: the protocol share first, then the caller's bounty, then everything left to the owner.
How a fee is booked
Every fee except the Levee pools' protocol share passes through FeeRouter, a contract with no owner and two fixed addresses: the ReferralRegistry it reads and the treasury it pays, which is the FeeCollector.
- The paying contract transfers the fee to the router, then reports it with
take(token, amount, user). A fee paid in native ETH arrives withtakeNative(user)instead; a v4 zap paid in ETH uses it. takeis public, so the router checks the report against its balance. It accepts the fee only if the balance covers everything already owed plus the new amount, and revertsFeeNotReceivedotherwise.- If
useris bound to a referrer, 20 % (REFERRAL_BPS) is credited to that referrer and the rest to the treasury. The router emitsTaken. - A referrer calls
claim(token)to pull their own balance. Anyone can callflush(token)to push the treasury's balance to the FeeCollector, where buyback and burn takes over.
The Uniswap-path skim
On the Trade page, a spot trade that goes through the Uniswap Universal Router includes a PAY_PORTION step that sends 25 bps of the output to the FeeRouter as a plain transfer; the minimum you receive is net of it. Nothing reports that transfer with take, so it stays in the router as an unbooked balance that neither claim nor flush can move. Anyone may book it with take, and whoever does picks the user, so the referrer credited is theirs to choose. No Levee service books it today. When the Levee Router pays more on a live quote, the trade goes through it instead and no skim applies. A build with no FeeRouter in its manifest turns the skim off.
Referrals
ReferralRegistry holds two write-once links and has no owner.
- Your code. On the Ideas page, register 1 to 8 letters or digits; the app upper-cases the code and stores it as
bytes8withregister. An address owns one code for life, and a code belongs to one address. - Your referrer. Opening
levee.trade/ideas?ref=CODEoffers a one-clickbindif you have no referrer yet. A binding never changes, and you cannot refer yourself. - Who counts as the user. Each contract names the user behind a fee: the zapper, the position owner rather than the bot that harvested, the order owner rather than the keeper that filled, the trader. A vault or a note names itself and can never bind, so its fees go to the treasury in full. A vault depositor is not referred through the vault.
- Earnings. The indexer adds each
Takenreferrer share to the referrer's per-token total, andGET /referral/:addressprices those totals into one dollar figure for the Ideas page. You claim on chain withFeeRouter.claim(token), one token at a time, from the referrer wallet. The app has no claim button yet.
Bounties
A bounty pays the gas of a public call nobody else is paid to make. The contract pays it to msg.sender before the owner's share, and it never passes through the FeeRouter.
| Call | Bounty | Paid from |
|---|---|---|
PositionKeeper.harvest, rebalance | the owner's bountyBps, at most 3 % | the fees collected, after the 10 % |
LPVault.harvest, rebalance | 0.5 % | the fees collected, after the 10 % |
RangeOrders.fill | 1 % | the order's output |
PreMarketPerp.liquidate | 1 % | the margin left after the loss and the fee; the rest goes to the insurance fund |
Seed and graduated vaults write bountyBps 50 into their policy, matching what the vault pays. Levee's keeper bot sends a bounty-paid call only when the bounty is at least 3 times the gas, and skips it when it cannot price the bounty. An untaken bounty costs nothing; the fees stay in the position.
The pre-market perp fee
PreMarketPerp charges 30 bps of the notional on open, and reverts TooSmall if that fee would reach the collateral. It charges again on close and on liquidation, capped at collateral plus PnL and zero when that is zero or less, so a fee never deepens bad debt. INSURANCE_SHARE_BPS (3333) sends one third of each fee to the insurance fund and two thirds to the FeeRouter in the trader's name. Graduation and pre-market perps covers the market.
Points
Points live in the API's Postgres, not on chain: 1 point per dollar of volume, 5 per dollar of fees earned, and volume counts double for 7 days after you post an idea. Totals are recomputed from the points_events ledger rather than incremented. GET /points/:address returns the total and its parts (volume, fees, thesisBonus); POST /points/recompute rebuilds every total behind ADMIN_SECRET.
A background job reads indexed Levee activity every few minutes and writes it to the ledger: swaps through the Levee Router, pre-market perp opens and voluntary closes (liquidations earn nothing) count as volume; keeper harvests, range-order fills, vault harvests (split by share) and the 20 % referral share count as fees earned. Each row's id comes from its on-chain event, so a re-read never counts twice, and amounts are priced in USD when the job reads them. Plain Uniswap fee collections are not Levee activity and earn nothing. rank is your place among the stored totals. Nothing is promised about points.
Reference
Constants
| Constant | Value | Where |
|---|---|---|
ZAP_FEE_BPS | 25 | LeveeZapV3, LeveeZapV4 |
SPOT_FEE_BPS | 25 | apps/web/lib/trade/spot.ts |
PROTOCOL_FEE_BPS | 1000 | PositionKeeper, LPVault, RangeOrders |
EARLY_EXIT_BPS | 50 | StructuredVault |
TAKER_FEE_BPS, INSURANCE_SHARE_BPS, LIQ_BOUNTY_BPS | 30, 3333, 100 | PreMarketPerp |
REFERRAL_BPS | 2000 | FeeRouter |
MAX_BOUNTY_BPS, HARVEST_BOUNTY_BPS, KEEPER_BOUNTY_BPS | 300, 50, 100 | PositionKeeper, LPVault, RangeOrders |
protocolFeeShareBps | 2000, at most 5000 | ProtocolConfig |
FeeRouter and ReferralRegistry errors
| Error | When |
|---|---|
FeeNotReceived | take with the zero address as token, or a balance that does not cover the report |
NothingToClaim | claim or flush with nothing owed |
NativeTransferFailed | the ETH recipient refused the payment |
ZeroCode, CodeTaken, AlreadyRegistered | register with an empty code, someone else's code, or a second code |
UnknownCode, SelfReferral, AlreadyBound | bind to a code nobody owns, to your own code, or a second time |
contracts/src/FeeRouter.soltake, takeNative, claim, flush, the balance checkcontracts/src/ReferralRegistry.solregister and bindcontracts/src/PositionKeeper.solfees-only split: protocol, bounty, ownercontracts/src/LPVault.solthe vault as its own usercontracts/src/RangeOrders.solthe 10 % on earned fees and the fill bountycontracts/src/PreMarketPerp.solthe taker fee, the insurance third, the liquidation bountyapps/web/lib/trade/universalRouter.tsthe PAY_PORTION skimapps/web/app/(app)/ideas/ReferralPanel.tsxregister, the ?ref= bindapps/api/src/points.tsthe points rulesapps/api/src/points/job.tsthe job that writes the ledger from indexed activityapps/api/src/bots/chain.tsthe bounty-to-gas rule