HartiiLabs docs

HartiiLabs

Contract map

Everything an indexer needs to pick up every token launched on hartiilabs.com, on one page. New launches now go through a fourth-generation factory (V4, live 2026-10-02), so index all three factories. Every address below returned bytecode from quai_getCode and every event topic was matched against real logs on Quai mainnet (chain 9, Cyprus-1) at block 10366996 (2026-09-30); the V4 addresses were confirmed at block 10407813 (2026-10-02).

1. Index these three factories

All three factories emit the same TokenLaunched event, so one handler covers them all. V1 and V3 still accept launches — keep indexing them.

FactoryAddressIndex from blockStatus
TokenFactoryV4 (LP Reserve)0x005566187B52313e03978C2caF4BE1a0A88eb90A10407724Live since 2026-10-02 — every new launch from hartiilabs.com
TokenFactoryV30x00249722868732Ee678b88Db668EAf7cC75Ae12A10356575Live — hartiilabs.com's default from 2026-09-29 to 2026-10-02; its tokens trade on unchanged
TokenFactory (V1)0x001AF1BbB40807fcb99C9Eeaa49dF5E91e7Efd428872950Live — the original factory

2. Events

topic0 is keccak256 of the signature.

EventEmitted bytopic0
TokenLaunched(address indexed token, address indexed curve, address indexed creator, string name, string symbol, bytes32 metadataHash)V1, V3 and V4 factory0x57e2b1dd3b3baad37496efb283e2935bc1cfedc331530404a4530514e5e71356
LaunchConfigured(address indexed token, uint256 vestingDurationSecs, uint256 lockStartDelaySecs, uint256 creatorFeeShareBps, uint256 treasuryFeeShareBps, uint256 snipeWindowBlocks, bool autoBuyback)V3 and V4 factory0x87811f92b40333fcc295e685f06b34bc066187e283798479a0ab372528df5b2a
Buy(address indexed buyer, uint256 quaiIn, uint256 tokensOut, uint256 fee)each token's curve0xbeae048c6d270d9469f86cf6e8fedda3c60ad770f16c24c9fc131c8e9a09101d
Sell(address indexed seller, uint256 tokensIn, uint256 quaiOut, uint256 fee)each token's curve0x846c37eef631e0943682d87352ec117c20008eb7f425c9b85ac011a6d4774cc0
Graduated(address indexed token, uint256 quaiReserve, uint256 tokenReserve)each token's curve0x1c858049e704460ab9455025be4078f9e746e3fd426a56040d06389edb8197db
LiquidityAdded(address indexed provider, uint256 quaiIn, uint256 tokensIn, uint256 shares)V3 curves after graduation0x64b83944e79c3ce8d4c297411de637c3e102d064677aac0c163976ebdcd6f50e
LiquidityRemoved(address indexed provider, uint256 quaiOut, uint256 tokensOut, uint256 shares)V3 curves after graduation0x1dc8bb69df2b8e91fbdcbfcf93d951b3f0000f085a95fe3f7946d6161439245d

3. How a token trades

  1. Launch. The factory emits TokenLaunched. token is a plain ERC-20 with 18 decimals; curve is where it trades. Both are EIP-1167 clones of the implementations in section 5.
  2. Bonding curve. Buys and sells hit the curve and emit Buy / Sell. The curve holds the QUAI reserve.
  3. Graduation. Graduated fires when the curve fills. The same curve contract then becomes the token's pool: Buy / Sell keep firing from the same address, so there is no new venue to discover. V3 curves also take LP deposits after graduation (LiquidityAdded / LiquidityRemoved).
  4. Optional HartiiSwap pair. Some tokens also have a Uniswap-V2-style pair on HartiiSwap (section 4). Resolve it with factory.getPair(token, WQUAI) — pairs are CREATE-deployed, so there is no init-code hash to compute.

4. HartiiSwap

A Uniswap V2 port, live since 2026-09-23. Pairs emit the standard V2 Mint, Burn, Swap and Sync events; the factory emits PairCreated. More in HartiiSwap.

5. Implementations

For source verification — every launch clones these.

6. Other live HartiiLabs contracts

Not needed for token indexing.

ContractAddressFrom blockStatus
LpLocker (time-locks LP, max 90 days)0x00276419b3aa2E7d034D2d54d52b59BdfFF4e60E10341499Live
AgentVaultFactory0x006C2be96D6Ca90d0105a2Bfa7aC2187f40e899d10341473Live — see Agent Terminal
HartiiProfiles0x0015f71de1574c772B6815D25B233C065f42c89610341682Live
LpArena v20x00614295C6AC13d3B7d93844b9BacC61a768082010351500Live
LpArena v10x0075B00Ca0313f88b0825BE62bBFB890c9F4C03F10341703Deprecated — unstake only
MiningVaultFactory v20x0024596369Fc22A22b720B0A959630913d8D680b10342308Live
MiningVaultFactory v10x0059f740fb9AD9F2Db19DA5Dac3b71bF6BD6B68c10341712Abandoned — never used, do not integrate
AchievementRewards0x001d607B22de6ACcFB4adEE62838DED222Aa0c8a10352297Live
QuaiRelay0x0031B09e63592B713768761cdDACC603974c10bD—Live — see QuaiRelay

7. LP Reserve (TokenFactoryV4 / BondingCurveV4) — live on mainnet

Every V4 launch reserves 3% of its supply (lpReserveBps = 300, read live from TokenFactoryV4.lpReserveBps()) as a protocol-owned bucket, carved off before the creator / curve / migration split. Nothing happens to it before graduation. When the token graduates, the whole reserve streams to real liquidity providers in proportion to their LP shares, linearly over 56 days (lpReserveStreamSeconds = 4838400). Rewards are paid in the launched token. LPs can claim them at any time with no expiry, and claiming never locks LP funds. V4 also works out virtualTokenReserve per launch, so the pool opens at exactly the curve's last price whatever the creator allocation is. Owner setters only change these numbers for future launches. A live curve keeps the values it launched with. Design rationale: docs/design/lp-reserve-2026-09-30.md in the hartii-labs repo.

ContractAddressNotes
TokenFactoryV40x005566187B52313e03978C2caF4BE1a0A88eb90ADeployed block 10407724. Creation fee 5 QUAI, graduation 25,000 QUAI net raised.
LaunchToken implementation (V4)0x007a8Fc000eB5D353b1f3c5C7019efeAAa3d5D03Same bytecode as LaunchTokenV3.
BondingCurveV4 implementation0x0049Ba9169F36a18b4a190AE057Ad69Ef8eDf75eClone target for V4 curves. Buy / sell / LP ABI unchanged from V3; sells need an ERC-20 approve to the curve first.

V4-only events (in addition to every V3 event, which is unchanged):

EventEmitted bytopic0
LpReserveConfigured(address indexed token, uint256 lpReserveTokens, uint256 lpReserveStreamSeconds)V4 factory, at launch0x112337f0e3b9bacb1cfaed29b8f0dc4e971d82b2c0a30d2cc9e80e2e941755c5
LpReserveStreamStarted(uint256 rewardRate, uint256 periodFinish, uint256 lpReserveTotal)V4 curve, at graduation0xbd0a41a511264ef937cf1a0914883798b1c0984bd6920ac3eb72e61cba4ce9b9
LpReserveRewardClaimed(address indexed account, uint256 amount)V4 curve0xbe9bfd96b705f3a9977d024b0db3388eeb5d13881c48615f09ab395d5a275cd7
LpReserveOrphanedSwept(uint256 amount)V4 curve0x92c2bc4c57c9d8c40362fd46277a2035dc8777ea6a8e543fb97cf329d4dd0d43

Read functions on a V4 curve: lpReserveTotal(), lpReserveRemaining(), rewardRate(), rewardPeriodFinish(), earnedLpReserve(address). Write: claimLpReserveRewards(). sweepOrphanedLpReserve() is permissionless. It burns only the reserve that accrued while there were zero real LPs, which nobody can ever claim, and it never touches an accrued claim.

8. Shortcuts

  • If you'd rather not scan logs: GET https://hartiilabs.com/api/tokens lists every indexed token, and GET https://hartiilabs.com/api/token/<address> returns one token with its curve address. See the API reference and how the indexer works.
  • When scanning yourself: Quai's quai_getLogs rejects ranges over 10,000 blocks, so page through in windows of 10,000 blocks or fewer.
Quai Network mainnet · chain 9 · Cyprus-1. Figures marked "read on" a date were read from the chain that day; re-read before relying on them.