§ 05 · For builders

Contracts

This launchpad runs on Monad mainnet, chain ID 143. These are its contracts; each links to MonadScan. Any other address presented as one of these is not. Every one is source-verified on Sourcify with an exact match, readable on MonadVision; MonadScan verification is to follow.

Read 00% · 0% lit

Buying with MON: PairZap

A coin here trades against another coin, so someone holding only MON has two trades to make. PairZap makes them as one transaction: an aggregator's route between MON and the pair asset (KyberSwap's router on Monad, 0x6131B5fae19EA4f9D964eAc0408E4408b66337b5, fixed at deployment), then the coin's own Uniswap V3 pool. You sign a single minimum that bounds both; if either leg falls short the whole transaction reverts and you keep what you had.

It has no owner and no settings, holds nothing between trades, and keeps no allowance standing. It is a convenience, not a gate: the pool is an ordinary Uniswap V3 pool, and anything that can trade one can trade your coin without it. It has not been audited.

Your coin's own contract

Every coin launched here is a PairToken, and every one of them is verified without the creator doing anything. That is not a courtesy — PairToken takes no constructor arguments (it calls back into the launchpad for its name, symbol and supply), so the creation bytecode is byte-identical every time, and one compiled source verifies them all. The site submits each new coin to Sourcify within about ten minutes of its launch.

There is nothing to renounce. A PairToken has no owner at all — not one that was renounced, one that never existed — so no address holds any power over it.

What that verified source says, and what it therefore cannot do: fixed supply set once in the constructor, no mint function, no transfer tax, no blacklist, no pause, no owner.

External contracts it uses

Every one of these was read off Monad before it was written down — the factories through their own interface, the tokens by symbol and decimals, Uniswap V3's QuoterV2 by asking it for its factory(), and Uniswap V4's PoolManager through the helpers that answer poolManager() with it.

Uniswap V3 factory (launch venue — every launch creates its pool here; also measured)0x204FAca1764B154221e35c0d20aBb3c525710498
Uniswap V3 QuoterV2 (prices the trade panel; simulated, never sent)0x661E93cca42AfacB172121EF892830cA3b70F08d
Uniswap V4 PoolManager (measurement only)0x188d586Ddcf52439676Ca21A244753fA19F9Ea8e
PancakeSwap V3 factory (measurement only)0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865
Uniswap V2 factory (measurement only)0x182a927119D56008d921126764bF884221b10f59
PancakeSwap V2 factory (measurement only)0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E
WMON, the wrapped gas token0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A
Chainlink MON/USD0xBcD78f76005B7515837af6b50c7C52BCf73822fb
Chainlink WBTC/USD0x2D1Df1bD061AAc38C22407AD69d69bCC3C62edBD
Chainlink cbBTC/USD0x3dDc1bAE752aaEe31b577bF844c799C349A1d6BD
Chainlink ETH/USD0x1B1414782B859871781bA3E4B0979b9ca57A0A04
KyberSwap MetaAggregationRouterV2 (the zap's router; a launch's first router)0x6131B5fae19EA4f9D964eAc0408E4408b66337b5
LI.FI diamond (a launch's fallback router)0x026F252016A7C47CDEf1F05a3Fc9E20C92a49C37

Calls worth knowing

Before launching

// Non-reverting. Returns whether it would be allowed, and why not if not.
registry.status(address quote)
  returns (bool eligible, Decision decision, Report report)

// The bar this particular asset has to clear — $10,000 if listed, $25,000 if not.
registry.requiredDepthUsdE8(address quote) returns (uint256)

Launching

launchpad.launch(LaunchConfig cfg) payable returns (address token, bytes32 poolId)
// The same launch with its first buy paid in MON, whatever the pair asset: msg.value is the fee plus
// the MON to spend; `route` is an aggregator's calldata for `router` (one of isRouter), delivering
// the pair asset to the launchpad. Against MON itself the MON is wrapped and router/route are unused.
launchpad.launchWithNative(LaunchConfig cfg, address router, bytes route) payable returns (address token, bytes32 poolId)
launchpad.isRouter(address router) returns (bool)
launchpad.predictToken(address creator, bytes32 salt) returns (address)
launchpad.launchFee() returns (uint256)

LaunchConfig carries, beyond the obvious:

fieldwhat it does
lpFee / tickSpacinga Uniswap V3 fee tier inside minLpFee..maxLpFee — 10000 (1%) or 3000 (0.3%) — and the spacing the factory fixes for it, 200 or 60; both ticks must be multiples of it
creatorBpsshare of supply kept back for you, capped at 20%
feeRoute0 keeps your fees, 1 buys the coin back and burns it, 2 pays your holders
feeRecipientzero means the launching wallet
devBuyQuotepair-asset amount spent buying your own coin as the pool's first trade; needs an approval to the launchpad first
devBuyMinOutleast you will accept from that buy — nobody can front-run it, so this guards against you and the pool disagreeing on the opening price

After launching

// Anyone can call. Proceeds only ever reach the recorded recipient, the sink and the treasury.
feeVault.collect(address token)

// Creator only. Both take effect from the next collect.
feeVault.setFeeRoute(address token, FeeRoute route)
feeVault.setFeeRecipient(address token, address recipient)

// Reads
launchpad.launchOf(address token)                              // a public mapping: an unnamed tuple
feeVault.launchOf(address token) returns (Launch)              // includes the pool address
feeVault.positionOf(address token) returns (liquidity, owed0, owed1)
feeVault.feeRouteOf(address token) returns (FeeRoute)
feeVault.feeRecipientOf(address token) returns (address)
feeVault.owed(address token, address who) returns (uint256)    // a payout that could not be pushed
feeVault.claim(address token)                                  // collect one

Where the liquidity lock actually lives

There is no lock contract and no locked LP token. A Uniswap V3 position only becomes an NFT when Uniswap's position manager wraps it; underneath it is a slot in the pool keyed by (owner, tickLower, tickUpper), and the fee vault minted into that slot directly. The usual "liquidity locked" detectors look for LP tokens or position NFTs sent to a burn address or a locker, and here there is nothing of the sort for them to find.

What holds instead is a property of FeeVault, and with its source published you can check it rather than believe it: no code path in the vault ever calls burn with a non-zero amount. Collecting fees calls burn with exactly zero — which only moves earned fees into the position's tokensOwed — and then collect. There is no withdraw, no emergency exit, and no owner function that adds one. Anyone can read the position with pool.positions(keccak256(abi.encodePacked(feeVault, tickLower, tickUpper))). The float cannot come back out — not by the creator, not by us.

Owner powers

The owner can retune the depth bars, the fee bounds, the launch fee, the treasury, the buyback sink, the curated list, the gates and their parameters. It cannot touch a launch's liquidity, change an existing launch's creator share, or redirect a creator's fees.

Ownership transfer is two-step everywhere: a handover that is never accepted leaves the current owner in place rather than sending the protocol to a wrong address.

The owner should be a multisig behind a timelock, and the contracts do not enforce that themselves. On Monad it is currently a single wallet, 0x415f19DFA79cE70449EcF6854f9bb4540812454e.

None of this has been audited.