Minted tokens
Microsales and Melt Pools each mint a fresh ERC20 at creation. Standard pools—presales, fair launches, and subscriptions—list a token supplied by the creator and are not covered here.
Token contracts
CheeseToken | CheeseTaxTokenV2 | |
|---|---|---|
TOKEN_TYPE() | 0 | 4 |
| Buy/sell tax | none | independent rates, each at most 10% |
| Minted by | createMicroSaleNoTaxToken, createBondingCurveNoTaxToken* | createMicroSaleTaxTokenV2, createMicroSaleTaxTokenWithVaultV2, createBondingCurveTaxTokenV2*, createBondingCurveTaxTokenWithVaultV2 |
| Revenue routing | — | fee receiver, holder dividends, burn, and liquidity |
TOKEN_TYPE() == 3 identifies a CheeseTaxToken. Use its dedicated ABI when reading a type-3
token; the create paths in the table above mint types 0 and 4.
Both tokens have:
- A fixed supply of
1,000,000,000tokens with 18 decimals. - Standard ERC20 reads, approvals, transfers, and
Transfer/Approvalevents. owner() == address(0)after launch. Ownership is renounced during initialization.- A
fundManagerbound to the microsale or Melt Pool that minted the token. - Pre-listing venue protection. Wallet-to-wallet transfers are allowed, while configured trading venues cannot be seeded before the official listing.
configurator is the launchpad address that initializes the token. For CheeseToken, it binds the
fund manager once. For CheeseTaxTokenV2, it also binds the fee receiver and revenue contracts and
can register additional taxed pools. It is not a token-owner wallet.
ABIs
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);
Download: CheeseToken.json · CheeseTaxToken.json · CheeseTaxTokenV2.json.
The Launchpad ABI is available at Launchpad.json. Current token source is
published in
cheesepad-ai/cheesepad-contracts.
Common token reads
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 | Type | Meaning |
|---|---|---|
name / symbol | string | values chosen at launch |
decimals | uint8 | always 18 |
totalSupply / TOTAL_SUPPLY | uint256 | always 1_000_000_000e18 |
TOKEN_TYPE | uint8 | 0 for CheeseToken, 3 for CheeseTaxToken, 4 for CheeseTaxTokenV2 |
owner | address | zero address after initialization |
configurator | address | launchpad that initialized and wired the token |
fundManager | address | microsale or Melt Pool handle |
tradingStarted | bool | whether the official DEX listing has started |
pair (CheeseToken) / PAIR (CheeseTaxTokenV2) | address | main token/quote pair |
Use TOKEN_TYPE() as the ABI discriminator. It is useful metadata, but it is not proof that a token
was minted by CheesePad; use the launchpad events described below for provenance.
CheeseToken
CheeseToken is the no-tax token. Its token-specific reads are intentionally small:
| Getter | Meaning |
|---|---|
DECIMALS | fixed decimal count, 18 |
pair | canonical token/quote pair |
tradingStarted | false until the official first liquidity seed |
isPreListingBlockedVenue(address) | whether an address is blocked as a pre-listing venue |
Before listing, normal wallet and launchpad custody transfers work, but transfers involving a
blocked trading venue revert. The official liquidity seed sets tradingStarted to true; ordinary
ERC20 behavior then applies everywhere.
CheeseTaxTokenV2
CheeseTaxTokenV2 has a four-stage lifecycle:
| State | Value | Meaning |
|---|---|---|
BondingCurve | 0 | pre-listing; no token-level DEX tax |
TaxEnforcedAntiFarmer | 1 | taxes buys and sells through every registered pool |
TaxEnforced | 2 | taxes buys and sells through mainPool |
TaxFree | 3 | tax window has ended |
The token starts at state 0 for both microsales and Melt Pools. The official DEX listing sets
tradingStarted, tradingStartedAt, and both expiration timestamps. For a Melt Pool, the launchpad
itself withholds creator tax from curve trades in the quote currency (see
the fee model); the token remains in state 0 until graduation.
Tax and lifecycle reads
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 | Meaning |
|---|---|
BUY_TAX_BPS / SELL_TAX_BPS | current per-side rates in BPS; each starts at no more than 1000 |
TAX_BPS | current maximum of the buy and sell rates |
TAX_DURATION | configured tax window in seconds after listing |
antiFarmerDuration | initial multi-pool tax window in seconds |
state() | current stored lifecycle state, 0–3 |
poolState() | state, current rates, liquidation threshold, and expiration timestamps |
allocation() | feeReceiver, holders, burn, and liquidity BPS; sum is 10000 |
FEE_RECEIVER | wallet or vault receiving its allocation slice |
QUOTE_TOKEN | asset used to settle tax revenue |
PAIR / mainPool | main listing pool |
isPool(address) | whether an address is a registered taxed pool |
isPreListingGuardedVenue(address) | whether a venue is blocked before listing |
taxProcessor | contract that swaps and routes collected tax |
dividendTracker | holder-dividend ledger; zero when the holder allocation is zero |
liquidationThreshold | current token amount that can trigger batched tax processing |
state() updates on transfers, so an idle token may retain its previous stored state after an
expiration timestamp. Use the timestamps in poolState() when displaying whether a window is open.
The next transfer advances the stored state and sets the current tax rates to zero when the tax
window has ended.
Revenue allocation
Collected tax is processed in batches and split by allocation():
feeReceiveris settled to the configured wallet or vault.holdersis distributed throughdividendTrackerin the quote token.burnis sent to the dead address.liquidityis paired and added as LP.
When a token has no eligible holder shares, processing reallocates the holder slice across the other
configured destinations. The token adjusts its liquidation threshold between
MIN_LIQ_THRESHOLD() and START_LIQ_THRESHOLD() based on processing results.
The fee model
A CheeseTaxTokenV2 has two fee layers worth keeping separate: the creator tax the launcher
configures, and the platform fee CheesePad charges on top.
Creator tax. You set BUY_TAX_BPS / SELL_TAX_BPS and an allocation() across
feeReceiver / holders / burn / liquidity. That is your revenue and your tokenomics — you choose
the rates and the split.
Platform fee. On top of the creator tax, CheesePad charges:
| Phase | Trade fee | Platform fee on the creator tax |
|---|---|---|
| Curve phase (Melt Pool, before graduation) | 1% of every buy and sell | an additional 10% platform fee on the creator tax |
| After graduation / listing | none | an additional 10% platform fee on the creator tax |
While a Melt Pool is on the curve, every trade pays the flat 1% trade fee, and CheesePad takes an
additional 10% platform fee on the creator tax the curve collects. Once the token graduates and lists
(or, for a microsale, from the moment it lists), the 1% trade fee no longer applies, but the 10%
platform fee on the creator tax continues for as long as the tax is live. A no-tax CheeseToken has no
creator tax, so it pays only the 1% fee while on the curve and nothing after listing.
The platform-fee rate is read from the launchpad's on-chain config (getPlatformCutBps() returns the
curve-phase and post-listing rates in BPS), so treat the 10% figures as the current schedule rather
than a hardcoded constant.
Detecting a CheesePad token
A token is platform-minted when it appears in a MicroSaleCreated or
BondingCurvePoolCreated event emitted by the CheesePad launchpad address. PoolCreated describes a
standard pool whose token was supplied by the creator, so exclude it when building a list of minted
tokens.
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.
}
For point lookups, the launchpad also exposes getMicroSaleByToken(token) and
getBondingCurvePoolByToken(token). Both return the complete launch record and reject an unknown
token.