Levee has one use for its protocol revenue: buying $LEVEE and burning it. A FeeCollector swaps fees to ETH, and BuybackV2 spends the ETH on $LEVEE and sends it to 0x…dEaD. Every call on the way is open to anyone, and the Protocol page has a button for each.
The path of one fee
A fee reaches the FeeCollector by one of two roads. A Levee pool swap pays its protocol share straight in; every other fee is booked in the FeeRouter until someone calls flush(token) (see Fees and referrals). The FeeCollector turns what it holds into ETH for BuybackV2, and buyback() spends that ETH on $LEVEE in the ETH/LEVEE Uniswap v4 pool, which pays the tokens directly to 0x…dEaD.
The protocol share of pool fees
LPs keep most of a Levee pool's swap fee. ProtocolConfig.protocolFeeShareBps (2000, so 20 % of the fee, at most 50 %) goes to the FeeCollector, always in the token you pay with.
- DAMM and stock pools are Uniswap v4 hooks and send it with
poolManager.take. If the PoolManager is short of that token mid-swap, the hook mints itself an ERC-6909 claim, and anyone can call the hook'ssweep(currency)to pay it out to the FeeCollector. - DLMM pairs transfer it on every swap, and on the composition fee a deposit into the active bin pays.
How each pool sets its fee is in Levee pools.
Converting fees to ETH
The owner gives each fee token a route: Router hops ending in native ETH, a cap per call, and an optional oracle floor. Then anyone can convert.
convert(token, 0)converts the balance up to the cap. An explicit amount above the cap revertsOverCap.- With the floor on,
minEthOutprices the input from theAssetRegistryfeed against Chainlink ETH/USD and accepts at mostmaxSlippageBps(3 %) less. A stale feed revertsStaleOracle. - WETH needs no route:
unwrapWeth()unwraps it 1:1.forwardEth()passes ETH fees on.
A production deploy has no routes until the owner adds them, so a token without one waits in the FeeCollector. A local deploy seeds USDG (10 000 per call) and its seeded stock (10 per call).
Buying and burning
buyback() takes BuybackV2's ETH balance, including any ETH sent with the call, up to maxEthPerCall (0.05 ETH). It keeps callerRewardBps (0.5 %) of that budget for the caller and spends the rest; a partial fill pays a proportional reward. Unspent ETH waits for the next call.
The price guard
$LEVEE has no Chainlink feed, so BuybackV2 checks the pool against a reference price that follows it slowly.
- The reference moves at most
driftBpsPerHour(30 %) per hour since its last update, and at mostmaxDeviationBps(10 %) per update. With no time elapsed it cannot move, so a pump inside one block does not shift it. buyback()catches the reference up, then revertsPriceAboveBandif $LEVEE is above the band: 10 % on the pool price ($LEVEE per ETH), about 11.1 % on $LEVEE's ETH price.- A cheaper $LEVEE never blocks a buyback, however old the reference.
- The swap stops at the tighter of the reference band edge and 10 % above its own starting price.
A reverted buyback also undoes its catch-up, so poke() exists to move the reference on its own. It pays nothing. The API's optional buybackPoker bot pokes when the reference is at least 1 % off the pool price and 600 s old. After PriceAboveBand: poke, wait, retry.
Burned and circulating supply
A burn is a transfer to 0x…dEaD, so circulating supply is totalSupply() − balanceOf(0x…dEaD), checkable by anyone. BuybackV2 also counts totalEthSpent and totalBurned. The indexer keeps every Converted and BoughtBack event for GET /protocol, and the Protocol page reads the live state on chain every 20 s.
What the owner controls
One cold key owns ProtocolConfig, FeeCollector and BuybackV2; ownership changes in two steps, propose then accept.
| Contract | The owner can | Limit |
|---|---|---|
| ProtocolConfig | set the protocol share; name another FeeCollector | share at most 50 % |
| ProtocolConfig | pause | stops swaps and new liquidity, never withdrawals |
| FeeCollector | set or clear routes; set maxSlippageBps; name another buyback | slippage at most 20 % |
| FeeCollector | sweep a token | only a token with no route, never ETH |
| BuybackV2 | configure the pool | once |
| BuybackV2 | set maxEthPerCall, callerRewardBps, the guard; resetReference() | reward at most 5 %, band 1 to 2000 bps, drift at most 10 000 bps per hour |
So the owner can redirect revenue that has not reached BuybackV2: by naming another collector or buyback, or by clearing a token's route and sweeping it. It cannot take ETH from BuybackV2, and none of these contracts reaches a user's position or deposit. The other keys are in Security model.
Reference
Calls and reverts
| Call | Can revert with |
|---|---|
FeeRouter.flush(token) | NothingToClaim |
sweep(currency) on a hook | NothingToSweep |
FeeCollector.convert(token, amount) | NoRoute, OverCap, StaleOracle, ZeroAmount, or the Router's TooLittleReceived on a dust amount |
FeeCollector.unwrapWeth(), forwardEth() | ZeroAmount |
BuybackV2.buyback() | NotConfigured, OncePerBlock, NothingToSpend (no ETH, or nothing the band allows), PriceAboveBand |
BuybackV2.poke() | NotConfigured |
Parameters
| Name | Allowed | Default | Effect |
|---|---|---|---|
protocolFeeShareBps | 0 to 5000 bps of the fee | 2000 | ProtocolConfig: Levee pool fee share sent to the FeeCollector |
maxSlippageBps | 0 to 2000 bps | 300 | FeeCollector: the oracle floor on convert |
maxEthPerCall | any ETH | 0.05 | BuybackV2: spend per buyback (BUYBACK_MAX_ETH_PER_CALL) |
callerRewardBps | 0 to 500 bps | 50 | BuybackV2: the caller reward |
maxDeviationBps | 1 to 2000 bps | 1000 | BuybackV2: the band, and the largest step the reference takes |
driftBpsPerHour | 0 to 10 000 bps per hour | 3000 | BuybackV2: how fast the reference follows the pool |
contracts/src/venue/periphery/FeeCollector.solroutes, the oracle floor, convert, sweepcontracts/src/venue/periphery/BuybackV2.solbuyback, poke, the reference and the bandcontracts/src/venue/core/ProtocolConfig.solthe protocol share and pausecontracts/src/venue/hooks/LeveeHookBase.solhow the hooks pay their sharecontracts/script/venue/VenueWiring.soldeploy values and ownershipcontracts/script/venue/VenueSeed.sollocal routes and the test $LEVEE poolapps/web/lib/amm/buyback.tsthe guard reading and circulating supply on the page