FeeRegistry & Treasury
FeeRegistry
contracts/src/core/FeeRegistry.sol — the single governance surface. Every other contract reads its configuration from here; nothing else has an owner with meaningful power.
Views (read by the token / hook / factory / treasury / bonds)
| Function | Meaning |
|---|---|
reserveAsset() | USDG — the quote asset, reserve denomination, and currency0 of every pool |
poolManager() | The Uniswap V4 PoolManager |
protocolTreasury() | Recipient of the 0.30% base fee + the 10% index-fee cut + launch fees |
protocolToken() | $IPAD — unset (0x0) until the token launches |
launchFeeWei() | Optional native fee per launch |
isAssetAllowed(address) | Stock allow-list membership |
priceFeedOf(address) | Chainlink USD feed for a basket stock (NAV + bond valuation) |
maxBondDiscountBps() | Protocol cap on any index's bond discount (10%) |
minBondPoolLiquidity() | Min pool liquidity before the bond TWAP is trusted (0 = off) |
sequencerFeed() | Optional L2 sequencer-uptime feed for guarded oracle reads |
isPaused() | Guardian pause state |
Governance setters (owner, Ownable2Step)
setAsset / setAssets (allow-list), setPriceFeed (feeds are replace-only — can't be cleared to 0x0), setPoolManager, setProtocolTreasury, setProtocolToken, setLaunchFeeWei, setMaxBondDiscountBps, setSequencerFeed, setMinBondPoolLiquidity, setGuardian.
Pause semantics
setPaused(bool) — callable by owner or guardian. Pausing blocks new launches only. It can never block a swap, an IndexTreasury.redeem(), or a bond claim() — exit paths are unpausable by construction.
The registry still carries a few fields from the removed keeper/dividend era (keeper, challengeWindow, maxEthPerRound, swapEngine, distributionEnabled, ethUsdFeed). They are vestigial in the current inline-split model and are not read by the live fee path. They're slated for removal before mainnet.
Treasury (interim protocol fee sink)
contracts/src/core/Treasury.sol — a plain Ownable2Step vault that receives the protocol's cut: the 0.30% base fee + 10% of every index fee (in USDG, sent by the hook) and native launch fees. It exposes withdraw(token, to, amount), withdrawNative(to, amount), and migrate(successor, tokens[]).
The $IPAD migration path
The protocol token ($IPAD) is not deployed yet — it will be distributed to participants later. The redeemable versions (ProtocolToken.sol, ProtocolTreasury.sol) are kept in-repo, tested, and un-deployed. Because the fee recipient is a mutable registry address, migration needs no core redeploy:
1. Deploy ProtocolToken ($IPAD) + ProtocolTreasury (redeemable)
2. registry.setProtocolTreasury(newTreasury)
3. registry.setProtocolToken(ipad)
4. oldTreasury.migrate(newTreasury, [usdg, ...indexTokens])
From then on, the protocol cut accrues to the $IPAD-redeemable treasury with no interruption to any live index token.