关于 pump-bonding-curve
面向 Pump 代币定价与 AMM 开发者的技能,用于实现和维护 bonding curve 计算。涵盖含手续费的买卖报价、市值、储备管理及曲线边界情况。
主要功能
- 01恒定乘积买卖报价
- 02手续费计算与费率分层
- 03市值计算
- 04虚拟与实际储备管理
- 05毕业曲线边界处理
适用场景
- 01计算 SOL 买入可得代币数量
- 02估算卖出代币所得 SOL
- 03处理曲线毕业后的报价
- 04按实际储备限制买入数量
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nirholas/ pump-fun-sdk --skill pump-bonding-curve安装后在 Claude Code 中输入/pump-bonding-curve确认已加载。
详细介绍
债券曲线 — 定价、报价与 AMM 数学
实现并维护为 Pump 代币定价提供支持的恒定乘积 AMM 债券曲线数学逻辑,包括买入/卖出报价、考虑手续费的计算、市值计算、储备管理,以及新建、活跃和已迁移曲线的边界情况处理。
背景
Pump 代币使用恒定乘积债券曲线($x \times y = k$)定价,其中 $x$ = 虚拟 SOL 储备,$y$ = 虚拟代币储备。债券曲线决定代币在毕业前阶段的价格。当市值达到阈值后,代币会“毕业”并迁移到 PumpAMM 池。
关键文件
src/bondingCurve.ts— 所有债券曲线数学函数(买入/卖出报价、市值)src/fees.ts— 手续费计算(基点、分级手续费、向上取整除法)src/state.ts—BondingCurve、Global、FeeConfig、FeeTier接口
恒定乘积公式
$$x \times y = k$$
买入(投入 SOL,获得代币): $$\text{tokensOut} = \frac{dx \times Y}{X + dx}$$
其中 $dx$ = SOL 输入量(扣除手续费后),$X$ = 虚拟 SOL 储备,$Y$ = 虚拟代币储备。
卖出(投入代币,获得 SOL): $$\text{solOut} = \frac{dy \times X}{Y + dy}$$
其中 $dy$ = 卖出的代币数量,$X$ = 虚拟 SOL 储备,$Y$ = 虚拟代币储备。
扣除手续费
在应用债券曲线公式之前,先从 SOL 数量中扣除手续费:
inputAmount = (amount - 1) * 10000 / (totalFeeBps + 10000)
扣除手续费之前的 - 1 是有意为之,用于处理舍入边界情况。
市值计算
$$\text{marketCap} = \frac{\text{virtualSolReserves} \times \text{mintSupply}}{\text{virtualTokenReserves}}$$
其中 mintSupply 默认为 ONE_BILLION_SUPPLY($1 \times 10^{15}$ — 6 位小数的 10 亿枚代币)。
手续费等级
存在 FeeConfig 时,手续费取决于市值。手续费等级按逆序遍历——从末尾开始,第一个满足 marketCapLamportsThreshold ≤ currentMarketCap 的等级即为选中等级。
interface FeeTier {
marketCapLamportsThreshold: BN;
fees: { lpFeeBps: BN; protocolFeeBps: BN; creatorFeeBps: BN };
}
向上取整除法
$$\text{ceilDiv}(a, b) = \frac{a + b - 1}{b}$$
function ceilDiv(a: BN, b: BN): BN {
return a.add(b).sub(new BN(1)).div(b);
}
虚拟储备与实际储备
| 储备类型 | 包含内容 | 用途 |
|---|---|---|
virtualSolReserves | 实际 SOL + 协议添加的虚拟偏移量 | AMM 公式计算 |
virtualTokenReserves | 实际代币 + 虚拟偏移量 | AMM 公式计算 |
realTokenReserves | 实际可用代币 | 买入输出上限 |
realSolReserves | 实际存入的 SOL | 提取限额 |
边界情况
| 情况 | 行为 |
|---|---|
| 数量为零 | 返回 BN(0) |
已迁移的曲线(complete === true,储备为零) | 返回 BN(0) |
| 债券曲线为 null | 通过 newBondingCurve(global) 创建一条新曲线 |
| 代币数量超过实际储备 | 限制为 realTokenReserves |
| 创建者手续费 | 仅当 bondingCurve.creator != PublicKey.default 或者这是新曲线时才收取 |
BondingCurve 状态
interface BondingCurve {
virtualTokenReserves: BN;
virtualSolReserves: BN;
realTokenReserves: BN;
realSolReserves: BN;
tokenTotalSupply: BN;
complete: boolean; // true = graduated to AMM
creator: PublicKey;
isMayhemMode: boolean;
}
应遵循的模式
- 所有数量都使用
BN(bn.js)进行任意精度整数运算——绝不使用 JavaScriptnumber - 手续费以基点为单位(1 bps = 0.01%,10,000 bps = 100%)
- 始终在应用 AMM 公式之前扣除手续费,而不是之后
- 使用向上取整除法(
ceilDiv)计算手续费,确保协议不会损失零头 - 报价函数是纯函数——不进行网络调用,没有副作用,不使用可变状态
- 构建交易指令之前,始终检查
bondingCurve.complete
常见问题
- 混淆虚拟储备(包含虚拟偏移量)与实际储备(实际数量)
- 报价时未考虑手续费——原始报价函数与考虑手续费的报价函数结果不同
- 尝试在已毕业的曲线(
complete === true)上交易会导致链上失败 - 手续费等级按逆序遍历——不是正序
- 市值计算使用
mintSupply,而不是tokenTotalSupply - 手续费扣除公式会先从数量中减去 1——这是有意为之
getBuySolAmountFromTokenAmountQuote会在结果上加+ 1,以确保 SOL 数量充足