Whitepaper

LIQUOR.TRADE Protocol

A permissionless token launchpad on Robinhood Chain that deploys every token straight into a permanently locked Uniswap V3 position — no bonding curve, no migration, no liquidity an administrator can touch.

v2.0September 2026Robinhood Chain (4663)Read the docs →
Contents

1. Abstract

LIQUOR.TRADE is a token launchpad on Robinhood Chain, an Arbitrum Orbit L2 that settles to Ethereum. A creator submits one transaction and receives, atomically, a fixed-supply ERC-20, a live Uniswap V3 pool paired with WETH, the full supply deposited as a one-sided liquidity position, and that position transferred into a locker contract with no withdrawal function. Trading begins in the same block, on Uniswap V3 itself, with no intermediary contract between the trader and the pool.

The protocol has no bonding curve and no graduation migration. The concentrated-liquidity position is the curve: because all of the supply sits above the opening price and none of the WETH sits below it, buying moves the price up along the V3 tick range in exactly the way a bonding curve would, except the liquidity is already in the place it would eventually have to migrate to. What other launchpads call “graduation” is here a milestone read from the position’s WETH principal, not a state transition that moves funds.

Fees are charged at two layers. Uniswap’s 1% pool fee accrues inside the locked position and is split on claim between the creator (70%) and the protocol (30%), a ratio snapshotted per token at launch. On top of that, trades sent through the app’s router pay a creator fee the deployer sets once (0–5%) and a 1% protocol fee, both in ETH, both capped by constants. The first two blocks after launch apply per-wallet and per-transaction caps that bind every buyer except the creator’s atomic opening buy. Everything the app shows is indexed from chain reads with block and transaction provenance; the repository contains no mock data.

What this document is
A description of the contracts in contracts/launch/ and the data layer in lib/pons*.ts as they are written. Every number is either a constant in the code or is derived from one by a formula shown alongside it. It is not marketing, and it does not describe features that do not exist yet — those are in §17.

2. The problem with launchpads

The dominant launchpad pattern — a custom bonding-curve contract that later “graduates” to a DEX — works, but it carries four structural costs that this design was built to remove.

2.1 The migration is a moment of custody

A bonding-curve pool holds every buyer’s ETH until the curve completes. Graduation is a transaction the pool contract executes: withdraw the ETH, withdraw the tokens, call a router, receive LP tokens, burn them. Every step is code the launchpad wrote, and for the duration of the curve the launchpad — not a DEX with years of battle-testing — is the custodian. An earlier version of this project ran exactly that design (contracts/BondingCurvePool.sol, still in the repository as history), and the migration path was where most of its risk lived.

2.2 Two price regimes mean two sets of bugs

Pre-graduation trades go through the curve; post-graduation trades go through the DEX. The UI, the indexer and the wallet integration all need two code paths, and the seam between them — the block in which the curve closes and the pool opens — is where price can be manipulated, where a stuck migration strands funds, and where an indexer that missed one event drifts permanently.

2.3 Snipers are a clock problem, not a wallet problem

Per-wallet caps are defeated by splitting across addresses for the cost of gas. The only constraint a sniper cannot buy around is time: what happens in the launch block and the blocks right after it. A protection that does not reason about block numbers is decoration.

2.4 Fake numbers

Launchpad frontends routinely display synthesised charts, invented volume and placeholder holders. A trader cannot tell a random walk from a market. A launchpad that earns from trades has an incentive to make markets look more alive than they are, and the only defence is a data layer where every number points at a block.

3. Design principles

One transaction, one venue

Deploy, pool, seed, lock, and buy in a single call. Trading happens on Uniswap V3 from block one. There is no second regime to migrate to.

The liquidity is not ours to move

The position NFT lives in a contract with no withdrawal, no arbitrary-call, and no upgrade function. The owner can change future policy; it cannot reach existing liquidity.

Time-bound protection

Anti-snipe rules are keyed to block.number, apply only to buys from the pool, and expire two blocks after launch. After that the token is a plain ERC-20.

Snapshot, don’t trust

Every economic parameter that affects an existing token — the fee split, the caps, the restriction window — is copied into the token or the locker at launch and read from there afterwards.

Every number has a block

The indexer writes only what it read from chain, keeps the block hash and transaction hash, and labels price points by source. A flat chart means nothing traded.

Simulate before you sign

Launches and fee claims are dry-run with the real calldata before the wallet opens, so the contract’s own revert reason — not a client-side guess — is what the user sees.

4. Protocol architecture

The protocol is three contracts plus shared Uniswap V3 infrastructure that already exists on the chain.

ContractRoleOwnership
LiquorLaunchFactoryEntry point. launchToken deploys the token via CREATE2, creates and initialises the pool, mints the position, hands it to the locker, records the launch, and executes the opening buy. Holds the DEX and launch configurations. Exposes graduationStatus.Ownable2Step
LiquorLaunchLockerPermanent custodian of every position NFT. Accepts NFTs only from the factory, verifies custody in lockPosition, splits collected fees, tracks per-token protocol share and fee redirects. No withdrawal path exists.Ownable2Step
LiquorTradeRouterThe app’s swap entry point. Wraps SwapRouter02 and charges the creator’s per-token fee plus the protocol fee in ETH. Independent of the factory; trades on unregistered tokens pay only the protocol leg.Ownable2Step
LiquorLauncherTokenFixed-supply ERC-20 with immutable launch parameters, self-describing metadata (logo, description, socials), and a transfer hook that enforces the launch-window caps on pool-to-wallet transfers only.None (immutable)

Off-chain, a single long-running indexer reads factory launch events, token metadata, pool state and swap logs into a libSQL database; a Next.js API serves that database to the browser. The browser touches the chain for exactly one purpose: signing a transaction the user asked for.

Data flow
Robinhood Chain (factories, tokens, V3 pools)
        │  eth_getLogs + view calls (paced, retried)
        ▼
scripts/pons-indexer.ts            long-running worker (PM2)
        │  writes markets / price_points / data_versions
        ▼
libSQL (local file in dev, Turso in production)
        │
        ▼
GET /api/data?kind=updates|markets|market      ETag + 304
GET /api/config
        │
        ▼
lib/use-markets.ts  →  React UI

Wallet writes (launch, swap, claim) go straight from the browser to the chain.
Nothing is settled server-side; the pool's own events are the record.

5. The launch transaction

launchToken(TokenParams, launchConfigId, dexId, salt) is payable and nonReentrant. msg.value must be at least the launch fee; whatever exceeds it becomes the creator’s opening buy. The full sequence, in order:

  1. Gate checks. launchEnabled (true from construction on this factory) or the caller is allowlisted; fee paid; DEX and launch config exist and are enabled; name and symbol are non-empty.
  2. Address prediction. The token’s creation code is built from the params and the config, and its CREATE2 address is computed. If a V3 pool for (predicted token, WETH, 1%) already exists, the call reverts PoolAlreadyExists. This is what makes a collision free to detect by simulation.
  3. Launch fee is forwarded to the locker’s protocolFeeRecipient. Default 0.0005 ETH, owner-adjustable.
  4. Token deploy via CREATE2 with the caller’s salt. The constructor mints the entire supply (1,000,000,000 × 10¹⁸) to the factory and stamps launchBlock, restrictionEndBlock = launchBlock + 2, and the caps as immutables.
  5. Pool creation. Token ordering is determined (isToken0 = token < WETH); the initial tick is sign-flipped if the token is token1; the pool is created and initialised at sqrtPriceX96 = getSqrtRatioAtTick(tick).
  6. One-sided mint. The factory approves the position manager for the supply and mints a position whose range is [initialTick, maxUsableTick] (token0 case) or [minUsableTick, −initialTick] (token1 case). Only token goes in; amountMin is zero because the pool is fresh and nothing can front-run a pool that did not exist a moment earlier.
  7. Record. A LaunchedToken struct is stored: deployer, paired token, position manager and id, config ids, restriction end block, supply, ordering, pool fee, and the opening buy amount. The graduation threshold is copied per token.
  8. Lock. The NFT is safeTransferFrom’d to the locker, which only accepts transfers where both operator and sender are the factory. lockPosition re-reads ownerOf and reverts unless the locker holds it, then snapshots the protocol fee share for that token.
  9. Fee redirect. If feeWallet was supplied, the locker is told to pay the creator share there instead of to the deployer.
  10. Event. TokenLaunched is emitted with a signature byte-identical to pons’s (§13).
  11. Opening buy. If anything remains above the fee, the token opens a one-call recipient exemption, the factory calls exactInputSingle on SwapRouter02 with the remaining ETH, and the exemption is closed. The buy lands with the creator (or their feeWallet) as recipient.
Launch config 0 (deploy script)ValueMeaning
pairTokenWETHEvery pool is token/WETH.
supply1,000,000,000Fixed. No mint function exists after construction.
initialTick−204,200Opening price ≈ 1.3557 × 10⁻⁹ WETH per token (§6).
graduationThreshold4.2 WETHPrincipal in the position at which graduated = true (§10).
maxWalletBps500 (5%)Max balance a buyer may hold via pool buys during the window.
maxTxBps550 (5.5%)Derived as 110% of maxWallet; cumulative pool-buy cap per wallet.
restrictionBlocks2Window = launch block plus the next two.
Pool fee tier10,000 (1%)Uniswap fee on every swap; the only LP fee in the pool.
tickSpacing200Required by the 1% tier.
launchFee0.0005 ETHPaid to the protocol fee recipient. Owner-adjustable.
The opening buy is not capped
The token’s transfer hook exempts the recipient of the factory’s atomic buy from both caps, in the launch block only. The creator can therefore take as much of the supply as their ETH buys at the curve price. The caps in §7 bind everyone else. This is disclosed rather than hidden: a buyer should read initialBuyAmount from getLaunchedToken, which is also shown on the token page, before deciding.

6. Price discovery on concentrated liquidity

Uniswap V3 quotes price in ticks. The price of token1 in units of token0 at tick i is:

P(i) = 1.0001i

With the token as token0 and WETH as token1, the launch config’s tick of −204,200 gives an opening price of 1.0001⁻²⁰⁴²⁰⁰ ≈ 1.3557 × 10⁻⁹ WETH per token. If the token sorts as token1 the sign flips and the pool price is the reciprocal, but the economic price is the same. The indexer computes it from slot0().sqrtPriceX96:

price = (sqrtPriceX96 / 296)²  ·  then inverted if the token is token1

At launch, all 10⁹ tokens are deposited into the range [P₀, Pmax] with no WETH. For a position entirely above the current price, V3 defines the token0 amount as x = L · (1/√P − 1/√Pmax). Since Pmax is the top of the tick range and effectively infinite, L ≈ S · √P₀, where S is the supply. As buyers add WETH the price rises and the WETH principal inside the position becomes:

y(P) = L · (√P − √P₀)  =  S · P₀ · (√(P / P₀) − 1)

S · P₀ is the fully diluted value at launch: ≈ 1.3557 ETH. That single number characterises the whole curve. Some consequences, ignoring the 1% swap fee:

WETH principal in positionPrice multiple vs launchFDVSupply sold
01.00×1.36 ETH0%
1.36 ETH4.00×5.42 ETH50.0%
2.71 ETH9.00×12.2 ETH66.7%
4.20 ETH (graduation)16.8×22.8 ETH75.6%
8.00 ETH47.6×64.5 ETH85.5%
20.0 ETH248×337 ETH93.7%

This is the same shape as a constant-product bonding curve with virtual reserves — it is one, expressed in V3’s square-root coordinates — with the difference that there is nothing to migrate. The liquidity that traders are buying against is already on the DEX, the position already exists, and the NFT is already locked.

6.1 Why the quoter, not the chart

The displayed price is the pool’s spot price and ignores the impact of the trade’s own size. On a curve this steep a modest buy moves the price materially, so a slippage floor derived from the displayed price would sit above what the trade can actually fill and revert every large order. The app therefore quotes every trade through Quoter V2 — which simulates the swap against current pool state — and applies the user’s slippage tolerance to that quote, capped at 50%.

6.2 Trade mechanics

  • Buy: exactInputSingle on SwapRouter02 with native ETH as msg.value; the router wraps it to WETH itself. Recipient is the buyer.
  • Sell: ERC-20 approve (once, unlimited) then a router multicall of exactInputSingle with recipient address(2) — the router’s “keep it here” sentinel — followed by unwrapWETH9(minOut, seller). The slippage floor is enforced on the unwrap, so the seller receives ETH, not WETH, or the whole multicall reverts.
  • Nothing is written to the database by the client. The pool’s Swap event is the record and the indexer reads it back. Writing client-side would double-count.

7. Launch-window protections

Protections live in the token’s _update override and are evaluated only while block.number ≤ restrictionEndBlock. They apply only when from is a pool for this token and WETH registered by the Uniswap factory — at any fee tier, so a pool created at a different tier to dodge the hook is still recognised. Wallet-to-wallet transfers, sells into the pool, and everything after the window are untouched.

BlockRule for pool → wallet transfers
launchBlockAll buys revert (LaunchBlockBuyBlocked) except the single recipient the factory registered for its atomic opening buy, and only while that registration is open. A sniper who lands in the launch block gets a revert, not a fill.
launchBlock + 1, + 2Resulting balance must not exceed maxWalletLimit() = 5% of supply (MaxWalletExceeded), and cumulative pool buys per recipient must not exceed maxTxLimit() = 5.5% of supply (MaxTxExceeded). The cumulative counter is per recipient, so splitting one large buy into several within the window does not help.
launchBlock + 3 onwardNo rules. The token is a plain OpenZeppelin ERC-20.

The relationship maxTxBps = ⌊1.1 × maxWalletBps⌋ is enforced by the factory when a launch config is added; a config with any other pairing reverts InvalidMaxTxBasisPoints. The 10% headroom exists so a wallet already near the cap can still complete a buy whose rounding would otherwise fail.

What this does and does not defend against
It removes the launch-block race entirely and bounds any single address to 5% for two blocks. It does not stop a determined actor from using many addresses in blocks +1 and +2; per-wallet rules never can. What it guarantees is that the first fill anyone can get, other than the creator, is at least one block after the creator’s own — and the creator’s buy is public in the launch event.

8. The liquidity lock

The locker is the contract the whole design rests on, and it is deliberately small. It is 5,426 bytes compiled — identical in size to pons’s deployed locker, which is a reasonable signal that the build reproduces the verified source.

  • onERC721Received returns the magic value only when both operator and from are the factory. Any other NFT transfer reverts.
  • lockPosition(token) is onlyFactory, reads the launch record back from the factory, and reverts PositionNotHeld unless ownerOf(positionId) is the locker itself. It cannot be called twice for one token.
  • initialize(factory) binds the locker to one factory, once. AlreadyInitialized otherwise.
  • There is no function that calls decreaseLiquidity, burn, transferFrom or safeTransferFrom on the position manager, no generic execute(address, bytes), no selfdestruct, and no proxy. The only call the locker makes on the position manager after locking is collect, which withdraws accrued fees and cannot touch principal.

The consequence is that the liquidity cannot be rugged by the creator, and cannot be rugged by the protocol either. The owner of the locker can change who receives the protocol’s share of future fees, and what that share is for tokens launched after the change. It cannot remove a position, cannot redirect an existing token’s split, and cannot pause trading — trading happens on Uniswap, which the locker does not control.

9. Fees and revenue split

Trading fees are charged at two layers. The pool layer is Uniswap V3’s 1% tier, taken by Uniswap on every swap in both directions and accrued inside the locked position, because that position is the only liquidity in the pool. The router layer is LiquorTradeRouter, the app’s swap entry point, which charges a per-token creator fee and a flat protocol fee in ETH on every trade sent through it.

FeeAmountGoes to
Launch fee0.0005 ETH (owner-adjustable)Protocol fee recipient, at launch.
Creator trading fee (router)0–5%, set once by the deployer; default 2%Creator wallet, in ETH, on every routed trade.
Protocol trading fee (router)1% (hard-capped at 2%)Protocol fee recipient, in ETH, on every routed trade.
Pool fee (Uniswap)1% of every buy and sellAccrues inside the locked V3 position.
— creator share on claim70% (100 − protocolFeeShare)Deployer, or the feeWallet redirect.
— protocol share on claim30% (default; hard-capped at 50%)Protocol fee recipient.

9.0 The router layer

The pool’s fee tier is fixed by Uniswap and cannot be raised, so a creator-chosen fee has to be collected outside the pool. The router wraps SwapRouter02: on a buy it takes creatorBps + protocolBps off msg.value and swaps the remainder; on a sell it swaps to WETH, unwraps, takes the same share off the output and pays the seller the rest. The slippage floor is on the net figure. The UI shows the two router legs as one number — a 2% creator fee displays as 3% — with the pool fee listed separately.

  • setTokenFee is callable only by the token’s deployer(), only once, and only up to MAX_CREATOR_FEE_BPS = 500. The fee a trader sees is the fee for the life of the token; only the recipient wallet can move. The 5% ceiling is a constant, not an owner setting, chosen because a round trip at 5% costs 10% and a round trip at anything higher starts to resemble a honeypot.
  • The protocol leg is owner-set between 0 and MAX_PROTOCOL_FEE_BPS = 200.
  • Fees are pushed at trade time under a 30k gas stipend; a recipient that cannot accept ETH has the amount booked to pending and claims it with claimPending(). A fee recipient can never revert a trade.
  • A fee-on-transfer hook in the token was rejected: it breaks sells on Uniswap V3, gets the token flagged as a tax token, and pays the creator in tokens they must then sell. The cost of the router design is that a trade sent directly to Uniswap pays only the pool’s 1%. That trade-off is deliberate and disclosed.

9.1 Claiming

collectFees(token) on the locker calls the position manager’s collect for the maximum of both assets, reverts NoFeesToCollect if both are zero, splits each asset by the token’s snapshotted share, and transfers all four legs. Authorised callers are the locker owner, the token’s deployer, the current fee redirect recipient, and any address in feeCollectors. Fees arrive in the assets they were paid in — a mix of WETH and the token — not converted.

9.2 Why fees are read by simulation

Uniswap V3 exposes no view that returns a position’s uncollected fees after accounting for fee growth; the honest number is whatever collect would return right now. The app therefore simulates collectFees with eth_call to display the pending amount and sends the real transaction only when the creator clicks claim. A NoFeesToCollect revert in simulation is rendered as zero. Zero means “nothing accrued yet”, never “already paid” — these contracts never push fees on their own.

9.3 Snapshotting

tokenProtocolFeeShares[token] is written once, in lockPosition, from the locker’s current protocolFeeShare. setProtocolFeeShare changes only what future launches will copy. A fork test launches a token at 30%, raises the share to 50%, and asserts the first token still splits at 30%.

9.4 Fee redirects

The deployer (or the factory, during launch) can point a token’s creator share at another wallet with setFeeRedirect. The locker maintains a reverse index (feeRecipientTokens) so a profile page can list every token a wallet earns from, whether it deployed them or was assigned them.

10. Graduation

Graduation on this protocol is a label, not a migration. Nothing moves. The factory’s graduationStatus(token) view computes the WETH principal currently inside the locked position — from slot0, the position’s tick bounds and its liquidity, via the same amount formulas V3 uses — and compares it to the threshold copied at launch:

graduated = threshold ≠ 0 ∧ pairedPrincipal ≥ threshold

The indexer stores progress = min(pairedPrincipal / threshold, 1). With the deployed config (4.2 WETH) and the curve in §6, graduation corresponds to roughly a 16.8× price move from launch, an FDV near 22.8 ETH, and about 75.6% of supply sold, before fees.

Donations do not count
The principal is computed from the position’s liquidity, not from the pool’s WETH balance. Sending WETH directly to the pool contract changes the balance but not the position, so it cannot fake graduation. A pool that later sells off can drop back below the threshold; the flag is a live read, not a latch.

11. Admin surface and what it cannot do

Both the factory and the locker use OpenZeppelin Ownable2Step: an ownership transfer must be accepted by the new owner, which prevents a typo from bricking administration. The complete list of owner-only functions:

ContractFunctionEffectAffects existing tokens?
FactoryaddDexConfig / setDexStatusRegister or disable a V3 deployment.No
FactoryaddLaunchConfig / updateLaunchConfigAdd or replace a launch parameter set.No — params are immutables in each token
FactorysetLaunchFeeChange the ETH fee for future launches.No
FactorysetLaunchEnabledOpen or close public launching.No — trading is on Uniswap
FactorysetWhitelistedLauncherAllowlist an address while public launching is closed.No
LockerinitializeBind to the factory, once.
LockersetProtocolFeeRecipientWhere the protocol share is paid.Yes, for future claims
LockersetProtocolFeeShareShare snapshotted by future launches (≤ 50).No — snapshotted
LockersetFeeCollectorAllow an address to trigger collectFees for any token.Only who may call; not the split
RoutersetProtocolFeeBps (≤ 200)Liquor’s leg on routed trades.Yes, from that block on
RoutersetProtocolFeeRecipientWhere Liquor’s leg goes.Yes, for future trades

Not possible for any owner: withdrawing or transferring a locked position; minting tokens; changing a token’s supply, caps, or restriction window; changing an existing token’s fee split; raising a creator’s trading fee or the 5% / 2% caps; pausing or blocking swaps; upgrading any contract. None of these functions exist.

12. Data integrity

The frontend serves nothing it computed itself and nothing it could not point at a block. The rules the indexer will not bend:

  • Every row in markets keeps block, blockHash and hash from its launch transaction. Every swap price point keeps its txHash.
  • A price point is either a real Swap log (source: "swap") or a real slot0 read (source: "sample"). They are labelled and never merged. No interpolation, no jitter, no synthesised history.
  • Reserves and prices are re-read from the pool on every pass rather than adjusted by event deltas, so a missed log costs one stale poll instead of permanent drift.
  • live.volume is the count of trades in the last 24 hours, not a notional USD figure. It is named honestly rather than inflated into a dollar amount that was not computed.
  • live.stale is set when a snapshot is older than PONS_STALE_MS (default 5 minutes), so the UI can say the data is old instead of presenting it as current.
  • Liquidity USD values both sides of the pool separately. A V3 pool is not balanced, so “double the WETH side” would overstate a pool that has drifted.
  • /api/config reports simulated: false and dataSource: "indexed-onchain". If a simulated mode is ever added, that flag is how the UI must gate a banner.
  • The repository contains no seed data for markets. An empty list means nothing has launched.

13. Interoperability with pons

pons is a third-party launchpad on Robinhood Chain whose contracts are verified on Blockscout and published under MIT. This protocol’s contracts are adapted from that source with two changes: type names carry a Liquor prefix, and launchEnabled is true from construction. pons ships it false and admits launchers by allowlist (checked 7 September 2026 on both of their factories), which is the entire reason for running a separate deployment.

Event signatures are byte-identical. TokenLaunched’s topic0 on this factory equals pons’s, so one indexer reads both factories with no second code path, and the app lists tokens from either. A fork test asserts the hash so it cannot drift silently. Trading is factory-agnostic anyway — a swap needs only the pool fee tier and WETH — and only launch metadata and fee claims walk the factory list.

pons factoryAddressCreator share
Legacy (PONS itself launched here)0x0c37a24F5D23A486FA692d1500881d698B1F77a490%
Active0xA5aAb3F0c6EeadF30Ef1D3Eb997108E976351feB70%
LIQUOR.TRADE indexes public on-chain data from pons and calls its public contracts. This is not a partnership; pons is not affiliated with this project and does not endorse it.

14. Security considerations

14.1 What has been verified

  • Ten tests run against a fork of Robinhood Chain mainnet and the real Uniswap V3 deployment (FORK=1 npm run contracts:test): unallowlisted launch succeeds; the whole supply reaches a live pool with only rounding dust left; everything above the fee becomes the opening buy; the creator’s buy is exempt from the caps; a later buyer is held to the max-transaction cap inside the window; the launch fee reaches the recipient; the position is locked and graduation reports progress; the fee split is snapshotted; the TokenLaunched hash matches pons’s.
  • Ten offline tests for the trade router against mock WETH / SwapRouter02 / token: fee arithmetic on both legs of both directions, deployer-only / once-only / capped creator fees, owner-only capped protocol fee, after-fee slippage floor, deferred fees, zero-amount rejection.
  • ReentrancyGuard on launchToken, collectFees, buy and sell; SafeERC20 for all token transfers; forceApprove reset to zero after the mint.
  • The deploy script refuses any chain other than 4663 and verifies each dependency address holds code.

14.2 What has not

No third-party audit
These contracts have not been audited by an independent firm. They are adapted from verified, deployed source, but adaptation is a change. The four client write modules (launch, swap, fee claim, quote) have no automated tests yet. Treat the protocol accordingly.

14.3 Known limitations and risks

  • Mainnet only. Uniswap V3 is not deployed on Robinhood Chain testnet; there is no way to rehearse a launch or a swap with test ETH. The first of each is real money.
  • Uncapped creator buy. A creator can buy a large fraction of supply at launch. It is public in the event and the token page, but it is possible.
  • Curve steepness. With FDV ≈ 1.36 ETH at launch, small buys move price a lot. This is the nature of a launchpad, not a bug, but slippage settings matter.
  • Rate limiter is per-instance. Server-side write limits live in module scope; on a horizontally scaled host the effective limit multiplies by instance count.
  • Public RPC. Robinhood’s public endpoint rate limits hard. The indexer paces and backs off, but production needs a dedicated endpoint or snapshots will go stale.
  • Build settings are load-bearing. viaIR is required or the factory does not compile; evmVersion: shanghai is required or it lands ~600 bytes over the 24,576-byte deploy limit. Cancun is avoided because TSTORE/MCOPY support varies across Orbit chains.

15. Robinhood Chain

Robinhood Chain is an Arbitrum Orbit L2 that settles to Ethereum and uses ETH for gas. It is a different network from Unichain. The app pins chain 4663 for every write regardless of other configuration.

MainnetTestnet
Chain ID466346630
RPCrpc.mainnet.chain.robinhood.comrpc.testnet.chain.robinhood.com
Explorerrobinhoodchain.blockscout.comexplorer.testnet.chain.robinhood.com
Uniswap V3DeployedNot deployed
This protocolTargetCannot run (no V3)

The chain produces roughly 864,000 blocks a day, so a two-block restriction window is on the order of a fraction of a second of wall-clock time rather than a minute. The protection is about ordering, not duration.

16. Licensing

LiquorLauncherToken.sol and LiquorLaunchLocker.sol are MIT. TickMath.sol is Uniswap’s, GPL-2.0-or-later, and copyleft carries into any contract that includes it, so LiquorLaunchFactory.sol is GPL-2.0-or-later. The contracts are published and verified either way; the practical consequence is that the factory cannot be relicensed as proprietary.

17. Status and roadmap

ItemStatus
Contracts written, compiled, fork-testedDone
Indexer running under PM2 against pons factoriesDone
Client hooks for launch / swap / quote / fee claimDone
Deploy LiquorLaunchFactory + Locker to mainnetPending — until then launching falls back to pons’s gated factory and is blocked with a clear message; trading works
First mainnet swap and launch, reconciled against the indexerPending
Hosted libSQL (Turso) for productionPending — code supports it
Shared-store rate limiterPending
Automated tests for client write modulesPending
Independent auditNot scheduled
Remove retired bonding-curve code once the V3 path has traded on mainnetPending

18. Disclaimer

This document describes software. It is not investment advice, an offer to sell, or a solicitation to buy any token. Tokens launched through the protocol are created by their deployers, not by LIQUOR.TRADE, and the protocol makes no representation about any of them. Concentrated-liquidity markets with small initial depth are volatile; a buyer can lose the entire amount spent. The contracts are unaudited and provided as-is under their respective licences. Nothing here should be read as a promise that any feature listed as pending will ship.