rail docs

How rail works

Plain-language explanations of launching, trading, graduation and fees, followed by an integration reference for builders. Numbers on this page are read live from the deployed contracts.

What rail is

rail is a noncustodial token launchpad on Arc, Circle's USDC-native chain. Anyone can launch a token in one transaction. It trades on its own bonding curve until $10,000 has been raised, then graduates into a Uniswap v4 pool whose liquidity is locked forever.

  • USDC is everything. It pays gas on Arc, prices every token, and is the only currency fees are charged in. There is no second gas token to hold.
  • Your wallet signs everything. rail never holds your keys or your funds. Contracts move tokens only in the transactions you sign.
  • Launch terms are frozen. Once a token exists, its fees, recipient and curve can't be changed by anyone, including the rail team.
Supply per token1B
Opening market cap$4,000
Graduation market cap~$49,000
Trade fee1%

Showing default parameters; live values load from chain when available.

Getting started

Add the Arc network

Most wallets add the network automatically when you connect. To add it by hand:

FieldValue
Network nameArc
Chain ID5042
RPC URLhttps://railpad.io/api/rpc
Currency symbolUSDC
Block explorerhttps://arc-scan.org

Get USDC

You need USDC on Arc for gas and for buying. Your wallet may show the native balance with 18 decimals; rail reads the USDC token (6 decimals). It's the same balance, so you only ever see one USDC number.

What one-click trading does

Buying or selling needs permission for the rail contract to move your tokens. When you press Buy, rail picks the shortest route your wallet supports:

  1. Already approved: one transaction.
  2. Batching wallet (EIP-5792): approval and trade in one prompt.
  3. Permit (EIP-2612): you sign a free, off-chain message granting the exact amount, then send one transaction. USDC and every rail token support permits.
  4. Fallback: an approve transaction, then the trade, automatically.

The caption under the button tells you which route will be used. "Unlimited approval" (off by default) approves the maximum so later trades need a single prompt.

Launching a token

Create deploys the token and its bonding curve in one transaction. Every launch gets 1B tokens, all held by the curve. Here is every field.

Name, symbol, image, description

These are labels. They are not unique: anyone can launch another token called the same thing with the same picture. The contract address is the only identity that matters, so always check it before buying. Images are pinned to IPFS.

Creator tax

An extra percentage on every buy and sell, on top of the 1% trade fee, between 0% and 10%. The default is 1%. Where it goes depends on the buyback mode below. It is fixed forever at launch.

Buyback mode: Off, Burn or Holder rewards

ModeFee share + creator tax go toCreator earns
Off (default)The fee recipient, via the escrowFee share + tax
BurnBuying the token back from the market and burning itNothing
Holder rewardsHolders, paid in USDC, pro-rata to their balanceNothing

The mode (Burn or Holder rewards) is chosen at launch and never changes. You can launch with buyback off and turn it on later from your profile or the token page.

Turning buyback on is permanent
Once on, nobody, not you and not the rail owner, can turn it off. It permanently gives all creator earnings (fee share + creator tax) to burns or holders.

Fee recipient

The address that receives creator earnings. It defaults to your wallet and is permanent: there is no transfer and no takeover. Use an address you will control for the life of the token. While buyback is on it receives nothing.

Early-buy wallets

The first 5 seconds carry a steep snipe tax. You can list up to 32 wallets that skip it, for your own opening buys. You and the fee recipient are always exempt.

Opening buy

An optional amount of USDC to buy in the same transaction. It is atomic (nobody can buy before you) and untaxed by the snipe tax. Normal trade fees still apply.

Launch fee

Each launch costs 1 USDC, pulled together with the opening buy. It goes to the protocol.

The bonding curve

Think of the curve as a vending machine that holds every token and a pile of USDC. Put USDC in, get tokens out; put tokens back, get USDC out. The price is simply the ratio of what's inside, so there is always someone to trade with.

  • Starting price. The machine starts with a virtual $4,000 of USDC, so a new token opens at a $4,000 market cap. No real money sits behind the virtual part.
  • Buys raise the price, sells lower it. Every token bought leaves fewer inside, so the next one costs more.
  • You can always sell back until the curve sells out; the machine never runs out of the USDC buyers put in.
  • Size moves price. A large order walks up the curve and gets a worse average price than a small one.
  • Slippage is rate-based. Your minimum output is checked against the price you actually got, so a refunded remainder never trips it.
  • The finishing buy is clamped. If a buy would take more tokens than remain for sale, it gets exactly the rest and the unused USDC is refunded in the same transaction.

28.57% of supply is never sold on the curve: it is reserved for the pool at graduation. The curve sells out once $10,000 of real USDC has come in, at ~$49,000 market cap.

Snipe protection

Bots try to buy in the same block a token launches. To make that unprofitable, buys in the first 5 seconds pay a tax that starts at 99% and falls to a quarter each second. Sells are never snipe-taxed. The tax is added to the trade fee.

Seconds after launchSnipe tax
099% (9900 bps)
124.75% (2475 bps)
26.18% (618 bps)
31.54% (154 bps)
40.38% (38 bps)
5+0% (0 bps)

Exempt: the launcher, the fee recipient and up to 32 wallets listed at launch. The trade panel shows the live snipe tax when it applies.

Graduation

When the curve sells out ($10,000 raised), the token graduates in that same finishing buy:

  1. The raised USDC and the reserved 28.57% of supply are swept out of the curve.
  2. A Uniswap v4 pool is created at the curve's final price. Every graduated pool starts with the same $10,000 of USDC.
  3. The liquidity is minted as one full-range position owned by the locker contract, which has no withdraw function. It is locked forever.
  4. Reserved tokens not needed to match the price are burned.

If pool creation can't complete inside the finishing buy (for example, too little gas), the buy still succeeds and the launch waits in a "graduating" state. Anyone can retry, and the rail keeper retries automatically within seconds.

Rescue
If a launch has been stuck for 7 days, the owner can rescue it: the raised USDC is sent to a recipient chosen by the owner and the swept tokens are burned. The launch then never trades on a pool. This exists only for pathological failures.

Fees

Every trade pays a 1% base fee plus the token's creator tax (0–10%), plus the snipe tax in the first seconds.

Who gets what

ProtocolFee recipientBurns / holders
Buyback off30% of base fee70% of base fee + creator tax
Burn30% of base fee070% of base fee + creator tax buys & burns the token
Holder rewards30% of base fee070% of base fee + creator tax paid to holders in USDC

The snipe tax is added to the base fee and split the same way.

Rules

  • Same rate everywhere. The curve and the graduated pool charge identical rates, in every direction.
  • USDC only. Fees are always taken in USDC, never in the token.
  • Rounded up. Fee amounts round up to the next smallest unit, so the protocol never undercharges by rounding.
  • Pool trades fill completely or revert. If the pool can't take your whole input (price limit reached), the trade reverts and no fee is charged. Try a smaller amount.

Sweeping and claiming

Fees accrue on the curve or pool. A sweep splits them and deposits each share into the fee escrow. Sweeps that don't need a market buy (buyback off, or Holder rewards) are permissionless: anyone can press "Distribute fees". Burn-mode sweeps are run by the keeper.

Recipients claim from the escrow on their profile under Fees. Claimed funds go straight to the wallet.

Holder rewards

In Holder rewards mode, each sweep sends the fee share and tax to the token contract as USDC and credits every eligible holder pro-rata to their balance at that moment. Rewards already credited to you stay yours even if you sell afterwards. Claim anytime from the token page or your profile; there is no expiry.

Not eligible (their balances would dilute real holders): the zero and dead addresses, the token itself, its curve, the factory, the launch deployer, the locker, the v4 PoolManager, the hook, the fee escrow and the protocol fee router. These are fixed when the token is created. Third-party AMM pairs are not excluded.

Sweep cadence. Anyone can sweep; the keeper sweeps rewards launches when accrued rewards pass a threshold or age, keeping each payout small.

Why sniping a sweep doesn't pay
Buying just before a sweep and selling after costs at least 2 × (1% fee + creator tax) in a round trip. Because sweeps are frequent, the rewards paid in any one sweep are a tiny fraction of the token's market cap, far below that cost. The bound is economic, not absolute: a very large, rare sweep could in theory be worth front-running, which is why the keeper keeps them small.

If no eligible holders exist yet, the reward is carried forward to the next sweep, never paid to the creator.

Burn mode

In Burn mode the fee share and tax buy the token on the market and burn it, permanently reducing supply. Because a market buy can be sandwiched, only approved sweep operators (the rail keeper) can run these sweeps, with a minimum-output quote.

  • On the pool, each buyback is capped at 3% price impact.
  • Whatever can't be spent (impact cap reached, no liquidity) stays as pending buyback and is retried next sweep. It never goes back to the creator.
  • Buybacks on the curve pay no fee, and never buy the last tokens that would trigger graduation.

RAIL and protocol buy & burn

The protocol's share of fees goes to the ProtocolFeeRouter. When it claims from the escrow, 80% of each USDC amount enters a burn budget and 20% goes to the treasury. Operators spend the budget buying RAIL through the rail router, in impact-bounded chunks, and burn it.

RAIL is an ordinary rail launch made by the team. The owner can point the burn at a different launch at any time.

The only upgradeable contract
The fee router is upgradeable so treasury and burn mechanics can evolve. It never holds user funds or liquidity: only the protocol's own fee share. Every contract that touches traders, holders or locked liquidity is immutable.

Safety and trust

Immutable

  • Token contracts, bonding curves, the Uniswap v4 hook, the liquidity locker and the fee escrow (no proxies, no admin upgrade).
  • The terms of a live launch: supply, fee rate, creator tax, economics, snipe settings, buyback mode.
  • The fee recipient of every launch.
  • Buyback once enabled.

What the owner can do

  • Pause new launches or restrict them to a whitelist.
  • Set launch configs, pair-token economics, launch fee, max creator tax, snipe config and fee policy: these apply to future launches only.
  • Approve pair tokens and add or remove sweep operators.
  • Rescue a stuck graduation after 7 days.
  • Change ProtocolFeeRouter settings (burn share, treasury, operators, RAIL target) and upgrade it.

What nobody can do

  • Mint tokens, freeze or blacklist holders, or add transfer taxes.
  • Withdraw or move locked pool liquidity.
  • Change a live launch's fees, terms or fee recipient.
  • Turn buyback off.

Risk disclosures

  • Tokens are launched by anyone. Most go to zero. Nothing here is investment advice.
  • Names, tickers and images can be copied. Verify the contract address.
  • Smart contracts can contain bugs. The core is immutable, so a bug can't be patched in place.
  • Prices move fast, especially in the first minutes; slippage and the snipe tax can make early buys expensive.
  • Holder rewards and burns depend on trading volume and can be zero.
  • Arc, USDC, wallets and RPC providers are third-party dependencies outside rail's control.
  • Transactions are final.

FAQ

Why did my pool trade revert?

The pool couldn't fill your whole order within its price range (PartialFillNotSupported), or the price moved past your slippage. No fee was charged. Try a smaller amount or a higher slippage.

Why is the snipe tax on?

The token launched less than 5 seconds ago. Wait a few seconds and it drops to zero.

Why do I see a signature request?

That's a permit: a free, off-chain approval for the exact amount you're trading. It replaces a separate approve transaction. Decline it and click again to use a normal approval.

Where are my creator fees?

Fees sit on the curve or pool until swept, then in the escrow. Open your profile → Fees: press "Distribute fees" on your launch, then "Claim". With buyback on, creators earn nothing.

Why is my rewards balance 0?

The token isn't in Holder rewards mode, buyback is off, no sweep has happened since you bought, or your address is excluded (for example, you hold through a contract that's excluded).

What happens if graduation fails?

Your trade still settles. The launch waits as "graduating" while the keeper retries; anyone can retry too. After 7 days the owner can rescue it (USDC returned to a chosen recipient, tokens burned).

Integration

Contracts

Active network: Arc (chain id 5042). Launch tokens have 18 decimals; USDC has 6. ABIs are generated from the interfaces in contracts/src/interfaces.

ContractAddressRole
factory0xF2BBe838C15da206A33Ce2fE8AE833c858c431ADLaunches tokens, stores launch records and config, graduation and rescue
router0xe0BCAE6cA3b9d1c2626Ea6008B9B5cB098F29062Stateless trading entry point: routes buys/sells to curve or pool, quotes, permits
hook0xc3d1721Da76F075977a8FD098be4d542f3B720CCUniswap v4 hook: fees, pending fees/tax/buyback per pool, pool sweeps
escrow0x928D49FCb22f4a3c981421e02Deb0e2aA419eF51Holds swept fees per recipient until claimed
locker0xC11f5F57a750477bcE7b4461729667Be888067c7Owns graduated full-range positions forever (no withdraw)
deployer0xa0345861Dc8ef4C5FC41F7422cD13B089b099a98CREATE2 deployer for tokens and curves
feeRouter0x3e8886cad58218eD3985EF0A6921849860ccfA23ProtocolFeeRouter (UUPS proxy): claims protocol fees, RAIL buy & burn
poolManager0x8366a39CC670B4001A1121B8F6A443A643e40951Uniswap v4 PoolManager
usdc0x3600000000000000000000000000000000000000USDC (6 decimals)
stateView0xF3334192D15450CdD385c8B70e03f9A6bD9E673bUniswap v4 StateView

Launching programmatically

Pin the economics you expect with previewLaunchEconomics(configId, pairToken): if the owner changes the config or pair economics before your transaction lands, the launch reverts with LaunchEconomicsMismatch instead of launching on terms you didn't see.

launch.ts
import { parseUnits, toHex } from "viem";
import { factoryAbi } from "./abis";

const configId = 0n;
const expectedEconomics = await publicClient.readContract({
  address: FACTORY, abi: factoryAbi, functionName: "previewLaunchEconomics", args: [configId, USDC],
});

const params = {
  name: "Arc Rider", symbol: "RIDE", logo: "ipfs://…", description: "",
  socials: { twitter: "", telegram: "", discord: "", website: "", farcaster: "" },
  creatorFeeRecipient: account.address, // permanent
  creatorTaxBps: 100,                  // <= maxCreatorTaxBps (1000)
  buybackEnabled: false,
  buybackMode: 0,                      // 0 Burn, 1 HolderRewards (fixed forever)
  expectedEconomics,
  salt: toHex(crypto.getRandomValues(new Uint8Array(32))), // namespaced: keccak256(abi.encode(sender, salt))
};

const quoteIn = parseUnits("25", 6);  // optional atomic opening buy (0 for none)
const minTokensOut = 0n;              // rate-based; compute from the curve formulas below
const exemptions: `0x${string}`[] = []; // up to 32 early-buy wallets

// approve FACTORY for launchFee + quoteIn (same token), then:
const { request } = await publicClient.simulateContract({
  account, address: FACTORY, abi: factoryAbi, functionName: "launchToken",
  args: [params, configId, USDC, exemptions, quoteIn, minTokensOut],
});
const hash = await walletClient.writeContract(request);
// parse TokenLaunched(token, curve, deployer, …) from the receipt

launchTokenWithPermit(…, permit) takes an extra PermitData {value, deadline, v, r, s} for an EIP-2612 permit on launchFeeToken (owner = sender, spender = factory) covering launch fee + quoteIn. With quoteIn > 0 the pair token must equal the launch-fee token. The permit is try/catch'ed, so a front-run permit doesn't brick the call as long as the allowance exists.

permit.ts
const nonce = await publicClient.readContract({ address: USDC, abi: erc20PermitAbi, functionName: "nonces", args: [owner] });
const deadline = BigInt(Math.floor(Date.now() / 1000) + 1200);
const sig = await walletClient.signTypedData({
  account, primaryType: "Permit",
  domain: { name: "USDC", version: "2", chainId: 5042, verifyingContract: USDC }, // launch tokens: name = token name, version "1"
  types: { Permit: [
    { name: "owner", type: "address" }, { name: "spender", type: "address" },
    { name: "value", type: "uint256" }, { name: "nonce", type: "uint256" }, { name: "deadline", type: "uint256" },
  ] },
  message: { owner, spender: FACTORY, value, nonce, deadline },
});
const { v, r, s } = parseSignature(sig);
const permit = { value, deadline, v: Number(v), r, s };

The launcher and the fee recipient are always snipe-exempt, so the opening buy pays no snipe tax; it still pays the normal 1% fee + creator tax. exemptions add more early-buy wallets.

Trading

The router routes by factory phase: 0 → bonding curve, 2 → Uniswap v4 pool, anything else → NotTradable. It has no privileges and pulls the pair token (buys) or launch token (sells) from the caller.

solidity
function buy(address token, uint256 quoteIn, uint256 minTokensOut, address recipient, uint256 deadline) returns (uint256 tokensOut);
function sell(address token, uint256 tokensIn, uint256 minQuoteOut, address recipient, uint256 deadline) returns (uint256 quoteOut);
function buyWithPermit(address token, uint256 quoteIn, uint256 minTokensOut, address recipient, uint256 deadline, PermitData permit);
function sellWithPermit(address token, uint256 tokensIn, uint256 minQuoteOut, address recipient, uint256 deadline, PermitData permit);
  • Curve refunds (finishing buy clamp) are forwarded to the caller.
  • buyWithPermit permits the pair token; sellWithPermit permits the launch token (domain name = token name, version "1").
  • You may also call the curve directly while in phase 0: curve.buy(quoteIn, minTokensOut, recipient) / curve.sell(tokensIn, minQuoteOut, recipient) (approve the curve).

Quoting

router.quoteBuy(token, quoteIn, recipient)(tokensOut, spent) and router.quoteSell(token, tokensIn)quoteOut work in both phases. They are non-view (the pool path simulates a swap), so call them with eth_call / simulateContract.

Curve math, integer order is normative (BPS = 10,000; fees round up):

curve math
amountOut(in, rIn, rOut) = in * rOut / (rIn + in)
amountIn(out, rIn, rOut) = out * rIn / (rOut - out) + 1
sellable = tokenReserve - reservedTokens
reservedTokens = supply * phantom / (phantom + threshold)

// buy(quoteIn)
snipeBps = min(currentSnipeTaxBps(recipient), BPS - feeBps - creatorTaxBps - 100)   // if > 0
fee   = ceilDiv(quoteIn * feeBps, BPS)
tax   = ceilDiv(quoteIn * creatorTaxBps, BPS)
snipe = ceilDiv(quoteIn * snipeBps, BPS)
net   = quoteIn - fee - tax - snipe
tokensOut = amountOut(net, quoteReserve, tokenReserve)
if tokensOut > sellable:                     // finishing buy: clamp + refund
  tokensOut = sellable
  netNeeded = amountIn(sellable, quoteReserve, tokenReserve)
  spent = min(quoteIn, smallest s with s - fees(s) >= netNeeded)
require tokensOut * quoteIn >= minTokensOut * spent        // rate-based slippage

// sell(tokensIn)
gross = amountOut(tokensIn, tokenReserve, quoteReserve)
out   = gross - ceilDiv(gross * feeBps, BPS) - ceilDiv(gross * creatorTaxBps, BPS)
  • curve.currentSnipeTaxBps(recipient) returns the live snipe tax (0 for exempt recipients). Defaults: start 9900 bps, window 5s, start >> (2·elapsed).
  • Stop quoting the curve when sellableTokens() == 0 or readyToGraduate(); route to the pool once phase is 2.
  • Pool trades revert with PartialFillNotSupported if the pool can't fill an exact-in order; quote first and size accordingly.

Reading state

factory.getLaunchedToken(token) returns the full launch record: curve, deployer, creatorFeeRecipient, pairToken, supply, economics, fee and tax bps, buybackEnabled, buybackMode, phase, swept amounts, poolId, launchedAt, exists.

phaseMeaning
0NotGraduated: trading on the curve
1Swept: curve sold out, pool not created yet (retryable)
2PoolCreated: trading on Uniswap v4
3Rescued: stuck launch rescued by the owner
  • Curve: getReserves(), realQuoteReserve() (progress = realQuoteReserve / graduationThreshold), sellableTokens(), quoteFeeBalance(), creatorTaxBalance(), pendingBuyback().
  • Hook: pendingFees(poolId), pendingCreatorTax(poolId), pendingBuyback(poolId).
  • Token rewards: claimableRewards(holder), claimedRewards(holder), totalRewardsDistributed(), eligibleSupply(), isExcludedFromRewards(account).

Fees and claiming

  • Escrow: balanceOfToken(recipient, asset), claimToken(asset), claimTokens(assets[]). Funds go to msg.sender.
  • Sweeps: curve.sweepFees(minBuybackTokensOut) and hook.sweepPoolFees(poolId, minBuybackTokensOut). Permissionless when buyback is off or mode is HolderRewards (pass 0). Burn mode with a buyback share requires a sweep operator (InternalSwapRequiresOperator).
  • Rewards: token.claimRewards() sends the caller's accrued USDC.
  • Enable buyback (one-way): factory.enableBuyback(token), callable by the deployer or fee recipient.

Events to index

ContractEventMeaning
FactoryTokenLaunched / LaunchDetailsNew launch; details carries metadata and terms
FactoryLaunchSwept / PoolGraduated / GraduationExcessBurnedGraduation steps
FactoryLaunchRescuedStuck launch rescued
FactoryBuybackEnabledOne-way buyback switch
FactoryLaunchConfigSet / PairTokenSet / FeePolicySet / SnipeConfigSet / LaunchFeeSet / …Owner config for future launches
CurveCurveBuy / CurveSell / CurveBuyRefundedTrades with post-trade reserves
CurveCurveCompleted / AutoGraduationFailedSold out / graduation needs a retry
CurveFeesSwept / BuybackBurned / HolderRewardsPaid / BuybackDeferred / BuybackForwardedToPoolSweep outcomes
HookPoolRegistered / PoolSwapPool registered; swaps with swapper-facing amounts (trader = tx.from)
HookPoolFeesSwept / PoolBuybackBurned / PoolHolderRewardsPaid / PoolBuybackDeferred / PoolBuybackCreditedPool sweep outcomes
TokenTransfer / RewardsDistributed / RewardsClaimedBalances, burns (to 0x0), rewards
EscrowCreditedToken / ClaimedTokenFee credits and claims
LockerPositionLockedLiquidity locked at graduation
FeeRouterClaimed / BoughtAndBurned / LaunchTokensBurnedProtocol fee routing and RAIL burns

Uniswap v4 pools

Reconstruct a launch's pool key (or read factory.poolKeyOf(token)):

pool key
const [currency0, currency1] = BigInt(USDC) < BigInt(token) ? [USDC, token] : [token, USDC];
const key = { currency0, currency1, fee: 0, tickSpacing: 200, hooks: HOOK };
const poolId = keccak256(encodeAbiParameters(
  [{ type: "address" }, { type: "address" }, { type: "uint24" }, { type: "int24" }, { type: "address" }],
  [key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks],
));
  • The LP fee is 0; the hook charges the same 1% + creator tax as the curve, in USDC, rounded up.
  • Buys: fee on the total quote paid. Sells: fee on the gross quote out. Exact-out amounts are grossed up so the effective rate is identical.
  • Exact-in swaps paying USDC are charged up front and revert with PartialFillNotSupported if the pool doesn't consume the whole input (price limit hit).
  • Swaps initiated by the hook itself (buybacks) pay no fee.
Estimate gas on curve buys
A buy that sells out the curve also creates the pool. The curve requires GRADUATION_GAS_RESERVE (~450k) of gas left before attempting graduation and reverts with InsufficientGasForGraduation otherwise. Always use eth_estimateGas rather than a fixed gas limit.

Errors

ErrorMeaning
SlippageExceededOutput below your minimum (curve: rate-based check; router, hook buyback).
DeadlineExpiredRouter deadline passed.
NotTradableLaunch is not in phase 0 (curve) or 2 (pool).
CurveGraduatedCurve completed or sold out; trade through the pool.
PartialFillNotSupportedPool couldn't consume the whole exact-in input; no fee charged.
InsufficientGasForGraduationFinishing buy sent with less than GRADUATION_GAS_RESERVE gas left.
ZeroAmountAmount is zero.
NotWhitelistedLaunching is restricted and the caller isn't whitelisted.
CreatorTaxTooHighcreatorTaxBps > maxCreatorTaxBps.
PairTokenNotApprovedQuote asset isn't approved.
LaunchEconomicsMismatchexpectedEconomics doesn't match previewLaunchEconomics (config or economics changed).
LaunchConfigDisabled / LaunchConfigUnknownBad launchConfigId.
ExemptionListTooLongMore than MAX_EXEMPTIONS early-buy wallets.
InvalidBuybackModebuybackMode not 0 or 1.
InvalidParamse.g. launchTokenWithPermit with quoteIn > 0 and pairToken ≠ launchFeeToken.
InvalidLaunchConfigOwner config rejected: supply ≠ SUPPLY or graduation price not representable in v4.
NotCreatorenableBuyback caller is neither deployer nor fee recipient.
BuybackAlreadyEnabledBuyback is already on.
InternalSwapRequiresOperatorBurn-mode sweep with a buyback share called by a non-operator.
WrongGraduationPhasecreateGraduatedPool/rescueLaunch outside phase 1.
RescueTooEarlyRESCUE_DELAY hasn't elapsed since the sweep.
UnknownTokenAddress isn't a rail launch.
NoEligibleHoldersdistributeRewards with eligibleSupply 0.
NotOperator / ExceedsBudget / PlatformTokenNotSetProtocolFeeRouter.buyAndBurn preconditions.
NotAuthorized / ZeroAddress / InvalidBpsAccess or argument checks.