From 6ef8fc8f8111c7938164bb271b5d4fa24369fc5a Mon Sep 17 00:00:00 2001 From: Kevin Codex Date: Mon, 7 Sep 2026 13:10:35 +0800 Subject: [PATCH 1/4] links: point the site at github.com/Gitlawb/openlaunch (footer, hero pill, rules, llms.txt); drop 'code release pending' --- app/src/app/layout.tsx | 5 ++++- app/src/app/llms.txt/route.ts | 2 +- app/src/app/rules/page.tsx | 5 ++++- app/src/components/launchpad/LaunchHero.tsx | 5 +++-- app/src/lib/brand.ts | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/app/layout.tsx b/app/src/app/layout.tsx index 83e0eea1..77bd3e85 100644 --- a/app/src/app/layout.tsx +++ b/app/src/app/layout.tsx @@ -9,7 +9,7 @@ import { getLaunchFeed, getLaunchTotals } from "@/lib/launchpad/queries"; import { ethUsd } from "@/lib/launchpad/ethPrice"; import { SITE_URL, explorerAddress } from "@/lib/chainPublic"; import { launchpad } from "@/lib/launchpad/config"; -import { BRAND, BRAND_DOMAIN, BRAND_TLD, BRAND_X, SITE_DESCRIPTION, SITE_TITLE, SOCIAL_DESCRIPTION } from "@/lib/brand"; +import { BRAND, BRAND_DOMAIN, BRAND_GITHUB, BRAND_TLD, BRAND_X, SITE_DESCRIPTION, SITE_TITLE, SOCIAL_DESCRIPTION } from "@/lib/brand"; import Mark from "@/components/launchpad/Mark"; import RouteProgress from "@/components/RouteProgress"; import { Suspense } from "react"; @@ -59,6 +59,9 @@ export default async function RootLayout({ children }: { children: React.ReactNo how it works agents llms.txt + + source · GitHub ↗ + {b.factory ? ( factory · Base ↗ diff --git a/app/src/app/llms.txt/route.ts b/app/src/app/llms.txt/route.ts index 042d0533..22988df9 100644 --- a/app/src/app/llms.txt/route.ts +++ b/app/src/app/llms.txt/route.ts @@ -9,7 +9,7 @@ export function GET() { const r = launchpad("robinhood"); const body = `# ${BRAND_DOMAIN} -> Open-source (contracts verified on Sourcify; code release pending), zero-fee token launchpad on Base (8453) and Robinhood Chain (4663). One transaction deploys a token and locks 100% of its supply as +> Open-source (MIT — https://github.com/Gitlawb/openlaunch; contracts verified on Basescan, Blockscout and Sourcify), zero-fee token launchpad on Base (8453) and Robinhood Chain (4663). One transaction deploys a token and locks 100% of its supply as > Uniswap v4 liquidity, forever. No platform fee: the factory and locker have no fee address at all. ## What a launch does diff --git a/app/src/app/rules/page.tsx b/app/src/app/rules/page.tsx index e39d1a02..d331519b 100644 --- a/app/src/app/rules/page.tsx +++ b/app/src/app/rules/page.tsx @@ -3,6 +3,7 @@ import Link from "next/link"; import { btn, cardPad } from "@/components/ui"; import { launchpad } from "@/lib/launchpad/config"; import { CHAIN_KEYS, CHAIN_LABELS, explorerAddress } from "@/lib/chainPublic"; +import { BRAND_GITHUB } from "@/lib/brand"; export const metadata: Metadata = { title: "How it works", description: "What a launch does on-chain, what it costs (gas), and what can never happen to your liquidity." }; @@ -111,7 +112,9 @@ export default function RulesPage() { ); })} -

Identical bytecode on both chains. Uniswap v4's PoolManager, PositionManager, Permit2 and Universal Router are Uniswap's canonical deployments. MIT-licensed source, verified on Sourcify.

+

Identical bytecode on both chains. Uniswap v4's PoolManager, PositionManager, Permit2 and Universal Router are Uniswap's canonical deployments. MIT-licensed source on{" "} + GitHub ↗, verified on Basescan, Blockscout and Sourcify on both chains. +

diff --git a/app/src/components/launchpad/LaunchHero.tsx b/app/src/components/launchpad/LaunchHero.tsx index dd3e57d0..7c7b8795 100644 --- a/app/src/components/launchpad/LaunchHero.tsx +++ b/app/src/components/launchpad/LaunchHero.tsx @@ -3,6 +3,7 @@ import { btn, pill } from "@/components/ui"; import LiveTotals from "./LiveTotals"; import { launchpad } from "@/lib/launchpad/config"; import { explorerAddress } from "@/lib/chainPublic"; +import { BRAND_GITHUB } from "@/lib/brand"; export default function LaunchHero({ configured }: { ethUsd?: number | null; configured: boolean }) { const b = launchpad("base"); @@ -11,8 +12,8 @@ export default function LaunchHero({ configured }: { ethUsd?: number | null; con
0% platform fee - - open source · verified contracts + + open source · verified contracts ↗ Base + Robinhood Chain · Uniswap v4 liquidity locked forever diff --git a/app/src/lib/brand.ts b/app/src/lib/brand.ts index af4aa7fa..3900bb4c 100644 --- a/app/src/lib/brand.ts +++ b/app/src/lib/brand.ts @@ -4,7 +4,7 @@ export const BRAND_TLD = ".lol"; export const BRAND_DOMAIN = `${BRAND}${BRAND_TLD}`; // openlaunch.lol /** @openlaunchlol and the openlaunchlol GitHub org were squatted after the rename — never link them. */ export const BRAND_X = "gitlawb"; -export const BRAND_GITHUB = "https://github.com/Gitlawb"; +export const BRAND_GITHUB = "https://github.com/Gitlawb/openlaunch"; // MIT, contracts + site export const TAGLINE = "launch a token. Free. Open source. On Base or Robinhood Chain."; /** * Per-surface copy (each surface truncates at a different point): From b117662d765b53680c3e8e9cc9772d488c0c313a Mon Sep 17 00:00:00 2001 From: Kevin Codex Date: Mon, 7 Sep 2026 13:35:59 +0800 Subject: [PATCH 2/4] review: per-chain verification copy with record links (Basescan is Base-only); badge label matches its destination --- app/src/app/llms.txt/route.ts | 6 ++++- app/src/app/rules/page.tsx | 27 ++++++++++++++++++++- app/src/components/launchpad/LaunchHero.tsx | 5 +++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/app/src/app/llms.txt/route.ts b/app/src/app/llms.txt/route.ts index 22988df9..5507ea1f 100644 --- a/app/src/app/llms.txt/route.ts +++ b/app/src/app/llms.txt/route.ts @@ -9,9 +9,13 @@ export function GET() { const r = launchpad("robinhood"); const body = `# ${BRAND_DOMAIN} -> Open-source (MIT — https://github.com/Gitlawb/openlaunch; contracts verified on Basescan, Blockscout and Sourcify), zero-fee token launchpad on Base (8453) and Robinhood Chain (4663). One transaction deploys a token and locks 100% of its supply as +> Open-source (MIT — https://github.com/Gitlawb/openlaunch), zero-fee token launchpad on Base (8453) and Robinhood Chain (4663). One transaction deploys a token and locks 100% of its supply as > Uniswap v4 liquidity, forever. No platform fee: the factory and locker have no fee address at all. +## Source verification +- Base (8453): Basescan https://basescan.org/address/${b.factory}#code (factory), https://basescan.org/address/${b.locker}#code (locker); Blockscout https://base.blockscout.com/address/${b.factory}?tab=contract; Sourcify https://repo.sourcify.dev/8453/${b.factory} +- Robinhood Chain (4663): Blockscout https://robinhoodchain.blockscout.com/address/${r.factory}?tab=contract (factory), https://robinhoodchain.blockscout.com/address/${r.locker}?tab=contract (locker); Sourcify https://repo.sourcify.dev/4663/${r.factory} + ## What a launch does 1. deploys a fixed-supply ERC-20 (1,000,000,000; no mint/pause/blacklist/tax/owner) 2. initializes a Uniswap v4 pool quote/token (quote = ETH, or USDG on Robinhood Chain; tick spacing 200, no hook) at the chosen start tick diff --git a/app/src/app/rules/page.tsx b/app/src/app/rules/page.tsx index d331519b..5ac46962 100644 --- a/app/src/app/rules/page.tsx +++ b/app/src/app/rules/page.tsx @@ -21,6 +21,19 @@ const NEVER = [ ["No admin", "No owner, no pause, no upgrade, no allowlist. The contracts are the same for everyone, forever."], ] as const; +/** Where each chain's contract source is verified (links go to the explorer's contract record). */ +const VERIFIERS: Record<(typeof CHAIN_KEYS)[number], { name: string; url: (addr: string) => string }[]> = { + base: [ + { name: "Basescan", url: (a) => `https://basescan.org/address/${a}#code` }, + { name: "Blockscout", url: (a) => `https://base.blockscout.com/address/${a}?tab=contract` }, + { name: "Sourcify", url: (a) => `https://repo.sourcify.dev/8453/${a}` }, + ], + robinhood: [ + { name: "Blockscout", url: (a) => `https://robinhoodchain.blockscout.com/address/${a}?tab=contract` }, + { name: "Sourcify", url: (a) => `https://repo.sourcify.dev/4663/${a}` }, + ], +}; + export default function RulesPage() { return (
@@ -109,11 +122,23 @@ export default function RulesPage() { not deployed yet )}

+ {c.factory && c.locker ? ( +

+ Source verified:{" "} + {VERIFIERS[k].map((v, i) => ( + + {i > 0 ? " · " : ""} + {v.name} (factory,{" "} + locker) + + ))} +

+ ) : null}
); })}

Identical bytecode on both chains. Uniswap v4's PoolManager, PositionManager, Permit2 and Universal Router are Uniswap's canonical deployments. MIT-licensed source on{" "} - GitHub ↗, verified on Basescan, Blockscout and Sourcify on both chains. + GitHub ↗; the verification records for each chain are linked above.

diff --git a/app/src/components/launchpad/LaunchHero.tsx b/app/src/components/launchpad/LaunchHero.tsx index 7c7b8795..a7a5d696 100644 --- a/app/src/components/launchpad/LaunchHero.tsx +++ b/app/src/components/launchpad/LaunchHero.tsx @@ -13,7 +13,10 @@ export default function LaunchHero({ configured }: { ethUsd?: number | null; con
0% platform fee - open source · verified contracts ↗ + open source · GitHub ↗ + + + verified contracts Base + Robinhood Chain · Uniswap v4 liquidity locked forever From 2e8661167f9517f1cc707543a57d99f402d57a6f Mon Sep 17 00:00:00 2001 From: Kevin Codex Date: Mon, 7 Sep 2026 13:41:14 +0800 Subject: [PATCH 3/4] review: llms.txt verification links omit missing (null) contract addresses instead of interpolating them --- app/src/app/llms.txt/route.ts | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/app/src/app/llms.txt/route.ts b/app/src/app/llms.txt/route.ts index 5507ea1f..82b60289 100644 --- a/app/src/app/llms.txt/route.ts +++ b/app/src/app/llms.txt/route.ts @@ -4,6 +4,16 @@ import { BRAND_DOMAIN } from "@/lib/brand"; export const dynamic = "force-dynamic"; +/** One "- : …" line per chain; links only for deployed contracts (factory / locker are nullable until configured). */ +function verificationLine(label: string, c: { factory: string | null; locker: string | null }, verifiers: [string, (a: string) => string][]): string { + if (!c.factory && !c.locker) return `- ${label}: (not deployed yet)`; + const parts = verifiers.map(([name, url]) => { + const links = [c.factory ? `${url(c.factory)} (factory)` : null, c.locker ? `${url(c.locker)} (locker)` : null].filter(Boolean).join(", "); + return `${name} ${links}`; + }); + return `- ${label}: ${parts.join("; ")}`; +} + export function GET() { const b = launchpad("base"); const r = launchpad("robinhood"); @@ -13,8 +23,15 @@ export function GET() { > Uniswap v4 liquidity, forever. No platform fee: the factory and locker have no fee address at all. ## Source verification -- Base (8453): Basescan https://basescan.org/address/${b.factory}#code (factory), https://basescan.org/address/${b.locker}#code (locker); Blockscout https://base.blockscout.com/address/${b.factory}?tab=contract; Sourcify https://repo.sourcify.dev/8453/${b.factory} -- Robinhood Chain (4663): Blockscout https://robinhoodchain.blockscout.com/address/${r.factory}?tab=contract (factory), https://robinhoodchain.blockscout.com/address/${r.locker}?tab=contract (locker); Sourcify https://repo.sourcify.dev/4663/${r.factory} +${verificationLine("Base (8453)", b, [ + ["Basescan", (a) => `https://basescan.org/address/${a}#code`], + ["Blockscout", (a) => `https://base.blockscout.com/address/${a}?tab=contract`], + ["Sourcify", (a) => `https://repo.sourcify.dev/8453/${a}`], +])} +${verificationLine("Robinhood Chain (4663)", r, [ + ["Blockscout", (a) => `https://robinhoodchain.blockscout.com/address/${a}?tab=contract`], + ["Sourcify", (a) => `https://repo.sourcify.dev/4663/${a}`], +])} ## What a launch does 1. deploys a fixed-supply ERC-20 (1,000,000,000; no mint/pause/blacklist/tax/owner) From 194dcab5cd6be678b8448032e32d3402f7fac3d0 Mon Sep 17 00:00:00 2001 From: Kevin Codex Date: Mon, 7 Sep 2026 13:43:26 +0800 Subject: [PATCH 4/4] tests: synthetic creator address in unit fixtures (the deployer stays only where it is meaningful: fork tests and deployment records) --- app/src/lib/launchpad/creator.test.ts | 2 +- app/src/lib/launchpad/holders.test.ts | 2 +- app/src/lib/launchpad/metaShared.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/lib/launchpad/creator.test.ts b/app/src/lib/launchpad/creator.test.ts index 485616f7..37505211 100644 --- a/app/src/lib/launchpad/creator.test.ts +++ b/app/src/lib/launchpad/creator.test.ts @@ -60,7 +60,7 @@ test("share card shaping", () => { const now = Date.parse("2026-09-06T12:00:00Z"); const c = shapeCard({ name: "Dollar Dog", symbol: "DDOG", chain: "robinhood", fdv_usd: 12345, fdv_quote: 12345, quote_symbol: "USDG", change_from_launch: 0.234, lp_fee: 10000, recipients: [{ payout: DEAD, bps: 10000 }], block_time: "2026-09-06T09:30:00Z" }, now); assert.deepEqual(c, { title: "Dollar Dog", symbol: "DDOG", chainLabel: "Robinhood Chain", mcap: "$12.3K", change: "+23%", up: true, fee: "1% fee, burned", age: "2h old", quote: null }); - assert.deepEqual(shapeCard({ name: "Base Stock Test", symbol: "BSTK", chain: "base", fdv_usd: 25206, fdv_quote: 109.6, quote_symbol: "NVDAc", change_from_launch: 0, lp_fee: 10000, recipients: [{ payout: "0x63f300b7b21fba52a8d874d90f7e1b301ae858c4", bps: 10000 }], block_time: "2026-09-06T09:30:00Z" }, now).quote, { symbol: "NVDAc", ticker: "NVDA" }, "stock quotes get a ticker tile on the card"); + assert.deepEqual(shapeCard({ name: "Base Stock Test", symbol: "BSTK", chain: "base", fdv_usd: 25206, fdv_quote: 109.6, quote_symbol: "NVDAc", change_from_launch: 0, lp_fee: 10000, recipients: [{ payout: "0x00000000000000000000000000000000000c0ffe", bps: 10000 }], block_time: "2026-09-06T09:30:00Z" }, now).quote, { symbol: "NVDAc", ticker: "NVDA" }, "stock quotes get a ticker tile on the card"); assert.equal(feeLabel(0, []), "0% fee"); assert.equal(feeLabel(30000, [{ payout: "0x1", bps: 10000 }]), "3% fee → beneficiary"); assert.equal(ageLabel("2026-09-06T11:59:30Z", now), "1m old"); diff --git a/app/src/lib/launchpad/holders.test.ts b/app/src/lib/launchpad/holders.test.ts index a57090aa..3406a0ec 100644 --- a/app/src/lib/launchpad/holders.test.ts +++ b/app/src/lib/launchpad/holders.test.ts @@ -4,7 +4,7 @@ import { DEAD_ADDR, ZERO_ADDR, applyTransfer, creatorActivity, fmtShare, holderT const PM = "0x498581fF718922c3f8e6A244956aF099B2652b2b"; const LOCKER = "0xcd1680D26922fcd9CabFbb8a56bA40C333fD842a"; -const DEV = "0x63f300b7b21fba52a8d874d90f7e1b301ae858c4"; +const DEV = "0x00000000000000000000000000000000000c0ffe"; const A = "0x" + "a".repeat(40); const B = "0x" + "b".repeat(40); const SUPPLY = 10n ** 27n; diff --git a/app/src/lib/launchpad/metaShared.test.ts b/app/src/lib/launchpad/metaShared.test.ts index 5e965fa0..263de5bb 100644 --- a/app/src/lib/launchpad/metaShared.test.ts +++ b/app/src/lib/launchpad/metaShared.test.ts @@ -2,7 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { metaUriFor, metaWriteDecision, validateMeta } from "./metaShared.ts"; -const L = "0x63F300b7b21FbA52A8D874D90F7E1B301AE858c4"; +const L = "0x00000000000000000000000000000000000c0ffe"; const SALT = "0x" + "a".repeat(64); const KEY = "0x" + "B".repeat(64); const base = { chain: "base" as const, launcher: L, salt: SALT, name: "Clear Sky", symbol: "sky" }; @@ -22,7 +22,7 @@ test("validateMeta: meta_key is optional (defaults to the salt) and normalized t test("metaUriFor is keyed by (launcher, meta_key) and is stable while the salt changes", () => { const u1 = metaUriFor(L, KEY); - assert.match(u1, /\/api\/launch\/meta\/0x63f300b7b21fba52a8d874d90f7e1b301ae858c4\/0xbbbb/); + assert.match(u1, /\/api\/launch\/meta\/0x00000000000000000000000000000000000c0ffe\/0xbbbb/); assert.equal(metaUriFor(L.toLowerCase(), KEY.toLowerCase()), u1, "case-insensitive"); assert.notEqual(metaUriFor(L, SALT), u1, "a different key → different URI"); });