Role: Main developer — owned it end-to-end: the seven Solidity contracts, the Ponder indexer, the Hono API and WS fanout, the auto-graduation keeper, the Next.js frontend, and the Docker/Cloudflare deployment.
End-to-end ownership of a live DeFi launchpad: seven immutable Solidity contracts, a Ponder indexer, a Hono/Bun API with WebSocket fanout, an auto-graduation keeper, a four-page Next.js frontend, and the Docker + Cloudflare deployment.
One interface layer. A Zod-first shared package defines every cross-service type, WS channel, REST DTO, and constant exactly once; contract ABIs are generated at compile time from `forge build` and deploy addresses at deploy time, so no consumer ever hand-writes an ABI or pastes an address.
Verification as infrastructure. Foundry unit, fuzz, invariant, fork, and economic suites; a local `validate.sh` that mirrors CI; a 53-flow E2E catalog enforced by a static coverage gate that demands a 1:1 spec per flow ID; and doc checks that fail the build on broken anchors, drifted canonical copy, or env inventory that no longer matches the `.env.example` files.
Key Features
- pnpm workspace monorepo with Bun as runtime and test runner — contracts, indexer, API, keeper, web, and a shared package
- Zod-first shared package defining every cross-service type, WS channel, REST DTO, and constant exactly once
- Contract ABIs generated at compile time from `forge build`; deploy addresses generated at deploy time — never hand-written
- Foundry unit, fuzz, invariant, fork, and economic test suites behind a `validate.sh` local CI mirror
- 53-flow E2E catalog enforced by a static coverage gate requiring a 1:1 spec per flow ID
- Docker Compose backend behind a Cloudflare Tunnel; Next.js SSR on Cloudflare Workers via OpenNext with R2-backed assets
Tech Stack
Smart Contracts
Indexer & Data
API & Services
Frontend
Infra & Testing
Challenges & Solutions
Making Rug-Pulls Structurally Impossible
Launchpad users have no reason to trust an operator's promise not to freeze withdrawals or drain liquidity, and any pause switch or push-payment fee path is a lever someone can eventually pull against them.
Removed the levers instead of promising not to use them: the only pause switches are on creates and buys — no code path can block a curve sell — and every fee leg accrues in-contract as a pull payment swept by permissionless functions, so a hostile treasury or a reverting creator address can at worst break its own claim. The graduated LP NFT goes into an immutable, ownerless vault whose sole external function is `collect()`, and no pause authority of any kind exists after graduation.
Graduating Into a Pool Someone Can Pre-Seed
Graduation mints liquidity into a Uniswap V3 pool that anyone can create and push to an arbitrary price first, turning the migration into a hostile-ratio mint that hands the attacker most of the raised ETH.
Created and initialized the V3 pool at token creation, at the deterministic graduation price, so there is no unclaimed pool to pre-seed. If the price is polluted anyway, the migrator arbs it back to the target tick from curve inventory within bounds and reverts rather than minting at a hostile ratio — leaving the curve retriable instead of drained. Because the pool starts at the curve's terminal price, the chart also continues as one series with no seam.
Sub-Second UX Without Lying About Finality
An Orbit L2 reflects trades at sequencer speed in about 100ms, but that is not settlement — showing an instant green check would be a finality claim the chain has not made, while waiting for L1 finality would throw away the entire speed advantage.
Made confirmation an explicit three-tier vocabulary — soft-confirmed, posted-to-L1, finalized — tracked by an indexer watermark poller and read-derived at query time from a row's block number, so tiers are monotonic by construction with no per-row write-back. Propagation is O(1): one broadcast per watermark advance upgrades every held event in every client. The UI renders optimistically and makes no finality claim on a fresh trade, and discloses the tier more prominently once a trade crosses 1 ETH.
Anti-Snipe Where Gas Auctions Don't Exist
The chain runs a single first-come-first-served sequencer, so priority fees cannot jump the queue — sniping is a pure latency race, and the usual gas-based mitigations are meaningless. Compounding it, `block.number` returns an L1 estimate on Orbit, so the obvious block-window guard silently misbehaves.
Capped per-transaction buys during an 8-second early window at 2.5% of the graduation target, making a latency win worth only a bounded slice instead of the whole curve, and made the creator's own initial buy atomic with creation so the launcher cannot self-snipe ahead of it. Banned `block.number` in contract logic outright — time-based logic uses `block.timestamp` or `ArbSys.arbBlockNumber()`.