How it works
Quote assets
Every coin is priced in something. OKB by default — or one of six tokenised Hong Kong equities, so a coin can be denominated in Tencent rather than in the gas token.
A coin's quote asset is what buyers spend, what its price and market cap are counted in, and what its creator earns. It is fixed when the coin is created and can never be changed — it is written into the curve, or into the pool, at that moment.
The default is OKB, the chain's own gas token. Six tokenised Hong Kong equities are also approved, so a coin can be denominated in Tencent or Meituan instead.
The approved list#
| Asset | Stock | Opens at | Graduates at |
|---|---|---|---|
| OKB | Native gas token | 30 OKB | 75 OKB |
| wTCENTx | Tencent · HK 700 | 61.7 | 154.2 |
| wSHEINx | SHEIN · HK 625 | 633.9 | 1,584.9 |
| wHKEXCx | HKEX · HK 388 | 66.2 | 165.4 |
| wKUAIx | Kuaishou · HK 1024 | 829.6 | 2,074.1 |
| wMEITx | Meituan · HK 3690 | 351.4 | 878.5 |
| wMIXUx | Mixue · HK 2097 | 135.8 | 339.5 |
Every figure is denominated in the asset on its own row, and every one is pegged to roughly the same value as the OKB numbers above it — around 30 OKB to open and 75 to graduate — so a coin's economics do not change because of what it is priced in. Stock prices move, so those pegs are adjusted on chain from time to time; the launch form reads them live rather than repeating this page.
A seeded pool opens within about 1% of the same figure. Its opening price has to land on a usable Uniswap tick, and ticks are 2% apart on the tier these launch on.
Why the wrapped version#
Backed's xStocks rebase on EVM: dividends and splits are applied by moving a
multiplier that rewrites balanceOf in place, without a transfer. A bonding
curve reads its own quote balance as the reserve backing every seller, so a rebase would
conjure reserve out of a dividend or strand it on a reverse split — the coin's price
would move because the underlying stock paid a dividend, which is not a market anyone
asked for.
The wrappers are ERC-4626 vaults. A share balance only moves when someone deposits or redeems, so the reserve means what the contract thinks it means. The dividend still accrues — it accrues to the vault, and therefore to the share price.
What changes for a creator#
- Your fees arrive in that asset. A wTCENTx-quoted coin pays its creator in wTCENTx, claimable from the same escrow as everything else.
- The launch fee is still OKB. It is charged in the gas token regardless of what the coin is quoted in, so you need OKB in the wallet either way.
- Your own buy is unavailable on a seeded launch. It is funded with the launch transaction's own native value, and that value is OKB.
- Your buyers need the asset. Which is the real cost — see below.
What changes for a trader#
You need the quote asset itself. There is no OKB pool for any of these stocks on X Layer — they trade against USDG on Uniswap v3, while the funded OKB market is a v4 pool — so reaching one from the gas token is three hops across two protocols.
Not yet on the site
Buying a stock-quoted coin with OKB in one click is not live here yet. The coin's market is real and public either way: a seeded one is an ordinary Uniswap v3 pool that anything holding the stock can trade, and a curve one can be traded by calling it directly with the stock. What is missing is the one-transaction path from OKB, and the trade panel says so rather than offering a form that would revert.
Launching against one#
A stock-quoted coin is a curve launch with the wrapper's address
in place of OKB. The quote asset is the third argument to
launchToken, and it is a constructor immutable on the curve — there is no
setter, and nothing can change it afterwards.
A seeded launch picks its quote asset differently. The v3 factory's
launchToken takes (params, launchConfigId, dexId, salt) — there
is no quote-asset argument, because the asset is part of the launch config rather than
passed alongside it. There is one config per approved asset, so the id you choose is the
pairing you get:
| launchConfigId | Quote asset | Graduates at |
|---|---|---|
0 | WOKB | 75.00 |
1 | wTCENTx | 154.21 |
2 | wSHEINx | 1,584.87 |
3 | wHKEXCx | 165.40 |
4 | wKUAIx | 2,074.10 |
5 | wMEITx | 878.49 |
6 | wMIXUx | 339.52 |
Read launchConfigCount() and getLaunchConfig(id) rather than
trusting this table — configs are added and re-pegged on chain, and the id is the only
thing your call passes. Note that a seeded launch quotes against wrapped
OKB where a curve launch quotes against the native token, which is why config
0 reads WOKB and not OKB.
Two things differ from an OKB launch, and both of them revert rather than misbehave if
you get them wrong. The opening buy is denominated in the stock, so
LaunchAndBuy pulls it with transferFrom and needs an allowance
first. And the call carries the launch fee alone as native value — the fee is
always OKB, but the buy no longer is, so the familiar
launchFee + quoteIn is wrong here and fails with
NativeValueMismatch.
import { erc20Abi, parseUnits, parseEventLogs } from 'viem'
import {
publicClient, walletClient, account,
size, factoryAbi, launchAndBuyAbi,
STOCKS, LAUNCH_CONFIG_ID,
} from './size.js'
import { params } from './launch-params.js'
// The quote asset this coin will trade against for the rest of its life. It is
// a constructor immutable on the curve — there is no setter and no owner call
// that can change it later.
const pairToken = STOCKS.TENCENT
// Never assume. The owner can withdraw an asset at any time, and launching
// against a withdrawn one spends the launch fee on a revert.
const approved = await publicClient.readContract({
address: size.factory,
abi: factoryAbi,
functionName: 'approvedPairTokens',
args: [pairToken],
})
if (!approved) throw new Error(`${pairToken} is not an approved quote asset`)
// Both figures are denominated in the quote asset, not in OKB, and they are
// re-pegged on chain as the stock moves. Read them rather than hardcoding.
const [phantomQuote, graduationThreshold, decimals] = await publicClient.readContract({
address: size.factory,
abi: factoryAbi,
functionName: 'pairTokenEconomics',
args: [pairToken],
})
console.log({ phantomQuote, graduationThreshold, decimals })
// What you want to spend on your own coin, in the quote asset — so this is
// wTCENTx, not OKB.
const quoteIn = parseUnits('2', decimals)
const launchFee = await publicClient.readContract({
address: size.factory,
abi: factoryAbi,
functionName: 'launchFee',
})
// The two things that differ from an OKB launch, and the two that catch people
// out. LaunchAndBuy pulls the quote asset with transferFrom, so it needs an
// allowance; and the call carries the launch fee ALONE as value, because the
// buy is no longer denominated in the chain's own token. Sending
// `launchFee + quoteIn` here reverts with NativeValueMismatch.
const { request: approval } = await publicClient.simulateContract({
address: pairToken,
abi: erc20Abi,
functionName: 'approve',
args: [size.launchAndBuy, quoteIn],
account,
})
await publicClient.waitForTransactionReceipt({
hash: await walletClient.writeContract(approval),
})
const { request, result } = await publicClient.simulateContract({
address: size.launchAndBuy,
abi: launchAndBuyAbi,
functionName: 'launchAndBuy',
args: [
{ ...params, creatorFeeRecipient: account.address },
LAUNCH_CONFIG_ID,
pairToken,
quoteIn,
0n, // minTokensOut — set a real floor in production
account.address, // who receives the opening buy
[], // extra addresses exempt from the snipe tax
],
value: launchFee,
account,
})
const [token, curve, tokensOut] = result
console.log({ token, curve, tokensOut })
const receipt = await publicClient.waitForTransactionReceipt({
hash: await walletClient.writeContract(request),
})
const [launched] = parseEventLogs({
abi: factoryAbi,
eventName: 'TokenLaunched',
logs: receipt.logs,
})
// pairToken comes back on the event, so an indexer never has to guess what a
// coin's figures are denominated in.
console.log(launched.args)
Read approvedPairTokens before you rely on an asset: the owner can
withdraw one, and launching against a withdrawn asset spends the launch fee on a revert.
Read pairTokenEconomics rather than hardcoding the opening and graduation
figures — they are denominated in the quote asset's own decimals and are re-pegged on
chain as the stock moves.
Addresses#
The wrappers, on X Layer:
| Asset | Address |
|---|---|
| wTCENTx | 0x41333Df9E7639188BBfca5522dC4844398Af9f9E |
| wSHEINx | 0xff637d2d435D6745Df3faf61272B1216e7e8b727 |
| wHKEXCx | 0xDFc060b4dE44Fb88998b695aA59169643DED10ea |
| wKUAIx | 0x096369B9b197bCbF669a3bC827Aa119d80d891E4 |
| wMEITx | 0xad1b65C8556957cf23d1B5e9accdc449b415fA97 |
| wMIXUx | 0x1Bac76a12d8EccA6dBF4B0A146Da8870d50F04c9 |
Approval is a mapping on each factory with no enumeration, so this list is what has
been approved rather than something readable in one call. Check any address with
approvedPairTokens(address) on the curve factory, or read the seeded
launcher's getLaunchConfig(id) — one config per asset, and a disabled one
disappears from the launch form without a deploy.