跳转到主要内容
BondingCurve 合约地址可通过 MemeFactory.bondingCurve() 获取。详见合约概览

恒定乘积公式

KasFun 使用恒定乘积 Bonding Curve(类似 Uniswap V2),并引入虚拟储备
(tokenReserves + virtualToken) * (kasReserves + virtualKas) = k
虚拟储备设定初始价格和曲线形状,无需种子流动性。

获取曲线参数

计算价格前,先获取代币的当前状态和曲线参数:
// 1. 当前储备
const info = await factory.getTokenInfo(tokenAddress);
const { tokenReserves, kasReserves } = info;

// 2. 虚拟参数
const params = await factory.getTokenParamVersion(tokenAddress);
const { virtualToken, virtualKas, graduationThreshold } = params;

价格计算函数

BondingCurve 合约提供三个纯计算函数:

计算买入收益

给定 KAS 数量,能得到多少代币?
function calculateBuyReturnWithParams(
    uint256 kasIn,
    uint256 tokenReserves,
    uint256 kasReserves,
    uint256 vToken,
    uint256 vKas
) pure returns (uint256 tokensOut)
const kasIn = ethers.parseEther("100"); // 100 KAS
const tokensOut = await bondingCurve.calculateBuyReturnWithParams(
  kasIn,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
console.log("可得代币:", ethers.formatEther(tokensOut));

计算卖出收益

卖出一定数量的代币,能得到多少 KAS?
function calculateSellReturnWithParams(
    uint256 tokensIn,
    uint256 tokenReserves,
    uint256 kasReserves,
    uint256 vToken,
    uint256 vKas
) pure returns (uint256 kasOut)
const tokensIn = ethers.parseEther("1000000"); // 100 万代币
const kasOut = await bondingCurve.calculateSellReturnWithParams(
  tokensIn,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
console.log("可得 KAS:", ethers.formatEther(kasOut));

计算买入成本

要得到指定数量的代币,需要花费多少 KAS?
function calculateBuyCostWithParams(
    uint256 tokensOut,
    uint256 tokenReserves,
    uint256 kasReserves,
    uint256 vToken,
    uint256 vKas
) pure returns (uint256 kasIn)
const desiredTokens = ethers.parseEther("1000000"); // 想要 100 万代币
const kasNeeded = await bondingCurve.calculateBuyCostWithParams(
  desiredTokens,
  info.tokenReserves,
  info.kasReserves,
  params.virtualToken,
  params.virtualKas
);
console.log("需要 KAS:", ethers.formatEther(kasNeeded));

当前价格

获取代币当前价格(每个代币对应的 KAS):
// 通过 MemeFactory(便捷方式)
const price = await factory.getCurrentPrice(tokenAddress);

// 通过 BondingCurve(从储备计算)
const price = await bondingCurve.getCurrentPrice(
  info.tokenReserves,
  info.kasReserves
);

console.log("价格:", ethers.formatEther(price), "KAS/token");

价格影响

对于大额交易,价格影响可能很大。通过比较有效价格和当前价格来计算:
const kasIn = ethers.parseEther("1000"); // 1000 KAS
const tokensOut = await bondingCurve.calculateBuyReturnWithParams(
  kasIn, tokenReserves, kasReserves, vToken, vKas
);

const effectivePrice = kasIn * BigInt(1e18) / tokensOut; // 每代币 KAS
const currentPrice = await factory.getCurrentPrice(tokenAddress);
const priceImpact = Number(effectivePrice - currentPrice) / Number(currentPrice) * 100;

console.log(`价格影响: ${priceImpact.toFixed(2)}%`);
kasIn 相对于 kasReserves 很小时,价格影响趋近于零,有效价格趋近于现货价格。

毕业阈值

每个代币的曲线参数中包含 graduationThreshold。当 kasReserves >= graduationThreshold 时,代币毕业:
const params = await factory.getTokenParamVersion(tokenAddress);
const info = await factory.getTokenInfo(tokenAddress);

const remaining = params.graduationThreshold - info.kasReserves;
console.log("距毕业还需:", ethers.formatEther(remaining), "KAS");