Back to Projects

ROBBED_

Memecoin Launchpad on an Arbitrum Orbit L2

Overview

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.

Next.js 16 + React 19 App Router on Bun, deliberately scoped to four pages — Discover, Token Detail, Create, and Portfolio. wagmi v2 + viem + RainbowKit for wallet and chain access, TanStack Query patched by a single multiplexed WebSocket instead of polling, and `lightweight-charts` rendering one venue-continuous series that crosses graduation without a visual seam. The trade lifecycle renders optimistically at tx-send and reconciles to indexed truth by transaction hash — values are replaced, never dropped — and the UI makes no finality claim on a fresh trade, escalating confirmation tiers only as the L1 watermarks advance.

Key Features

  • Next.js 16 + React 19 App Router on Bun, scoped to four pages: Discover, Token Detail, Create, Portfolio
  • wagmi v2 + viem + RainbowKit wallet integration against chain 4663, including mobile wallet connect
  • TanStack Query patched by one multiplexed WebSocket — no polling layer anywhere between chain and browser
  • `lightweight-charts` price series that crosses curve → Uniswap V3 as one continuous chart with no economic or visual seam
  • Optimistic trade lifecycle reconciled to indexed truth by tx hash, with confirmation tiers escalated for trades ≥1 ETH
  • Top Holders table and on-chain metadata commitment surfaced as first-class anti-rug transparency

Tech Stack

Frontend

Next.js 16React 19wagmi v2RainbowKitlightweight-chartsTailwind CSS

API & Services

HonoBunWebSocketsviemZod

Smart Contracts

SolidityFoundryOpenZeppelin v5Uniswap V3Arbitrum Orbit

Infra & Testing

Docker ComposeCloudflare WorkersOpenNextCloudflare R2Playwrightpnpm

Indexer & Data

PonderPostgreSQLpg_trgmRedisTypeScript

Challenges & Solutions

Sub-Second UX Without Lying About Finality

Problem

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.

Solution

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.

Graduating Into a Pool Someone Can Pre-Seed

Problem

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.

Solution

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.

Anti-Snipe Where Gas Auctions Don't Exist

Problem

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.

Solution

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()`.

Making Rug-Pulls Structurally Impossible

Problem

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.

Solution

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.

Key Achievements

4 Pages
Discover, Token Detail, Create, Portfolio — nothing else
1 WebSocket
Multiplexed stream replacing every polling layer
1 Chart Series
Curve → Uniswap V3 with no economic or visual seam
Next.js 16
React 19 App Router on Bun, SSR on Cloudflare Workers
ROBBED_ - Project | Oleksandr Yusypenko