GITLAWB exists on Robinhood Chain as a LayerZero V2 OFT
(0xd1b0d44E4f6ed940fcC7A9F59Bf30Daf62cCFe3D, community repo contracts.ts), minted 1:1 against
GITLAWB locked in the GitlawbOFTAdapter on Base (peers verified both ways on-chain). So the
Robinhood side needs no bridge work: the OFT is now a fixed quote next to USDG and ETH.
- config: robinhood quotes [USDG, ETH, GITLAWB]; same key, same badge, same live USD
(the Base pool price; the two are one supply kept within arbitrage by the bridge)
- queries: filter + USD factor match per chain (Base address on Base, OFT on Robinhood)
- filter chip offered on both chains; launch form nudge on any chain that offers GITLAWB
- copy: form, token page, rules, agents, llms.txt, README mention the bridged token
- contracts/test/LaunchFactory.gitlawbRobinhood.fork.t.sol: pins endpoint + Base peer and
proves launch/buy/sell/collect with the fee burned as GITLAWB on live Robinhood Chain
Launches on Base can now be priced in GITLAWB (Gitlawb's token), next to ETH and
Coinbase tokenized stocks. Same contracts, same ERC-20 quote path (Permit2, salt
ordering); trading fees are paid in GITLAWB, or burned when no beneficiary is named.
- lib/launchpad/gitlawb.ts: token facts, the WETH/GITLAWB Uniswap v4 pool key
(dynamic-fee hook, tick spacing 200; pool id asserted = keccak(abi.encode(key))),
USD from sqrtPriceX96 x ETH/USD with a sanity window, dollar->GITLAWB presets, tile
- lib/launchpad/gitlawbServer.ts: StateView.getSlot0 read, 60s cache, fail-soft
- config: quote key "gitlawb", Base quotes [ETH, GITLAWB], presets, quoteKeyOf()
- queries: live USD factor in SQL sorts/volume/mcap + totals, gitlawb list filter
- launch form: GITLAWB chip with live price, dollar start-cap presets, compact units
- token page + share card: "priced in GITLAWB" note/pill with the Gitlawb mark
- fmtQuote: 18-dec amounts >= 100K read as 1.2M (GITLAWB is millions per dollar)
- copy: rules (new FAQ entry), agents, llms.txt, README
- tests: gitlawb.test (pool id, price, presets), filter + card cases (256 total);
contracts/test/LaunchFactory.gitlawb.fork.t.sol proves launch/buy/sell/collect on
live Base with the 1% fee burned as GITLAWB
Four points from the CHANGES_REQUESTED review, plus the test-key concern:
1. Cross-platform test command. `npm test` used inline `TEST_MOCK_DB=1
NODE_OPTIONS=...` which fails on Windows (cmd does not expand inline
env vars). The mock swap is actually done by tsconfig.test.json paths,
so TEST_MOCK_DB was vestigial; the only need is the react-server
condition for `server-only`. Pass `--conditions=react-server` straight
to tsx, which is portable with no env var and no new dependency.
Removed `test:unit`: plain `node --test` cannot run the server test
(needs tsconfig path mocks + react-server), so it was broken, and
`test` now runs the whole suite cross-platform.
2. RPC outage classification. viem 2.55.19's verifyMessage returns false
(rather than throwing) when the RPC transport is unreachable, so an
outage surfaced as 401 "signature does not match" instead of 503.
Added a getChainId liveness probe on the false branch: if the probe
throws, the false came from an outage (503); otherwise it is a genuine
mismatch (401). The nonce is intact either way. The probe only runs on
the failure path, so the happy path keeps its cost.
3. Transport-level outage test through viem itself. The chain mock now
returns a real viem client with an unreachable transport when
transportOutage is set, so the outage path runs through viem's actual
verifyErc6492 path (the same one smart-wallet verification uses) rather
than a hand-rolled stub. Added a unit test asserting 503 + nonce intact.
4. e2e IP-limit test. The IP check used a fresh IP per request, so it
passed even with no limiter. Kept the cross-IP isolation check and
added a single repeated IP past the 30/min limit, asserting it
eventually gets 429.
Test key: replaced the hardcoded TEST_PRIVATE_KEY with a freshly
generated disposable key (never funded, public by design) and labelled
it. The old key is in git history; if it was ever used for real funds
those should be moved, since it is now public.
- Metadata registration is INSERT-only for unsigned callers: the creator registers before broadcasting
(salt still private); replaying the public launch params returns 409 and cannot overwrite image /
description / website. Later changes go through the wallet-signed edit flow. (review finding 1)
- The on-chain metadataURI is keyed by a client-chosen meta_key instead of the salt, so findSalt's
result stays valid for USDG / stock quotes. Proven on the live Robinhood factory: 17/100 deterministic
USDG launches reverted with the old scheme, 0/100 with the new one. (finding 2)
- Swap and fee ingestion commit the event row and the launch totals in one transaction; a rebuild script
recomputes totals from raw events if ever needed (production checked: no drift). (finding 3)
- Fresh checkout: npm run migrate reads DATABASE_URL from .env.local/.env; fly-secrets.sh is self-contained
(FLY_APP, SECRETS_ENV); README run + deploy steps corrected.
- CI workflow (lint, typecheck, unit tests, production build; forge build + unit tests), CONTRIBUTING.md,
SECURITY.md with private reporting.
openlaunch — launch a token. Free. Open source. On Base or Robinhood Chain.
Contracts (LaunchFactory / LaunchLocker / LaunchToken, Foundry), the site (Next.js),
brand assets. No platform fee, liquidity locked forever.