The code examples on this page use a
bondingCurve contract instance for price quotes. Get its address from MemeFactory.bondingCurve(). See Contract Overview for details.Buy Tokens
Send KAS toMemeFactory.buy() to receive tokens.
function buy(address token, uint256 minTokensOut) external payable;
| Parameter | Description |
|---|---|
token | Token contract address |
minTokensOut | Minimum tokens to receive (slippage protection) |
msg.value | Amount of KAS to spend (wei) |
const kasAmount = ethers.parseEther("100"); // 100 KAS
// 1. Get quote first
const tokensOut = await bondingCurve.calculateBuyReturnWithParams(
kasAmount, tokenReserves, kasReserves, vToken, vKas
);
// 2. Apply slippage (e.g., 20%)
const minTokensOut = tokensOut * 80n / 100n;
// 3. Execute buy
const tx = await factory.buy(tokenAddress, minTokensOut, {
value: kasAmount,
});
await tx.wait();
Buy Event
event Buy(
address indexed token,
address indexed buyer,
uint256 kasAmount,
uint256 tokenAmount,
uint256 fee
);
Sell Tokens
Sell tokens back for KAS viaMemeFactory.sell().
function sell(address token, uint256 tokenAmount, uint256 minKasOut) external;
| Parameter | Description |
|---|---|
token | Token contract address |
tokenAmount | Amount of tokens to sell (wei) |
minKasOut | Minimum KAS to receive (slippage protection) |
Before selling, you must approve the MemeFactory contract to spend your tokens.
const tokenAmount = ethers.parseEther("1000000"); // 1M tokens
// 1. Approve MemeFactory to spend tokens
const tokenContract = new ethers.Contract(tokenAddress, [
"function approve(address spender, uint256 amount) returns (bool)",
], signer);
const approveTx = await tokenContract.approve(FACTORY_ADDRESS, tokenAmount);
await approveTx.wait();
// 2. Get quote
const kasOut = await bondingCurve.calculateSellReturnWithParams(
tokenAmount, tokenReserves, kasReserves, vToken, vKas
);
// 3. Apply slippage (e.g., 20%)
const minKasOut = kasOut * 80n / 100n;
// 4. Execute sell
const tx = await factory.sell(tokenAddress, tokenAmount, minKasOut);
await tx.wait();
Sell Event
event Sell(
address indexed token,
address indexed seller,
uint256 tokenAmount,
uint256 kasAmount,
uint256 fee
);
Slippage Protection
Always setminTokensOut (buy) or minKasOut (sell) to protect against price changes between quoting and execution.
| Slippage | Multiplier | Use Case |
|---|---|---|
| 5% | quote * 95 / 100 | Low volatility |
| 20% | quote * 80 / 100 | Normal (recommended) |
| 50% | quote * 50 / 100 | High volatility / large orders |
KasFun website uses 20% default slippage. For programmatic trading, adjust based on the token’s volatility and your order size relative to pool reserves.
Complete Trading Flow
import { ethers } from "ethers";
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const FACTORY = "0x..."; // MemeFactory Contract Address
const factory = new ethers.Contract(FACTORY, [
"function buy(address token, uint256 minTokensOut) payable",
"function sell(address token, uint256 tokenAmount, uint256 minKasOut)",
"function getTokenInfo(address token) view returns (tuple(uint256 tokenId, address creator, address pool, uint256 tokenReserves, uint256 kasReserves, uint256 createdAt, bool fulfilled, bool graduated, string metadataUri, uint256 paramVersion))",
"function getTokenParamVersion(address token) view returns (tuple(uint256 graduationThreshold, uint256 virtualToken, uint256 virtualKas, uint160 sqrtPriceX96Token0, uint160 sqrtPriceX96Token1, bool active))",
"function bondingCurve() view returns (address)",
], signer);
// Get BondingCurve address
const bcAddress = await factory.bondingCurve();
const bc = new ethers.Contract(bcAddress, [
"function calculateBuyReturnWithParams(uint256,uint256,uint256,uint256,uint256) pure returns (uint256)",
"function calculateSellReturnWithParams(uint256,uint256,uint256,uint256,uint256) pure returns (uint256)",
], provider);
const TOKEN = "0x..."; // your token address
// Read current state
const info = await factory.getTokenInfo(TOKEN);
const params = await factory.getTokenParamVersion(TOKEN);
// --- BUY ---
const kasIn = ethers.parseEther("100");
const buyReturn = await bc.calculateBuyReturnWithParams(
kasIn,
info.tokenReserves,
info.kasReserves,
params.virtualToken,
params.virtualKas
);
const minTokens = buyReturn * 80n / 100n; // 20% slippage
const buyTx = await factory.buy(TOKEN, minTokens, { value: kasIn });
await buyTx.wait();
// --- SELL ---
const tokensIn = ethers.parseEther("500000");
const sellReturn = await bc.calculateSellReturnWithParams(
tokensIn,
info.tokenReserves,
info.kasReserves,
params.virtualToken,
params.virtualKas
);
const minKas = sellReturn * 80n / 100n; // 20% slippage
// Approve first
const token = new ethers.Contract(TOKEN, [
"function approve(address,uint256) returns (bool)",
], signer);
await (await token.approve(FACTORY, tokensIn)).wait();
const sellTx = await factory.sell(TOKEN, tokensIn, minKas);
await sellTx.wait();
Bonding curve trading is only available when the token is not yet fulfilled (
info.fulfilled === false). Once fulfilled, buy/sell will revert.