已铸造的代币
Microsales 和 Melt Pools 各自在创建时铸造一个全新的 ERC20。标准 pools——presale、fair launch 和 subscription——上线的是由创建者提供的代币,本页不作介绍。
代币合约
CheeseToken | CheeseTaxTokenV2 | |
|---|---|---|
TOKEN_TYPE() | 0 | 4 |
| 买入/卖出 tax | 无 | 各自独立的费率,每一侧最多 10% |
| 铸造者 | createMicroSaleNoTaxToken, createBondingCurveNoTaxToken* | createMicroSaleTaxTokenV2, createMicroSaleTaxTokenWithVaultV2, createBondingCurveTaxTokenV2*, createBondingCurveTaxTokenWithVaultV2 |
| 收入路由 | — | fee receiver、持有者分红、销毁与流动性 |
TOKEN_TYPE() == 3 标识一个 CheeseTaxToken。读取 type-3 代币时请使用它专属的 ABI;上表中的
创建路径铸造的是 type 0 和 4。
两种代币都具备:
- 固定供应量
1,000,000,000个代币,18 位小数。 - 标准的 ERC20 读取、approve、transfer,以及
Transfer/Approval事件。 - 上线后
owner() == address(0)。所有权在初始化期间被放弃。 - 一个
fundManager,绑定到铸造该代币的 microsale 或 Melt Pool。 - 上线前的交易场所保护。允许钱包到钱包的转账,但在官方上线之前,已配置的交易场所无法被 注入流动性。
configurator 是初始化该代币的 launchpad 地址。对于 CheeseToken,它只绑定一次 fund
manager。对于 CheeseTaxTokenV2,它还会绑定 fee receiver 和收入合约,并可以注册额外的
收税池。它不是一个代币所有者钱包。
ABI
import { ethers } from "ethers";
import CheeseTokenABI from "./abi/CheeseToken.json";
import CheeseTaxTokenABI from "./abi/CheeseTaxToken.json";
import CheeseTaxTokenV2ABI from "./abi/CheeseTaxTokenV2.json";
const tokenType = await new ethers.Contract(
TOKEN_ADDRESS,
["function TOKEN_TYPE() view returns (uint8)"],
provider,
).TOKEN_TYPE();
const abi =
tokenType === 0n
? CheeseTokenABI
: tokenType === 3n
? CheeseTaxTokenABI
: tokenType === 4n
? CheeseTaxTokenV2ABI
: undefined;
if (!abi) throw new Error(`Unsupported CheesePad token type: ${tokenType}`);
const token = new ethers.Contract(TOKEN_ADDRESS, abi, provider);
下载:CheeseToken.json · CheeseTaxToken.json · CheeseTaxTokenV2.json。
Launchpad ABI 位于 Launchpad.json。当前的代币源码发布在
cheesepad-ai/cheesepad-contracts。
常见的代币读取
const [name, symbol, decimals, totalSupply, tokenType, listed, manager] = await Promise.all([
token.name(),
token.symbol(),
token.decimals(),
token.totalSupply(),
token.TOKEN_TYPE(),
token.tradingStarted(),
token.fundManager(),
]);
| Getter | 类型 | 含义 |
|---|---|---|
name / symbol | string | 上线时选择的值 |
decimals | uint8 | 始终为 18 |
totalSupply / TOTAL_SUPPLY | uint256 | 始终为 1_000_000_000e18 |
TOKEN_TYPE | uint8 | CheeseToken 为 0,CheeseTaxToken 为 3,CheeseTaxTokenV2 为 4 |
owner | address | 初始化后为零地址 |
configurator | address | 初始化并接线该代币的 launchpad |
fundManager | address | microsale 或 Melt Pool 句柄 |
tradingStarted | bool | 官方 DEX 上线是否已开始 |
pair (CheeseToken) / PAIR (CheeseTaxTokenV2) | address | 主 token/quote 交易对 |
使用 TOKEN_TYPE() 作为 ABI 判别符。它是有用的元数据,但并不能证明某个代币是由 CheesePad
铸造的;请使用下文描述的 launchpad 事件来确认来源。
CheeseToken
CheeseToken 是无税代币。它专属的读取方法刻意保持精简:
| Getter | 含义 |
|---|---|
DECIMALS | 固定小数位数,18 |
pair | 规范的 token/quote 交易对 |
tradingStarted | 在官方首次注入流动性之前为 false |
isPreListingBlockedVenue(address) | 某个地址是否作为上线前场所被阻止 |
上线之前,正常的钱包转账和 launchpad 托管转账均可进行,但涉及被阻止交易场所的转账会 revert。
官方注入流动性会把 tradingStarted 设为 true;此后普通的 ERC20 行为处处适用。
CheeseTaxTokenV2
CheeseTaxTokenV2 具有一个四阶段的生命周期:
| State | Value | Meaning |
|---|---|---|
BondingCurve | 0 | 上线前;没有代币层面的 DEX tax |
TaxEnforcedAntiFarmer | 1 | 对通过每一个已注册池的买入和卖出收税 |
TaxEnforced | 2 | 对通过 mainPool 的买入和卖出收税 |
TaxFree | 3 | tax 窗口已结束 |
无论是 microsale 还是 Melt Pool,代币都从 state 0 开始。官方 DEX 上线会设置 tradingStarted、
tradingStartedAt 以及两个到期时间戳。对于 Melt Pool,launchpad 自身会以 quote currency 从
曲线交易中扣留 creator tax(见费用模型);代币在毕业之前一直保持 state 0。
Tax 与生命周期读取
const [
buyBps,
sellBps,
duration,
antiFarmerDuration,
poolState,
allocation,
feeReceiver,
quoteToken,
] = await Promise.all([
token.BUY_TAX_BPS(),
token.SELL_TAX_BPS(),
token.TAX_DURATION(),
token.antiFarmerDuration(),
token.poolState(),
token.allocation(),
token.FEE_RECEIVER(),
token.QUOTE_TOKEN(),
]);
const now = BigInt(Math.floor(Date.now() / 1000));
const taxWindowOpen =
(await token.tradingStarted()) && now < poolState.taxExpirationTime;
const allRegisteredPoolsTaxed =
taxWindowOpen && now < poolState.antiFarmerExpirationTime;
| Getter | 含义 |
|---|---|
BUY_TAX_BPS / SELL_TAX_BPS | 当前每一侧的费率,单位 BPS;每一侧起始时都不超过 1000 |
TAX_BPS | 当前买入与卖出费率中的较大值 |
TAX_DURATION | 配置的 tax 窗口,单位为上线后的秒数 |
antiFarmerDuration | 初始的多池 tax 窗口,单位为秒 |
state() | 当前存储的生命周期状态,0–3 |
poolState() | 状态、当前费率、清算阈值以及到期时间戳 |
allocation() | feeReceiver、holders、burn 与 liquidity 的 BPS;之和为 10000 |
FEE_RECEIVER | 接收其 allocation 份额的钱包或 vault |
QUOTE_TOKEN | 用于结算 tax 收入的资产 |
PAIR / mainPool | 主上线池 |
isPool(address) | 某个地址是否为已注册的收税池 |
isPreListingGuardedVenue(address) | 某个场所在上线前是否被阻止 |
taxProcessor | 对收集到的 tax 进行兑换并路由的合约 |
dividendTracker | 持有者分红账本;当持有者 allocation 为零时为零地址 |
liquidationThreshold | 当前可触发批量 tax 处理的代币数量 |
state() 在转账时更新,因此一个闲置的代币在过了到期时间戳之后可能仍保留其先前存储的状态。在
展示某个窗口是否开放时,请使用 poolState() 中的时间戳。下一次转账会推进存储的状态,并在
tax 窗口结束时把当前 tax 费率置为零。
收入分配
收集到的 tax 会分批处理,并按 allocation() 拆分:
feeReceiver结算到所配置的钱包或 vault。holders以 quote token 通过dividendTracker分发。burn发送到销毁地址。liquidity被配对并作为 LP 加入。
当一个代币没有符合条件的持有者份额时,处理过程会把持有者份额重新分配到其他已配置的去向上。
代币会根据处理结果,在 MIN_LIQ_THRESHOLD() 与 START_LIQ_THRESHOLD() 之间调整其清算阈值。
费用模型
CheeseTaxTokenV2 有两个值得分开看待的费用层:上线者配置的 creator tax,以及 CheesePad
在其之上收取的 平台费。
Creator tax。 你设置 BUY_TAX_BPS / SELL_TAX_BPS,以及一份在
feeReceiver / holders / burn / liquidity 之间的 allocation()。这是你的收入和你的
代币经济学——费率和拆分由你选择。
平台费。 在 creator tax 之上,CheesePad 收取:
| Phase | Trade fee | Platform fee on the creator tax |
|---|---|---|
| 曲线阶段(Melt Pool,毕业之前) | 每笔买入和卖出的 1% | 对 creator tax 额外 10% 的平台费 |
| 毕业 / 上线之后 | 无 | 对 creator tax 额外 10% 的平台费 |
当 Melt Pool 处于曲线阶段时,每笔交易都支付固定的 1% 交易手续费,并且 CheesePad 会对曲线
收集到的 creator tax 额外收取 10% 的平台费。一旦代币毕业并上线(对于 microsale,则从它上线的
那一刻起),1% 的交易手续费不再适用,但只要 tax 仍然生效,对 creator tax 的 10% 平台费就会
持续。无税的 CheeseToken 没有 creator tax,因此它在曲线阶段只支付 1% 手续费,上线之后不
支付任何费用。
平台费率读取自 launchpad 的链上配置(getPlatformCutBps() 以 BPS 返回曲线阶段和上线后的
费率),因此请把 10% 这些数字视为当前的费率表,而非硬编码的常量。
检测 CheesePad 代币
当一个代币出现在由 CheesePad launchpad 地址发出的 MicroSaleCreated 或
BondingCurvePoolCreated 事件中时,它就是平台铸造的。PoolCreated 描述的是一个由创建者提供
代币的标准 pool,因此在构建已铸造代币列表时应将其排除。
import LaunchpadABI from "./abi/Launchpad.json";
const launchpad = new ethers.Contract(LAUNCHPAD, LaunchpadABI, provider);
const [microsales, meltPools] = await Promise.all([
launchpad.queryFilter(launchpad.filters.MicroSaleCreated(), fromBlock, toBlock),
launchpad.queryFilter(launchpad.filters.BondingCurvePoolCreated(), fromBlock, toBlock),
]);
for (const event of [...microsales, ...meltPools]) {
const { token, fundManager } = event.args;
const launchStyle =
event.eventName === "MicroSaleCreated" ? "microsale" : "melt-pool";
// Persist token, fundManager, launchStyle, block number, and transaction hash.
}
对于单点查询,launchpad 还提供了 getMicroSaleByToken(token) 和
getBondingCurvePoolByToken(token)。两者都返回完整的上线记录,并拒绝未知代币。