The launchpad contracts
A launchpad on VYRE is an app. The launchpad contracts are ordinary contracts deployed on the chain like any app's: nothing about them is built into VYRE, and anyone can deploy their own launchpad alongside them (see Partner launchpads to use these contracts under your own brand). The launch contract (VyrePad on the testnet, VyrePadV2 on mainnet) launches a token in one transaction: anyone, any time, no approval or waiting. The token's whole supply goes into its own pool from the first block, and the pool's liquidity is locked forever. Trading is open to everyone, bots included.
Which network. Where an address appears on this page, the mainnet one is given first and the testnet's second. Send a call to the address of the network you are connected to: a testnet address has no contract on mainnet, so a transaction sent to it there is a plain transfer and the USDC sent with it is lost. The upload and metadata routes in the last section are written with the testnet's API host (https://testnet-api.vyrechain.com).
On mainnet: VyrePadV2
Mainnet's launch contract is VyrePadV2 (0x3B3f9098575a88E56a22b9e2f93ea40fA9340bC5). It makes launches the same way as the testnet's VyrePad, with a simpler fee rule:
| Fee | Size | Goes to |
|---|---|---|
| Creator's tax | 1–10%, set per side (buy and sell) at launch; it can be lowered, never raised and never below 1% | The creator, or up to 4 wallets they name, after the platform's share below |
| Platform's share | One tenth of the tax, taken when the tax is paid out | The platform wallet (platformWallet() on the pad) |
There is no other fee. A trade pays the creator's tax and nothing more: no extra platform fee on top of it, no partner fee, no promoter share and no early-buy fee (createLaunch fails with early-buy fee if the pool factory ever has one switched on). Both sides of the tax are paid in USDC (as WUSDC) and a sell's tax is taken out of the USDC it pays. For a trade of 1,000 USDC:
| Creator's tax | Trader pays | Creator gets | Platform gets |
|---|---|---|---|
| 1% | 10 USDC | 9 USDC | 1 USDC |
| 5% | 50 USDC | 45 USDC | 5 USDC |
| 10% | 100 USDC | 90 USDC | 10 USDC |
The platform's tenth is worked out when the tax is paid out (collectCreatorFees, which anyone can call), on the whole payout, rounded down to the smallest unit; the creator's side is the rest. The pad emits PlatformPaid(token, wallet, amount) for the tenth and CreatorFeesCollected(token, creator, amount) for the rest.
Launching on mainnet
Call createLaunch on VyrePadV2 (0x3B3f9098575a88E56a22b9e2f93ea40fA9340bC5) once the pad's owner has opened launches (launchesOpen() reads it). Any USDC sent with it is the creator's first buy, made in the same transaction before anyone else can trade. Every launch opens at the same market cap, $3,000 (OPENING_MARKET_CAP), and its liquidity is locked in the pool.
struct CreateParams {
string name; // 1-64 bytes
string symbol; // 1-16 bytes
uint256 totalSupply; // 18 decimals: 1,000 to 10^15 tokens
uint256 startingMarketCap; // exactly OPENING_MARKET_CAP, 3,000e18 ($3,000)
uint16 buyTaxBps; // 100-1000 (1% to 10%)
uint16 sellTaxBps; // 100-1000
string metadataURI; // up to 256 bytes: a link to a JSON file with the picture, description and links
}
function createLaunch(CreateParams calldata p) external payable returns (address token, address pool, uint256 bought);The creator's controls are the ones in The creator's controls below, with one difference: lowerTaxes never goes under 1% (MIN_TAX_BPS, 100). launches(token) returns the pool, the two taxes, the position's ticks, the creator and the creation time; there is no partner. The SDK's launch() checks these limits before sending.
Trading on mainnet
Trade through Uniswap's SwapRouter (0x38231F0fa2Bb09Fdb3fD783b110CB5B3a4d3Ad84). Pools use fee key 10000 and trade against WUSDC (0xf892e07468eE3cca58795C265de4DfAa3d3b04dc). multicall joins the steps in one transaction, so a trader sends and receives native USDC:
buy (send the USDC as the transaction's value)
multicall([
exactInputSingle({ tokenIn: WUSDC, tokenOut: token, fee: 10000, recipient, deadline,
amountIn: value, amountOutMinimum, sqrtPriceLimitX96: 0 }),
refundETH() // hands back any USDC the pool did not take
])
sell (approve the router for exactly amountIn, or start with selfPermit)
multicall([
selfPermit(token, amountIn, deadline, v, r, s), // optional: launch tokens support EIP-2612
exactInputSingle({ tokenIn: token, tokenOut: WUSDC, fee: 10000, recipient: address(0), deadline,
amountIn, amountOutMinimum, sqrtPriceLimitX96: 0 }), // address(0): the router receives it
unwrapWETH9(amountOutMinimum, recipient) // WUSDC to native USDC, to the recipient
])Price a trade first with QuoterV2 (0x92c33Bef4552fBAb7264A4Da1805743A295FC3FA): quoteExactInputSingle with WUSDC and the token, fee 10000. The quote already has the creator's tax taken out. Another trade can land between your quote and your transaction (bots are welcome here), so set a minimum a little below the quote (the SDK uses 2%). The SDK's buy and sell do all of this, simulated first.
Events to index on mainnet
| Contract | Event |
|---|---|
| VyrePadV2 | LaunchCreated(token, creator, pool, name, symbol, buyTaxBps, sellTaxBps, openingMarketCap, sqrtPriceX96, tickLower, tickUpper) |
| VyrePadV2 | FirstBuy(token, creator, usdcIn, tokensOut), LaunchMetadata(token, uri) |
| VyrePadV2 | PlatformPaid(token, wallet, amount), CreatorFeesCollected(token, creator, amount), TaxPaid(token, wallet, amount) |
| VyrePadV2 | TaxesLowered, TaxWalletsSet, CreatorOffered, CreatorChanged, LaunchesOpened, PlatformWalletOffered, PlatformWalletChanged |
| Each pool | Uniswap v3's Swap event (every trade, whichever router) |
VyrePadV2 also lists every launch: launchCount(), tokens(i) (oldest first), launches(token), metadataOf(token), taxWalletsOf(token), platformWallet().
The sections from Fees on describe the testnet's launch contract, VyrePad, which has a 1% platform fee, partner fees, promoters and an app router. On mainnet, the section above is the one that applies. Tax wallets, the metadata file and the pools' design work the same on both.
The pools are a copy of Uniswap v3 with a few changes: only the pad can add liquidity (no outside positions), every fee is paid in USDC (never in the launched token), buys and sells can carry different taxes, and there are no flash loans. They price trades exactly like Uniswap v3 (tested against Uniswap's own contracts, trade by trade).
The pad's owner can close and reopen new launches (setLaunchesOpen, event LaunchesOpened): while they are closed,
createLaunch fails with launches closed. Trading on launches that already exist is never affected.
Fees
Every fee is taken in USDC, from the USDC side of the trade: out of what a buyer pays, or out of what a seller
receives. Pools trade against WUSDC (USDC wrapped one to one, an ERC-20), so every payout below (the creator's tax, the promoter's
share, a partner's fee) arrives as WUSDC; withdraw(amount) on WUSDC (mainnet 0xf892e07468eE3cca58795C265de4DfAa3d3b04dc, testnet 0x3604b49523F950f832AA7d4Fa11Fdc3C0a541913) turns it back into USDC.
| Fee | Size | Goes to |
|---|---|---|
| Creator's tax | 0–10%, set per side (buy and sell), can only go down | The creator, or up to 4 wallets they name |
| Platform fee | 1% of every buy and sell | The platform treasury, run by the VYRE team (a promoter's share of it, below, when the trade came through the app router) |
| Partner fee | 0–1%, set at launch by whoever launches, and it cannot be lowered later | The wallet named as partner (a partner launchpad, or any address the launcher names) |
The contract does not check who the partner is: any launcher can name any address and a fee up to 1%, a creator's own wallet included. So, outside the early-buy window below, one token can charge up to 12% a side in all (10% creator tax, 1% platform fee, 1% partner fee). A buy in the first seconds of a pool made after the early-buy fee was added also pays it, up to 99% in all (the current testnet deployment has no such fee: see below). Read the pool's buyFee() and sellFee(), or the sum a token's page shows, and do not rely on the tax alone.
The early-buy fee
The current testnet deployment was made before this fee and does not have it: its factory has no launchFee(), its pools no launchFeeConfig(), and no buy there pays an early-buy fee. Newer deployments have it, and what follows describes them.
A buy in the first seconds after a token opens pays one more fee, on top of the fees above. It starts high and falls to nothing:
the platform sets a start level and a length when a pool is made (at most 99% and 10 seconds), and the pool keeps them for good.
At a start level of 99% over 3 seconds the fee, in basis points of what the buyer pays in, is up to 9,900 at the pool's first second,
618 in the next, 19 in the third and 0 after that (start >> floor(elapsed * 14 / length)). The early-buy fee and the buy fee
together are never more than 99%, so where the buy fee is 4% the first second's fee is 9,500, not 9,900.
- It comes out of what the buyer pays in, like the other buy fees, so a quote taken at the moment of the trade (QuoterV2, the SDK's
quoteBuy) already has it taken off, so a buy mined in the window never gets less than the quote said. The fee only falls, though: the same buy mined after the window gets many times the quote, so inside the window the quote is a floor and not a price, and a minimum set a little under it guards nothing against a price that moves. - All of it goes to the platform treasury. It is not shared with a promoter, a partner or the creator, and the creator's tax is unchanged.
- Sells never pay it. The creator's own first buy, made in the launch transaction, does not pay it either.
- The current fee:
launchFeeConfig()on the pool gives its start level, length and opening time packed in one word, andlaunchFeeBps(pool)on the pool factory gives what a buy sent now would pay. The SDK'sgetLaunchFee(client, token)does both and returnsnullfor a pool without one. A buy is charged at the time its block is made, a moment after it is sent, so a trade near the end of a step may pay the next, lower step. Withoutat,getLaunchFeeuses the later of the asking machine's clock and the chain's latest block, so a clock that runs behind the chain does not show "no fee" at the very start. - The platform can lower the start level and length for pools made later at any time, and raise them only with 7 days' notice
(
launchFee(),scheduledLaunchFee()on the factory). A pool made before a change keeps its own settings. - A pool made by a factory without this fee has none and never gets one: that is every pool on the current testnet.
- A bot that buys in the first seconds should read the fee, simulate the trade at the time it expects it to be mined, and set
amountOutMinimumfrom the price it will accept, not from a quote taken inside the window; a trade with no minimum can pay the whole start level. The SDK'sbuyrefuses its default minimum (the quote lessslippageBps) while the fee is running: passminTokensOut.
Launching
Call createLaunch on VyrePad (testnet 0x60A2E571f0272151a23Cd0d5EC814A67fBf9bf34). Any USDC sent with it is the creator's first buy, made in the same
transaction before anyone else can trade.
struct CreateParams {
string name; // 1-64 bytes
string symbol; // 1-16 bytes
uint256 totalSupply; // 18 decimals: 1,000 to 10^15 tokens
uint256 startingMarketCap; // in USDC, 18 decimals: exactly OPENING_MARKET_CAP, 3,000e18 ($3,000); the pool opens within about 1% of it
uint16 buyTaxBps; // 0-1000 (10%)
uint16 sellTaxBps; // 0-1000
address partner; // a partner launchpad, or address(0)
uint16 partnerFeeBps; // 0-100 (1%), only with a partner
string metadataURI; // up to 256 bytes: a link to a JSON file with the picture, description and links
}
function createLaunch(CreateParams calldata p) external payable returns (address token, address pool, uint256 bought);Every launch opens at the same market cap, $3,000: a rule of the contract (OPENING_MARKET_CAP), not of any page, so no app, script or partner launchpad can open one elsewhere. A call that names another value fails with market cap. A creator's choices are the supply (so the price of a token), the taxes and the first buy. (The current testnet deployment was made before this rule and still accepts other values; newer deployments enforce it.)
name and symbol are stored exactly as given, as raw bytes: the contract does not strip control, invisible or direction-changing characters (a NUL, a right-to-left override, a zero-width space), so two tokens can look alike on screen. An app that shows them should strip or escape those characters and show the contract address next to a name.
The caller becomes the creator. The SDK's launch() checks these limits before sending.
The creator's controls
| Call on VyrePad | What it does |
|---|---|
collectCreatorFees(token) | Pays out the tax collected so far, in WUSDC (anyone can call it; it pays the creator or the tax wallets) |
setTaxWallets(token, wallets, bps) | Splits the tax between up to 4 wallets (shares in basis points adding up to 10,000); tax earned so far is paid out first |
lowerTaxes(token, buyTaxBps, sellTaxBps) | Lowers either tax; they can never go up |
setMetadata(token, uri) | Changes the picture, description and links |
offerCreator(token, to) / acceptCreator(token, buyTaxBps, sellTaxBps) | Hands the creator role over in two steps (the new creator accepts at the taxes they expect) |
Tax wallets must be wallets their owners control. The pad refuses its own contracts, but it can't know every address where USDC would be lost: never name Uniswap's SwapRouter (anyone could take tax sent there), an app router, the pool deployer, or an address nobody holds the key to.
Trading
Through the app router (recommended for apps)
VyreAppRouter (testnet 0xbf593CB56983688FB279DDDA6f582A19cFAb38FD) trades with native USDC (no wrapping or approval to buy) and pays the trader's
promoter on the spot.
function buy(address token, uint256 amountOutMinimum, uint256 deadline, address recipient)
external payable returns (uint256 amountOut);
function sell(address token, uint256 amountIn, uint256 amountOutMinimum, uint256 deadline,
address recipient, bool unwrap) external returns (uint256 amountOut);
function sellWithPermit(address token, uint256 amountIn, uint256 amountOutMinimum, uint256 deadline,
address recipient, bool unwrap, uint256 permitDeadline, uint8 v, bytes32 r, bytes32 s)
external returns (uint256 amountOut);buyspends the USDC sent (msg.value);sellneeds an exact approval ofamountInto the router, or usesellWithPermit(launch tokens support EIP-2612 permits, so a sell is one transaction).- The router can charge an app fee on top, for the platform treasury: it's 0 today, and any change is announced on chain 7 days
ahead (
currentAppFeeBps(),nextAppFeeBps,nextAppFeeAt). - Price a trade first with QuoterV2 (mainnet
0x92c33Bef4552fBAb7264A4Da1805743A295FC3FA, testnet0x41A83F6CcCEC9FfE9ab28e82E5C92B16056d33f4):quoteExactInputSinglewith WUSDC and the token, fee 10000. Another trade can land between your quote and your transaction (bots are welcome here), so set a minimum a little below the quote (the SDK uses 2%).
Directly through Uniswap's router
The SwapRouter (mainnet 0x38231F0fa2Bb09Fdb3fD783b110CB5B3a4d3Ad84, testnet 0xF82D41955e7126bBBE158C43E48ef3e54D1606B6) works like Uniswap v3's: pools use fee key 10000 and trade against WUSDC
(mainnet 0xf892e07468eE3cca58795C265de4DfAa3d3b04dc, testnet 0x3604b49523F950f832AA7d4Fa11Fdc3C0a541913). Trades this way pay no promoter.
Promoters
A wallet can name the promoter who brought it, once, with setPromoter(promoter) on VyreReferrals
(testnet 0x818acB2F48CCBe090F41a2cb5c923186FAba04b7). When that wallet then trades through the app router, the promoter is paid 30% of the 1% platform fee of
that trade in the same transaction, in WUSDC. Promoters are paid only after they have signed up and been approved (terms, tax
forms, a sanctions check); for a wallet whose promoter is not approved, the share stays with the platform treasury. The promoter program is closed to new sign-ups (since October 9, 2026): promoters who were already approved keep their links and their share, and nobody new is approved. It was never available in the UK, the EU, Australia or Singapore.
App and bot builders can trade through the app router. A trade pays a promoter only when its wallet has named one who is approved.
Partner launchpads
Other launchpads can run on VyrePad under their own brand: launch with partner set to your payout address and
partnerFeeBps up to 100 (1%). Your fee is added on top of the creator's tax and the 1% platform fee (it never comes out of
either) and paid to you in WUSDC by VyreFeeSplitter when the fees are collected (anyone can trigger the collection; see Run your own launchpad) (testnet 0xcd874cEDA1A51ed7F18b2358F6A399aD81f9BCd5). No sign-up or approval is needed.
Events to index
| Contract | Event |
|---|---|
| VyrePad | LaunchCreated(token, creator, pool, name, symbol, buyTaxBps, sellTaxBps, openingMarketCap, sqrtPriceX96, tickLower, tickUpper) |
| VyrePad | FirstBuy(token, creator, usdcIn, tokensOut), LaunchMetadata(token, uri), LaunchPartner(token, partner, partnerFeeBps) |
| VyrePad | TaxesLowered, TaxWalletsSet, TaxPaid, CreatorFeesCollected, CreatorOffered, CreatorChanged |
| VyreAppRouter | Trade(trader, token, isBuy, usdc, tokens, appFee, promoter, promoterReward) |
| VyreReferrals | Referred(trader, promoter) |
| Each pool | Uniswap v3's Swap event (every trade, whichever router), and LaunchFee(feeBps, amount) on a buy that paid the early-buy fee |
| VyreFeeSplitter | LaunchFeesPaid(pool, amount) when a pool's early-buy fees are paid to the platform treasury |
VyrePad also lists every launch: launchCount(), tokens(i) (oldest first), launches(token), metadataOf(token),
partnerOf(token), taxWalletsOf(token).
The metadata file
metadataURI points to a small JSON file (IPFS, Arweave or any HTTPS URL). A launchpad app saves it for the creator, and the picture they choose from their device with it: the app crops it to a square, shrinks it and uploads it. Builders can do the same with VYRE's API: POST https://testnet-api.vyrechain.com/image with the picture's bytes (a still PNG, JPEG or WebP, up to 400 KB, 16 to 1,024 px a side, sent with its own Content-Type) answers { "uri": "https://testnet-api.vyrechain.com/i/<hash>.webp" }, and that address goes in the file's image. Pictures are stored by the hash of their contents (the same bytes always give the same address), served for any site to show, and limited per caller an hour. Browsers may upload only from the launchpad apps' own pages; scripts and servers may upload from anywhere within the limits. Anything that isn't a well-formed still PNG, JPEG or WebP is refused (what a valid picture carries inside isn't inspected; it is served only as an image). The file itself can be saved the same way: POST https://testnet-api.vyrechain.com/metadata with the JSON below (sent as application/json, 4 KB at most, plain text only) answers { "uri": "https://testnet-api.vyrechain.com/m/<hash>.json" }, the metadataURI to launch with; browsers may save one only from the launchpad apps' own pages, scripts and servers from anywhere within the limits. A file saved there names only a picture uploaded there: its image must be exactly the uri that /image answered, still stored (any other picture link, another site's or ipfs://, is refused); a file you host yourself may name any picture. Pictures are stored for launches on this chain: one stays while a launch on VyrePad points to a file saved here that names it, and a picture no launch uses within 6 hours of its upload is removed, so upload it when you launch (sending the same picture again more than an hour later starts its 6 hours over). A picture named only by a file you host yourself isn't seen and goes too: host both, or neither. The store has a size limit, and a picture can be removed (taken down) at any time, so a link may stop working: keep your own copy.
The file itself (image is the address /image answered; in a file you host yourself, any picture's address):
{
"image": "https://testnet-api.vyrechain.com/i/<hash>.webp",
"description": "What the token is about.",
"links": { "website": "https://example.com", "x": "https://x.com/example", "telegram": "https://t.me/example" }
}