Skip to content

Build on revenue tokens

The calls a contract or an app makes on a revenue token: sync, claims, the asset books, the earning supply, drops and signed actions.

On this page

A revenue token is an ordinary ERC-20 with an income ledger inside it. Anything that can hold an ERC-20 can hold one, and any contract can read its income, pull it in, claim it and pass it on. Nothing about the token changes after the mint, so what you build on it can rely on every rule below for as long as the token exists.

This section is for builders. It covers the calls a contract or an app makes, how income accrues, how a new platform plugs in as a door, the add-ons as worked examples, the read APIs, and a list of things to build.

The calls

Every call below is on the revenue token itself (IHookrRevenueToken). Assets are numbered: asset 0 is always native ETH, and the rest are the up to three currencies the token's streams pay in.

CallWhat it does
sync()Pulls every door, recognizes what arrived and starts releasing it. Anyone may call; the caller gets the tip when the pull is at least 0.001 ETH.
syncSome(doors)The same over the listed door indexes only, to step past a door that misbehaves.
claimable(account, asset)What account can claim of asset now, with the release run up to this block.
claim(asset, to) / claimAll(to)Pays the caller's income in one asset, or every asset, to to.
releasable(asset)How much of asset a release now would move to holders.
poke()Releases every asset's due income. Transfers, claims and syncs do it too.
assetCount() / assetAt(asset)The asset list and each asset's books: received, paid, what is still releasing and until when.
earns(account) / earningSupply()Whether an address earns, and the supply that does. The PoolManager, 0xdead, the drop box and the token itself never earn.
doorCount() / doorAt(i)The doors, fixed at the mint, each with its kind, its contract and its gas stipend.
depositBonus(asset, amount)Pays income in from anyone, released like the rest, with no tip.
dropBox() / dropStray(asset)The token's drop box, and turning any other ERC-20 sent to the token into a drop.
streamSeconds() / tipBps() / bridge() / bridgeBps()The release period, the tip and the Fee Bridge slice, all fixed at the mint.

A sync needs gas for every door's stipend. A call that leaves too little reverts with SyncStarved instead of skipping a door; send more gas, or skip the door with syncSome.

The tokenizer adds the record of each token: tokenCount() and tokenAt(i) list every token it made, tokenizations(token) says who made it, which way in, its term and Hookr's leg, and streamsOf(token) lists each stream with how and when it ends.

Signed actions

A holder never needs gas. Every action can be signed and sent by anyone, under the token's EIP-712 domain (eip712Domain(), EIP-5267):

  • permit: ERC-2612, with sequential nonces.
  • transferWithAuthorization and receiveWithAuthorization: EIP-3009-style signed transfers with random nonces, the form x402's EVM "exact" scheme settles with.
  • claimWithSig and claimAllWithSig: a claim that pays only the to the holder signed, refused past its deadline; cancelAuthorization revokes an unused nonce.

Each signature can come from an EOA or a contract wallet through ERC-1271, so a smart wallet or an EIP-7702 account signs like anyone else. Permit2 works as with any ERC-20.

The rest of this section