A fair-launch launchpad on Solana where every token runs under a post-quantum signature scheme (WOTS) and every ticker is decided by an open race, not an allocation.
QPL Factory is a launchpad for memecoins on Solana where every token is protected by post-quantum signatures and every launch is a race, not a presale. There is no allocation, no reserved supply for the team, and no upgrade authority. The program is immutable once deployed.
Anyone can submit a candidate under a ticker. Users pick a winner by minting into the candidate they like. The first token to reach the race target wins the ticker forever, graduates to an on-chain AMM, and all other candidates refund their minters automatically.
A ticker is a short symbol (up to 8 characters) like $PEPE. Multiple wallets can each submit a candidate token under the same ticker. Each candidate has its own mint pool and its own holders. They are racing head-to-head for the ticker.
Whoever reaches 50 SOL raised first wins the ticker. At that moment, the winning candidate graduates:
Race state is visible in the scanner: New Race is any ticker with open candidates, Near To Win flags the ones above 80% progress, and Winners shows graduated tokens live on the AMM.
Every holder-facing operation in QPL Factory is signed with WOTS(Winternitz One-Time Signatures), a hash-based signature scheme that does not rely on elliptic-curve crypto. Shor's algorithm does not break it. A cryptographically relevant quantum computer cannot forge a WOTS signature the way it could forge an Ed25519 one.
Every token position is protected by its own chain of WOTS keys. Every signed operation reveals the current key, and simultaneously commits to the hash of the next key in the chain. Re-using a key is cryptographically impossible. The chain only moves forward.
key_index.key_index from the token master secret.hash(key #key_index+1) on-chain as the next expected hash.key_index by one. Replay is impossible.QPL Factory supports two signer modes. You can use the built-in local wallet (a 24-word seed stored in your browser), or you can connect an external Phantom wallet. Both paths feed the same WOTS signing layer, so the quantum-resistant guarantees are identical.
signMessage challenge, so no seed is exported and no extra backup is needed. Same master on every device that connects the same Phantom.Local wallet Phantom connect
──────────── ───────────────
24-word seed (BIP44) Phantom signs gas txs
├── ed25519 keypair → gas sha256(signMessage challenge)
└── WOTS master └── WOTS master
└── per-token master └── per-token master
= HKDF(master, tokenPda) = HKDF(master, tokenPda)
└── WOTS key #0, #1, … └── WOTS key #0, #1, …The local seed is stored encrypted in your browser and never touches any server. Phantom connect derives the WOTS master from a fixed challenge, so re-connecting on another device yields the same QPL positions without any import step.
During the race phase, the only way to acquire a candidate is to mint. Minting is a fixed-price operation: you send SOL, you receive tokens at a known rate. The rate is the same for everyone, from the first mint to the one that triggers the graduation.
To keep race sprints fair, the program enforces a per-slot mint cooldown and rejects mints once supply is exhausted. You can also withdraw (undo a mint) while the candidate is still racing. Useful if you change your mind before graduation.
When a candidate crosses the race target, graduation is atomic: the ticker is locked, the winner's race pool is split between a bonding-curve AMM and a two-bucket launch reserve, and the token transitions to the WINNER state in a single instruction.
At graduation the program also snapshots the graduation price as par and seeds the EMA at the same value. The reserved tokens stay inside the token PDA as a separate bucket (they are not burned at graduation), ready to be consumed by the BURN and ADD_LP crank actions over time.
The trading pool is a Uniswap-v2-style x * y = k constant-product market. Every trade pays a fee split three ways (see §9): part stays in the curve (benefits every holder as an implicit LP), part is routed to the protocol treasury, and a third slice is siphoned into the launch reserve so the tri-crank keeps firing forever. No single trade can drain more than 99% of either reserve.
solReserve / tokenReserve, what the next 1-token trade pays.The launch reserve is not a team allocation. It is a programmatic flywheel that any wallet can turn. Three separate permissionless instructions drain the reserve over time and feed value back into the AMM. Each crank call pays a tiny tip to whoever submitted the transaction, so the three actions compete for attention on their own economic incentives with zero off-chain automation required.
The program stores three per-action anchors on the token PDA: last_buy_slot, last_burn_slot, last_addlp_slot. Any crank is rate-limited by a global cooldown measured against the max of all three, so you cannot spam the flywheel by alternating actions.
Each action reads its own anchor for drain sizing, so a burst of BUY cranks leaves the BURN and ADD_LP vesting windows untouched. The next BURN fired after that streak still drains a fully-matured slice. This asymmetry rewards crankers who pick the under-used action.
Once a race graduates, every losing candidate enters the REFUNDING state. The losing pools are not confiscated, burned, or redistributed: they are held in their original PDA and redeemable pro-rata by the original minters.
/refund/ALL or open the scanner.Fees exist to fund the protocol treasury, keep the pool safe from zero-value spam, and feed the tri-crank flywheel. All fees are visible on-chain and enforced by the program. They cannot be raised, waived, or redirected after deploy.
(ticker, creator), so sybil-stacking a race with duplicates is physically impossible.key_index. A replayed transaction references an old key and is rejected on signature verify.launch_reserve. As long as the token has volume, the reserve keeps accruing, so the flywheel keeps firing. Volume dies, the flywheel naturally slows down. Nothing extra to maintain.claim_refund. No SOL is burned, no SOL is redirected.