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.

Indexer. Ponder over the on-chain event families → Postgres with `pg_trgm`, the single source of derived truth: venue-continuous candles across six intervals, `Transfer`-sourced holder balances, confirmation-state watermarks, metadata-hash verification, and creator-fee accrual — one Redis publish per handler and zero hot-path reads.

API + WS. Hono on Bun as two processes — HTTP (25+ read endpoints over indexer tables, `pg_trgm` search, API-mediated R2 uploads, server-side metadata canonicalization, moderation gating, SIWE admin, per-token OG rendering via satori + resvg) and a Bun WebSocket fanout relaying Redis to sockets. The API never writes to the chain.

Keeper. A small Bun + viem service that makes graduation automatic — a topic-filtered `eth_subscribe` on `GraduationReady` fires the permissionless `graduate()` within ~1–2 blocks, with a Postgres sweep as the fallback for WS drops, an on-chain `phase()` re-read before every send for idempotency, and a cooldown that stops persistent-revert hot-loops. It holds no privileged role and adds zero new authority.

Key Features

  • Ponder indexer over the on-chain event families → Postgres + `pg_trgm`, one Redis publish per handler, zero hot-path reads
  • Venue-continuous candles across six intervals (1s/15s/1m/5m/15m/1h) that stay a single series across graduation
  • Three-tier confirmation state (soft-confirmed → posted-to-L1 → finalized) read-derived from watermarks, so propagation is O(1) per advance
  • Hono on Bun in two processes — HTTP read API and a Bun WebSocket fanout relaying Redis to sockets; no chain writes, ever
  • Content-addressed R2 uploads with server-side metadata canonicalization the client re-verifies before signing
  • Auto-graduation keeper on a topic-filtered `eth_subscribe` with a Postgres sweep fallback, idempotent `phase()` re-reads, and revert cooldowns

Tech Stack

Indexer & Data

PonderPostgreSQLpg_trgmRedisTypeScript

API & Services

HonoBunWebSocketsviemZod

Smart Contracts

SolidityFoundryOpenZeppelin v5Uniswap V3Arbitrum Orbit

Infra & Testing

Docker ComposeCloudflare WorkersOpenNextCloudflare R2Playwrightpnpm

Frontend

Next.js 16React 19wagmi v2RainbowKitlightweight-chartsTailwind CSS

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.

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.

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

Key Achievements

25+ Endpoints
Hono-on-Bun REST surface over indexer tables
6 Intervals
Venue-continuous candles from 1s to 1h
3 Tiers
Read-derived confirmation state, O(1) propagation
~1–2 Blocks
Keeper latency firing permissionless graduation
ROBBED_ - Project | Oleksandr Yusypenko