Buy and sell
Exact-in buys and sells through the launchpad, plus quoter eth_call examples.
Trading always goes through MintFastLaunchpad against the coin's Uniswap v4 pool. The hook takes 2% of the ETH side on the way through.
Buy (ETH in, tokens out)
function buy(
address token,
uint256 minTokensOut,
uint256 deadline
) external payable returns (uint256 tokensOut);msg.valueis the exact ETH you offer (fee comes out of this path via the hook)- unused ETH on a partial fill is refunded
deadlineis a unix timestamp, tx reverts if mined laterminTokensOutis your slippage floor
await walletClient.writeContract({
address: launchpad,
abi: launchpadAbi,
functionName: "buy",
args: [token, minTokensOut, BigInt(Math.floor(Date.now() / 1000) + 120)],
value: parseEther("0.1"),
})Sell (tokens in, ETH out)
function sell(
address token,
uint256 tokenAmount,
uint256 minEthOut,
uint256 deadline
) external returns (uint256 ethOut);You must approve the launchpad (or use permit) for tokenAmount first. Unsolds on a partial fill are returned. ETH proceeds are paid to msg.sender.
await walletClient.writeContract({
address: token,
abi: erc20Abi,
functionName: "approve",
args: [launchpad, tokenAmount],
})
await walletClient.writeContract({
address: launchpad,
abi: launchpadAbi,
functionName: "sell",
args: [
token,
tokenAmount,
minEthOut,
BigInt(Math.floor(Date.now() / 1000) + 120),
],
})Quote before you trade
MintFastQuoter simulates a swap inside a PoolManager unlock and reverts with the deltas. You must call it via eth_call (or viem simulateContract / a custom decoder). Nothing settles.
function quoteBuy(address token, uint256 ethIn)
external returns (uint256 ethUsed, uint256 tokensOut);
function quoteSell(address token, uint256 tokenIn)
external returns (uint256 tokenUsed, uint256 ethOut);Returned amounts already net the 2% hook fee. If ethUsed < ethIn (or tokenUsed < tokenIn), the quote would only partially fill the locked range.
viem sketch
import { decodeErrorResult } from "viem"
const quoterAbi = [
{
type: "function",
name: "quoteBuy",
stateMutability: "nonpayable",
inputs: [
{ name: "token", type: "address" },
{ name: "ethIn", type: "uint256" },
],
outputs: [
{ name: "ethUsed", type: "uint256" },
{ name: "tokensOut", type: "uint256" },
],
},
] as const
try {
await publicClient.simulateContract({
address: quoter,
abi: quoterAbi,
functionName: "quoteBuy",
args: [token, parseEther("0.1")],
})
} catch (err) {
// Depending on RPC / viem version, decode the QuoteResult revert
// or read the structured return if your client surfaces it.
console.error(err)
}The quoter always reverts with a QuoteResult carrier on success. Your client should simulate the call, decode that revert, then set minTokensOut / minEthOut with a slippage buffer.
Spot price and market cap
function state(address token)
external view
returns (
TokenInfo info,
bytes32 poolId,
uint256 spotPriceWad // ETH per token, 1e18 scale
);Market cap in ETH:
marketCapEth ≈ spotPriceWad * 1e9 / 1e18(1e9 tokens of total supply, price in ETH per whole token.)
Common reverts
UnknownToken, ZeroAmount, DeadlineExpired, Slippage, PoolNotLive, TransferFailed (sell path if ETH payout rejects).