Skip to main content

Architecture

What is built, as of 16 Sep 2026. The earlier six-layer sketch planned contracts that were never written; this describes the ones that were. Why each is shaped this way lives in DECISIONS.md.

The map

Solid arrows are calls; dashed arrows are seams — an interface with nothing behind it yet. Everything inside the dotted box is created per launch; everything outside is shared by every launch.

The contracts

ContractRoleInstancesUpgrade pathImports v4
LaunchFactoryLaunches a token and its curve; the registry (launchOf); quote, fee and pool-share configoneUUPS, owned (D2)no
BondingCurveBuy and sell on virtual reserves, fees pushed per trade, graduates inside the crossing buyone per launchbeacon, bound for life to the beacon current at launch (D12)no
LaunchTokenThe ERC20. One extension point: an immutable, gas-capped observerone per launchnoneno
PoolMigratorOpens the pool at launch, seeds it at graduation, holds the liquidity forever, collects and splits its feesone per pool shapereplaced, never upgraded (D16)yes
FeeVaultThe protocol's treasury, per currency; hands fees to a replaceable strategyonenone; the strategy is the seamno
LaunchRouterETH or any token in and out of a launch, along a v3 path, on the curve or in the pooloneUUPS, owned (D22)yes
BasketWrapper, BasketFactoryStocks and baskets as quote assets (src/assets)one per composition; one factorywrapper none; factory UUPSno

src/assets and the core never import each other; the factory reaches baskets only through IQuoteSource (D19, D20). make check-boundaries enforces it, and treats src/router as core.

A launch, end to end

A launch is only ever in one of four states:

  1. Launch. LaunchFactory.launch deploys the token and a curve proxy, and has the migrator open the pool empty at the price the curve will close at — in the same transaction, so nobody can open it first (D16). The migrator records the curve as the only address that may seed it (D24), with the creator's fee wallet and pool share (D25).
  2. On the curve. Every buy and sell pushes the protocol's fee to the vault and the creator's to their wallet; a refused push is held and retryable by anyone (D17).
  3. Graduation. The buy that crosses the threshold locks the curve and calls graduate(), which approves exact amounts and lets the migrator pull them into a full-range position. Short of the gas for that, the buy reverts rather than deferring, so wallet estimates include it (D23).
  4. In the pool. A hookless v4 pool, quotable by aggregators. Anyone can call collectFees, which splits both currencies between the creator's wallet and the vault.

The router sits beside all of this, never in it (D22): every launch stays directly tradable.

The seams

InterfaceWhat can be swapped behind it
IQuoteSourceWhat a launch may be paired against beyond the owner's list — baskets today
IMigratorThe pool a launch graduates into: a new migrator is a new pool shape, for new launches
IFeeSink, IFeeStrategyWhat happens to protocol fees once collected
ITokenObserverWhat watches a token's balances move

Not yet per launch. The hook comes with the migrator, which is chosen per quote asset; the fee sink and the observer are global. Making all three per launch, isolated from each other, is the modular infrastructure effort experiments need (D26).

The local stack

make dev-deploy builds it on a bare anvil, in three steps:

StepWhat it deploys
contracts/dev/uniswap-v3Uniswap v3 from official source, its own Foundry project: WETH9, factory, position manager, SwapRouter02
script/DevMarkets.s.soldUSD and dARB, and full-range v3 pools routing ETH into them
script/Deploy.s.solThe v4 PoolManager from source, the launchpad, the router; WETH, dUSD and dARB registered; fees on

Addresses land in contracts/deploy/31337*.json. make dev-smoke drives the whole path against them.