Integration
What a front end or an indexer needs. The protocol page is the mechanism; this is the surface.
:::info Live contracts, closed protocol
The six core contracts are deployed on chain 4663 and frozen. Nothing can be launched on them yet: public launching is off, no stock is listed, the launch router is not yet authorised, and the strategy count is zero.
Addresses below are the production ones, verified read-only on chain on 2026-09-22. Any address not on this page is not Hedgefun — in particular, do not point anything at the sandbox hook, which is a different contract with a similar-looking address.
:::
Network
| Chain | Robinhood Chain |
| Chain ID | 4663 |
| The desk | hedgefun.trade — its own domain, not a subdomain of the app |
| Explorer | robinhoodchain.blockscout.com |
| A launch's own pool | Uniswap V4, on the shared hook, quoted in the stock |
| The treasury's stock leg | Uniswap V3 only, with a 10-minute TWAP corroborating spot |
| Stock oracle | Chainlink, RHxxx / USD ÷ the USDG feed — see the three prices |
| Block time | ~0.1s, which is why every decay here is timed in seconds, not blocks |
The contracts
Production addresses
Deployed from commit 3dc07eb at block 69,454,565 on chain 4663, and verified read-only at block 69,459,976 on
2026-09-22. All six carry a Sourcify creation and runtime match (not exact_match); Blockscout source display
and Uniswap routing approval are separate checks that do not follow from it.
| contract | address |
|---|---|
HedgeFunFactory | 0x58F6Ced8d02cD2567f1458801440Bc4eb67fA961 |
HedgeFunHook | 0x2A16d0973385952cFBE750D37f803d0958472844 |
TradingCalendar | 0xFE9E85f0C258Fc2757eB6Acd1ca032Ec860487F5 |
HedgeFunLaunchRouter | 0x470F5DeB0897118F6575F72183781C6a0610E1FA |
TreasuryDeployer | 0x05BC7875a7d61C3bbA2D7737D40C81aF5fD10DBE |
TokenDeployer | 0x9C0440dCc1b651C4707aa44E0eA083Fa4E0E8A6b |
HedgeFunTradeRouter | 0xb281F7D91325A3A386A00cA0F6010BC8B1491c8C |
owner, protocol and the calendar's owner are all the same Safe:
0x2910117dd2cB431173Ae9Fb6eAF30726321d1693, 3-of-4, with pendingOwner zero.
Listed stocks
Twelve, listed by the owner: NVDA, AMD, MU, INTC (the semiconductor group), SPCX, CRCL, GOOGL, AMZN, GME, META, USAR, MSTR. Each opens around a $10k FDV.
A listing is three things, and you read them from the factory rather than from us — they are the oracle and pool a creator cannot choose:
listings(stock) -> (oracle, pool, openingPrice)
# verified on chain, 2026-09-22
listings(NVDA) -> 0x03c77f527Aa1B0B304602e3fB9Ac994dd1c157f8 # PriceOracle
0xd4EB21209C4D6093f80B5b84f5C45cc093EA14a3 # the V3 pool the stock leg trades
44200000000 # opening price
Public launching is off. publicLaunch reads false and strategyCount reads 0, so a launch form should
say so rather than imply anyone can launch today.
What each contract is for
| contract | what you call it for |
|---|---|
HedgeFunFactory | predict(request) for a quote and its hash, launch(request, terms) to launch, and the listings a creator may pick from |
HedgeFunHook | one instance for every launch, state per pool id. The live tax rates, the split, and the tax events |
HedgeFunToken | the token, plus its page — logo(), description(), socials(), getTokenInfo(), with pons' reader names and selectors, so a tool written for a pons token reads this one unchanged |
HedgeFunTreasury | lots, the reserve, and health() |
HedgeFunLaunchRouter | launch + the creator's first buy + the treasury's first lot, in one transaction |
HedgeFunTradeRouter | USDG ↔ a launch's token in one transaction: the V3 hop, all-or-nothing, then the V4 pool |
PriceOracle, TradingCalendar | the stock's price in USDG, and the 24/5 exchange calendar it consults |
The ABI bundle lives in abi/ in the contracts repo, next to a generated surface listing, and main is current.
Regenerate it against the deployed commit rather than against main if the two have moved apart.
Regenerate it against whatever commit is actually deployed: the take-profit fields widened to uint32 in
09f42b4, which changed the launch, launchWithMetadata and predict selectors, so anything generated before
that is stale.
Launching
A launch takes a request and terms — the hash predict(request) returned, which is the launcher's commitment
to everything they were quoted. If a listing, a default or a fee moved in between, launch reverts rather than
going through at the new one.
| field | what it is |
|---|---|
name, symbol | the token's |
stock | a stock the factory already lists. A creator-supplied address is refused: a creator-supplied oracle is a creator-controlled price |
creator | receives the creator's share of the stock-denominated sell tax, forever. Must be an address that can call vetoCreator — an EOA or a Safe, not a splitter |
taxBps, creatorBps | the tax and the creator's cut of it, both bounded by the factory |
tp1Bps, tp2Bps | the two take-profit levels, uint32 and uncapped — surface what a creator actually set, however large |
dipBps | how far under the last sale the USDG reserve re-buys |
stopBps | optional stop. 0 means no stop, and a lot then never sells below its own cost |
lotBps | the lot size the rule works in |
bandBpsPerHour | the staleness band — see below. Legal range is 0..bandCeiling(stock), which is 0 until the owner sets it, and the contract bounds it again at 200. Frozen into the treasury at birth |
Launch fee, optional, in one of three currencies: the native gas token (straight through, no swap), USDG, or
the same stock being launched against — so a creator holding only NVDA never has to touch USDG. A stray
msg.value on a non-native fee reverts rather than being kept.
launchWithMetadata also writes the token's page in the same transaction. The page belongs to the launching
address, which may appoint one editor and may lock() it for good; the protocol has no power over it.
Quoting a trade
Read the live rate. In a pool's first seconds a buy can pay up to 99%, and a sell can pay a spiked rate after every buy-back:
buy → hook.buyRateBps(poolId) // 99% → 66% → 33% → flat over the first 3 seconds
sell → hook.sellRateBps(poolId) // spiked at launch and after each buy-back, decaying to flat
A quote that shows the flat rate during those windows is wrong by up to 99 percentage points. Show the rate the hook returns, and show that it is decaying.
Other rules that change what you can offer:
- Sells are exact-input only.
- Exact-output is accepted for a buy at the flat rate only, taxed on the stock going in and grossed up so the route costs the same. Anything else is refused.
- The launcher's own buys inside the launch transaction are exempt from the window, with no cap on size or count. If you render a launch's early history, that is worth showing rather than averaging away.
- Show first-buy concentration on every token. How much of the supply the launcher took for themselves in the launch transaction is the single number that separates a launch someone can buy into from one they cannot, and a front end that leaves it out is hiding the thing a buyer most needs.
The staleness band, and how to ask for it
The band does not let a treasury trade at the pool price. It widens how far spot may sit from the last
Chainlink print before health() closes — maxDeviationBps + bandBpsPerHour × feedAgeHours, capped at 3000 —
and the trade still executes against the oracle-derived bound.
Read bandCeiling(stock) and branch, rather than always rendering the field:
- Ceiling 0 — and it is 0 for every stock until the owner sets one — the only legal value is 0. Do not render the field at all: say the treasury follows Chainlink only and sits out closures. A disabled slider only invites "why can't I".
- Ceiling above 0 — a slider from 0 to the ceiling, defaulting to the ceiling. Say plainly that lower is safer and that 0 is a legitimate choice whose only cost is sitting out some closure hours.
Do not sell a wider band as "more trading": availability saturates almost immediately, and what a wider band buys after that is a wider range for a manipulator to pin a closure trade inside. Either way, label it frozen at launch — neither the creator nor the owner can change it afterwards.
Reading a launch
| view | what it tells you |
|---|---|
lotCount() | how many lots the rule is carrying |
reserveUsdg() | the dip-buying reserve |
unbookedStock() | stock that has arrived but is not yet costed — anyone may call book() |
health() | whether the treasury can price and trade right now, and at what price |
Read health() before showing a launch as live. It is false when the feed is stale beyond the band, when the
token's oraclePaused() is set for a corporate action, when the calendar says the market is shut, and when the
pool disagrees with the oracle beyond the execution gate. A treasury that cannot price does not trade, by
construction — while its token keeps trading all week.
Pricing
A launch pool's price is the token in the stock, not in USDG. To show a USDG price or a market cap, multiply by the stock's own oracle price.
price_usdg = price_in_stock × oracle_usdg(stock)
market_cap = price_usdg × (total supply − burned supply)
Two things to read from chain rather than assume:
- Token ordering. Which side of a pool is token0 is not a constant across this chain's stock pools. Assuming one ordering produces a near-zero number with no error, which reads as "no liquidity" rather than as a bug. It has shipped twice.
- The seeded range. The launch position is one-sided, from just above the opening tick to the top of the usable range, so progress along it is computed from the pool's current tick. There is no graduation event to listen for, because nothing migrates.
Events
Event topics and decoding examples are published here with the addresses. The paths worth indexing are the launch
itself, the hook's tax split on each swap, and the treasury's book / takeProfit / stopLoss / buyDip /
buyback steps — together they reconstruct every lot without needing our API.
Support
team@hedgehood.app, or @0xHedgehood.
This is an interface, not investment advice. See the Terms of Use.