One launch, one contract
The launchpad is two contract shapes:LunyaLaunchFactory— the singleton you configure once. It creates launches, keeps the registry, and holds the DEX permission used at graduation.LunyaLaunch— one clone per launch (EIP-1167 with immutable args). Each launch holds its own unsold supply and its own raise, and exposes the trading surface. The launched ERC-20 (LaunchToken) is deployed by its launch.
Launch addresses are deterministic and known before creation. Clones deploy via
CREATE2 with a salt namespaced per creator — keccak256(abi.encode(creator, salt)) — so a salt only has to be unique among one creator’s launches, nobody can take an address someone else was going to use, and mining the salt is how a creator picks a vanity address.Predicting an address
predictLaunch returns both addresses: a fresh clone’s first CREATE is at nonce 1, so fixing the launch fixes the token. One caveat, by design: the clone’s immutable args include the factory’s current terms (fees, virtual reserves, graduation settings), so the predicted address is only valid while those terms are unchanged. Read termsHash() beside the prediction and pass it back as expectedTermsHash at creation — the create then fails cleanly instead of deploying to a different address than the one you published.
Discovery
A launch’s state and config
Mutable state on each launch:reserve() (quote raised, in quote units), sold() (tokens sold — not monotonic: sells decrease it), phase(), pool() (after graduation), protocolFees().
config() — a struct with the quote token, creator, curve parameters (virtualQuote, virtualToken, curveSupply, lpSupply), fees (tradeFeeBps, graduationFeeBps, creatorFeeBps), graduationReward, graduationPoolType, and the native-handling fields (nativeDivisor, wrapsNative).
Supply is fixed per launch: total 1,000,000,000 tokens (18 decimals) — 793,100,000 sold on the curve, 206,900,000 reserved for graduation liquidity.
Units
Every amount is in the quote token’s own decimals — reserve, fees, quotes, event fields. On a 6-decimal quote,2e18 is not “two units”. The only exception is sellForNative, whose minimum-out is denominated in the native coin.
Launch types and versioning
LaunchType is a uint8 naming an implementation in an append-only registry: a corrected implementation is the next type number, and old types can be retired (existing launches keep trading; only creation is blocked). Over time, launches of different types coexist under one factory, all emitting the same LaunchCreated — treat a launch’s ABI as a function of its launchType, and read it from the creation log.