Pre-launch. The protocol is not publicly live yet. This documentation describes the contracts as implemented; deployed addresses are published at launch.

SecondaryHook

Owns the token↔$LP24 pool for every graduated token on V4-family chains. Deliberately minimal: one pool per token, a flat fee taken in the token and burned, permanently locked liquidity, and nothing else.

Contract Type

Singleton — one per chain, on Base, BSC, Polygon and Robinhood. No owner, no admin keys, no upgrade path. Not deployed on Gnosis.

One-directional coupling

SecondaryHook reads PrimaryHook.tokenInfo() to verify a token graduated. PrimaryHook needs nothing back — it pushes funds at graduation and never interacts again. Even the $LP24 acquisition swap is an ordinary fee-paying swap, so there is no fee-exemption path between the two contracts.

Pool Creation

notifyReserved(token: address) external payable

PrimaryHook only. Delivers and earmarks this token's native share during graduation. The token side arrives via a separate ERC-20 transfer in the same transaction.

Because only the PrimaryHook can credit nativeEarmark, the earmark cannot be forged — which is what makes createSecondary's per-token accounting sound.

Reverts
  • "Only PRIMARY_HOOK"
  • "Wrong native amount" — must equal SECONDARY_NATIVE_RAW exactly
  • "No secondary for PROTOCOL_TOKEN"
Emits

SecondaryFunded(token, nativeAmount)

createSecondary(token: address) external

Create the token↔$LP24 pool using funds this contract already custodies. Anyone can call — a keeper, a bot, the deployer. Not payable: the caller brings nothing and pays only gas.

Swaps the earmarked native for $LP24 on the primary $LP24 pool, initializes the pool at the resulting ratio, and mints a full-range position owned by this contract.

Requires
  • token != $LP24
  • Token registered in PrimaryHook (deployer non-zero)
  • No secondary already exists
  • Contract holds at least 40,000,000 × 10⁹ (40M)
  • nativeEarmark[token] >= SECONDARY_NATIVE_RAW — consumed on success
  • The $LP24 pool exists and is initialized
Reverts
  • "No secondary for PROTOCOL_TOKEN"
  • "Token not registered in PrimaryHook"
  • "Secondary exists"
  • "Token funds not received"
  • "No native earmark for token"
Emits

SecondaryCreated(token, poolId, protocolTokenAmount, tokenAmount, positionId, tokenIsCurrency0)

Safe to retry

A revert costs only gas. The earmark is consumed up front, but any later failure in the same call rolls it back along with everything else — so on failure the custodied funds and the earmark both survive for a later attempt, and on success the earmark is spent exactly once.

Fee Behaviour

A flat 60 bps (0.6%) is taken in the launched token, in both directions, and burned to 0x…dEaD. There are no tiers, no reinvestment, and no deployer or protocol share.

CaseCallbackTaken from
Token is the inputbeforeSwapThe specified input amount
Token is the outputafterSwapThe token output delta
$LP24 sideNever taxed

take() sends the fee directly to the dead address. It debits the caller — this hook — regardless of recipient, which clears the delta the callback returns, so one call both burns the tokens and settles the pool. Each burn emits SecondaryTokenBurn(token, amount).

Dispatch is by pool id: tokenOfPool[poolId] returns the zero address for any pool that is not one of ours, and the callbacks no-op. indexOfPool[poolId] records which currency slot the launched token occupies — its default of 0 is indistinguishable from "token is currency0", so tokenOfPool must always be checked first.

View Functions

FunctionReturns
hasSecondary(token) -> boolWhether a secondary pool exists
secondaryPoolIdOf(token) -> bytes32Pool id, or zero if none exists
nativeEarmark(token) -> uint256Native reserved but not yet consumed
tokenOfPool(poolId) -> addressReverse lookup, zero for foreign pools
indexOfPool(poolId) -> uint80 if the token is currency0, 1 if currency1
getHookPermissions() -> uint256Permission bitmap for the venue

Constants

ConstantBaseBSCPolygonRobinhood
SECONDARY_FEE_BPS60 bps (0.6%)
SWAP_SLIPPAGE_BPS200 bps (2%)
SECONDARY_TOKEN_RAW40,000,000 × 10⁹ (40M)
SECONDARY_NATIVE_RAW0.4 ETH1.2 BNB9,600 POL0.4 ETH
TICK_SPACING200
POOL_FEE0 — fees taken by the hook