DEXs, lending markets and vaults
Who earns while revenue tokens sit in a pool, a router, a lending market or a vault, and the market each token opens at mint.
A revenue token trades and moves like any ERC-20. What a DEX, an aggregator, a lending market or a vault has to know is who earns while the token sits with it, because income goes to the address that holds the token and only that address can claim it.
The token
- A fixed supply, minted once: no mint after it, no burn function and no rebase. 18 decimals.
- No transfer fee, no pause and no blocklist. A transfer moves exactly the amount sent and calls nothing outside the token.
- A transfer to the token's own address reverts with
InvalidRecipient. - A transfer costs more gas than a plain ERC-20's: before the balances move it releases each asset's due income, settles both sides and writes the balance checkpoints drops are paid from. Estimate gas for it rather than use a fixed figure.
Who earns
| Holder | Earns | Who can claim |
|---|---|---|
| A wallet, or any contract | Yes | Only that address: claim and claimAll pay the caller's own income, and a signed claim needs its signature, through ERC-1271 for a contract |
| The Uniswap v4 PoolManager, which holds every v4 pool's tokens, the token's own market included | No | Nothing accrues to it; its part goes to every other holder |
| 0xdead, the token's drop box, the token itself | No | Nothing accrues to them |
So:
- Revenue tokens in a Uniswap v4 pool earn nothing while they are in it. An LP who adds them gives up their income for that time.
- A Uniswap v2 pair, a v3 pool or any other contract with no way to call
claimearns income and drops that nobody can ever take. - Holding inside one transaction earns nothing. Income is released by the second and a drop goes by balances at the end of the block before, so a router, an aggregator's executor or a flash loan gets neither.
The market opened at mint
- A token minted with a market has a revenue token / ETH pool on the Hookr root.
MarketOpened(token, familyId, poolId, seed, bridge, bridgeBps)names it, and the PoolManager'sInitializefor that pool id gives its key. rHOOKR's market, for one, has native ETH ascurrency0, rHOOKR ascurrency1, fee0x800000(the dynamic fee flag), tick spacing 60 and the Hookr root ashooks. - The pool's LP is locked in the token's family door, for good or until the family's unlock block.
- The pool starts with revenue tokens only, its seed. Buyers can take them for ETH from the first block, and sellers can sell into it once buys have left ETH there.
- Its LP fees go to the token: the ETH side becomes income at the next sync, and the side paid in the revenue token goes to 0xdead. Its royalty names the token too.
- Markets opened from /tokenize use the tokenizer's
defaultMarket, which turns arb recapture on, so a swap on one carries the lane's gas floor. Swapping and quoting has the routes, the quoter and the floor.
Lending markets and vaults
- A deposit is a transfer, so it settles first: the depositor keeps the income released before it, and from then on the income accrues to the contract.
- The contract must claim it:
claimAll(to)orclaim(asset, to)called by the contract, and its drops from the drop box withclaim(dropIds, to). A contract that answers ERC-1271 can instead sign a claim that anyone sends. Without either, the income and the drops stay owed to the contract for good. - Tokens lent out earn for the borrower while it holds them. A liquidation is a transfer like any other: the account liquidated keeps what was released before it.
- ETH is paid with a plain call, so a contract that claims ETH to itself must be able to take ETH.
- To pass income on to depositors, follow the add-ons: time shares and Compound hold revenue tokens, claim for their holders and hand the income on.
Before you send revenue tokens anywhere is the same warning for holders.