Core Contracts & Roles
Each PURITY launch deploys a fixed set of contracts with strictly separated responsibilities. A third-party launch deploys six: Token, Treasury, TeamDistribution, SupporterDistribution, SupporterVault, and GovernanceModule. $PURE itself deploys a seventh — the EcosystemReceiver, a singleton that every subsequent third-party launch points at.
The separation is deliberate. The Treasury does one job — market-making — and holds only market-making capital. Team compensation lives in its own contract with its own vesting clock. Supporter payouts live in their own contract with their own pro-rata ledger. Nothing overlaps, so nothing can be quietly repurposed.
1. Treasury
The Treasury is the market-making core of a launch: it creates and owns the canonical AMM pool, receives the entire token supply at deployment, and executes all buy-side and sell-side logic. It is the only contract in the system that trades.
On every liquidation, the Treasury splits the proceeds and immediately forwards the team and supporter buckets to their distribution contracts, keeping only the market-making share. It carries no team accounting, no supporter accounting, and no ecosystem accounting — those live where the money lives. What the Treasury does hold, beyond its market-making WETH, is the token-holder claim pool after a shutdown, from which holders are paid.
The Treasury also runs the launch itself. launch() seeds the pool from the Treasury's own minted token balance and the supporter vault's committed capital, in one atomic transaction, callable only by the launch's designated team address. The mechanics are covered in Launch & Initialization.
Market-making execution is pull-based and permissionless: anyone may call accumulate() or liquidate(), and nothing happens unless the coded conditions hold at that moment. In practice an off-chain keeper drives liquidate() on the sampling cadence; keeping that keeper alive is a team responsibility. The system remains correct without it — no wrong action becomes possible — but selling opportunities during keeper gaps are simply not recovered.
What the Treasury cannot do is as important as what it can:
- no discretionary trading — every trade is condition-gated and parameter-bounded,
- no arbitrary withdrawals — value leaves only via the distribution split, a passed governance release, or shutdown claims,
- no external price oracles and no off-chain dependencies,
- no participation in governance — it executes a passed release when the GovernanceModule instructs it, never the reverse.
The Treasury also exposes read-only views of its own price math — the live floor and the liquidation band (getFloor(), getPLiqStart(), getPLiqMax()) — so anyone monitoring a launch reads the anchors from the contract's own arithmetic rather than re-deriving formulas off-chain.
2. Token
The token contract is intentionally minimal: a fixed-supply ERC-20 with the ERC20Votes extension and nothing else. The full supply is minted to the Treasury at construction. There is no minting afterward, no transfer taxes, no hooks, no rebasing, no pause switch.
Burning exists in exactly one gated form: the Treasury may burn tokens it holds (burnFromTreasury). This is used at shutdown — the Treasury burns its remaining inventory, and token holders burn their tokens to claim their share of the shutdown pool. There is no public burn path.
Two behaviours are worth understanding:
The launch whitelist. While the whitelist is active, tokens can only move to the Treasury, the canonical pair, or the burn address — which is what keeps the full supply contained during the launch transaction itself. The Treasury lifts the whitelist (liftWhitelist()) at the end of launch(), immediately after its initial accumulation completes. Lifting is irreversible, and after it the token contract contains no privileged actors of any kind.
Auto-delegation. ERC20Votes normally requires holders to delegate their own voting power before they can vote — a step most holders never take. This token does it automatically: on first receipt of tokens, a holder is self-delegated. An address that has already chosen a delegate is left alone, and the Treasury and pair addresses are excluded (their balances should not count as votable supply).
PurityToken itself is $PURE-specific, with name and symbol hardcoded. Third-party launches use PurityTokenTemplate, a parameterised twin that takes name, symbol, and supply as constructor inputs and is otherwise behaviourally identical — a launching team gets its own token identity but no lever over the economics.
3. TeamDistribution
TeamDistribution holds the team-compensation bucket and enforces the mandatory six-month linear vesting. It is funded by deposits from its Treasury (each liquidation's team share) — and, on $PURE's instance only, by the EcosystemReceiver as a second authorised depositor. Each deposit becomes a vesting tranche; the team claims vested value whenever it likes, pull-based, paid out as native ETH.
At shutdown the contract resolves in one of two ways, on the Treasury's instruction: in a No-Traction shutdown, vesting accelerates and the full balance becomes claimable (the team still pulls — nothing is pushed to any wallet); in an Abandonment shutdown, the entire remaining balance is clawed back to the Treasury and the team forfeits everything unvested and unclaimed. Details in Team ETH Vesting.
4. SupporterDistribution
SupporterDistribution holds the supporter bucket and pays each supporter their strictly pro-rata share, using the SupporterVault's immutable contribution record as the basis. It is funded only by its Treasury. Claims are permissionless to trigger — anyone can execute a claim for a supporter — but the funds always go to the supporter's own address. The same single claim path operates identically before and after shutdown; there is no separate mechanism to switch between. Details in Supporter Distributions.
5. SupporterVault
The SupporterVault collects base-asset contributions before launch, under caps fixed at deployment and an optional admin-managed whitelist. It is not a presale: contributors receive no tokens, no governance rights, and no ownership. Base asset held by the vault can move to exactly two places — back to the original contributor (refund, open any time before launch) or into the Treasury at launch.
For $PURE the vault is not merely a record: it funds the launch. Finalization is callable only by the Treasury, only from inside launch(), and only if the vault holds at least its committed minimum — so there is no such thing as supporter funds committed to a launch that never happens. If the team never launches, refunds stay open indefinitely.
After launch the vault becomes a pure, read-only contribution record — the pro-rata basis SupporterDistribution reads forever after. It tracks no claims and executes nothing. The vault has its own page: The Supporter Vault.
6. GovernanceModule
The GovernanceModule manages token-holder voting. The relationship with the Treasury is strictly one-directional — governance calls the Treasury to execute a passed decision; the Treasury never calls governance — and its scope is deliberately narrow. It is not a general-purpose DAO. It handles exactly two proposal types:
Treasury release. The launch's designated team address — and only that address — may propose releasing capital from the Treasury to a stated destination. Token holders vote. Releases are hard-capped in code: at most 20% of the Treasury's live market-making WETH per proposal for ETH, and at most 2% of total token supply for tokens. See Governed Treasury Release.
Shutdown authorisation. Any holder of at least 0.05% of supply may propose winding the launch down. A passed vote does not itself shut anything down — it authorises the arbitrator to execute shutdown() within a seven-day window. If the window lapses unused, the authorisation expires.
Both proposal types share the same machinery: a 7-day voting window, vote weight from an ERC20Votes snapshot taken at submission, quorum of 50% of external supply (total supply minus the Treasury's and the pool's holdings — tokens that cannot vote should not inflate the denominator), simple-majority approval, and a 7-day cooldown between proposals. The pool's balance for the quorum calculation is captured at submission time, not read live at execution, closing a window in which the denominator could otherwise be manipulated after voting ends.
The arbitrator holds one narrow power here: it may cancel an active proposal, but only during its open voting window — a visible, one-way safety valve that can stop a vote from completing but can never pass one.
GovernanceModule presence is what converts the arbitrator's shutdown power from unilateral to holder-gated. The Treasury's governanceModule reference is immutable: if it is set, shutdown requires a passed vote; if a launch were deployed without one (address(0)), the arbitrator would retain unilateral shutdown — which is why factory-deployed launches always include governance.
7. EcosystemReceiver ($PURE only)
The EcosystemReceiver is a singleton deployed once, as part of $PURE's genesis. Every third-party launch routes its fixed 500 bps ecosystem share here — as a plain WETH transfer, which runs no code on the receiver and therefore can never fail because of the receiver. The receiver's WETH balance is the pending amount; there is no counter to drift.
Anyone may call processEcosystem() at any time. It splits the accumulated balance on a fixed, immutable 50/50: half to the $PURE Treasury as ordinary market-making capital, half into $PURE's TeamDistribution, where it vests on the normal six-month schedule. There is no supporter leg and no configurability — the split is baked into the contract. The odd wei, when the balance is odd, goes to the team leg so nothing is ever stranded.
The Launchpad Arbitrator
Across every launch, one predefined role exists for resolving end-of-life events: the arbitrator. The role is held by the PURITY core team through a multisig — the same body for every launch, wired in at deployment, never chosen by a launching team.
This is an honest centralisation, and its scope is tightly drawn. With governance present — as it is on all factory launches — the arbitrator cannot shut a launch down on its own initiative. The sequence is always: holders propose, holders vote, the vote passes, and only then may the arbitrator execute the shutdown, within seven days, choosing between the two predefined modes (No-Traction or Abandonment) with published reasoning. Its other powers are similarly narrow: cancelling a proposal during its open voting window, sweeping unclaimed funds after the one-year post-shutdown claim window (third-party launches only — $PURE has no sweep anywhere), and a two-step transfer of the arbitrator role itself, which is the eventual exit path toward a DAO or independent body.
The arbitrator cannot trade, cannot withdraw funds, cannot modify parameters, and cannot touch a live launch's operation in any way.
For third-party launches this structure is a feature: the arbitrator is independent of the launching team, so a team cannot use shutdown powers against its own holders, and holders retain a functioning exit that the team cannot veto. For $PURE itself there is a real, acknowledged conflict — the team is the arbitrator — covered honestly in Risk & Limitations.