KasForge
KasForge is PumpForge's token launchpad built natively on Kaspa L1. Coins launch on a bonding curve, graduate into a pool with locked liquidity, and trade through covenant contracts. Everything is signed in the user's own wallet.
At a glance
| Item | Value |
|---|---|
| Network | Kaspa L1 mainnet (mainnet) |
| Token standard | KCC-20 at its Final text, the official reference build byte for byte; name and ticker on chain in the KCC-23 format |
| Verification | Every coin is checked from chain on Kascov: identity, full history, supply conserved |
| Supply per coin | 1,000,000,000 tokens, 0 decimals |
| Price discovery | Constant-product bonding curve with virtual reserves |
| Graduation | When the curve has raised the creator's chosen amount; 80% of the curve's tokens sold, 20% open the pool |
| After graduation | A constant-product pool; the graduation liquidity is locked for good |
| Trading fee | 1.5% per trade (1% platform, 0.5% creator; in the pool 0.75% platform + 0.25% LP + 0.5% creator) |
| Wallets | Kasware, Kastle and Kaspire in the browser, the Kaspire app on Android through WalletConnect, or any signer through the API and SDK. See Connect a wallet. |
| Contracts | SilverScript covenants, current version 3.8 |
| Coin tools | Bubble map of the top holders and their links, chart markers for dev trades and transfers, holder list with locks, vesting and streams |
| App | kaspa.pumpforge.tech |
How it fits together
- Contracts on Kaspa L1 hold every coin's curve or pool, its tokens, orders, locks and streams. They enforce prices, fees and who may move what.
- The sequencer settles orders in sequence, usually within seconds. It can only fill an order on the terms the user signed; it can never take funds. If it stops, orders can be cancelled by their owner and are refunded after about 60 minutes.
- The API prepares every transaction for the user's public key and returns it unsigned with a cost summary. The user's wallet (or a bot's signer) signs; the API submits.
- Data: markets, trades, candles, holders, a token list and DEX aggregator feeds are public.
Launch mechanism
Anyone can launch a coin from /launch or through the API (action: "launch"). A launch is two transactions, approved one after the other.
What the creator sets
| Setting | Details |
|---|---|
| Name, ticker, image, description, links | Written on chain in the first launch transaction (KCC-23 format). Image upload or https link; website, X, Telegram. |
| Raise | How much KAS the curve collects before the coin graduates. From 150,000 KAS to 10,000,000 KAS. It sets the starting and graduation market cap. |
| First buy | Optional, any size, priced by the curve like any buy. A first buy as large as the raise graduates the coin at once. |
| Vesting of the first buy | Optional: a simple lock (one date), a cliff (up to four dates) or linear (start, optional cliff, end). |
| Free allocation | Optional, up to 50% of the supply, locked in a vault until graduation, then 1% of the supply unlocks at graduation and 1% per day. Fee about $10 in KAS. Not combined with first-buy vesting. |
| Creator fees | Share them with up to two other wallets, or with one wallet and the coin's holders (holder rewards), choose a buyback-and-burn share (0–100%) and its schedule (every 5 minutes to 24 hours). These settings can be changed once after launch. See Fees and burns. |
Supply and identity
Every coin has a supply of 1,000,000,000 tokens with 0 decimals. A coin is identified by its token covenant id (64 hex characters, the KCC-20 id). Names and tickers are chosen by creators and are not unique: integrations should always key on the covenant id. Each launch's genesis transaction id is published so the id can be checked against the chain.
Anti-snipe (first minute)
For the first minute after launch one buy can take at most 1% of the supply (checked by the contract) and one wallet at most 1% in total (checked by the service). A larger buy is accepted as an order and settles when the minute is over. Market JSON shows antiSnipe.active.
Launch fee
The launch fee is $5, charged in KAS at the current rate. The launch form and the cost summary show the exact amount before approval.
Trading and pricing
Trades are orders: the user locks KAS (buy) or tokens (sell) in an order contract with a minimum to receive; the sequencer settles it against the curve or pool.
Connect a wallet
Press Connect wallet and pick one. Every trade, launch, lock and stream is signed in your own wallet; KasForge never holds your keys or funds.
| Wallet | Where | How it connects |
|---|---|---|
| Kasware | Browser extension | Detected on the page |
| Kastle | Browser extension | Detected on the page |
| Kaspire | Browser extension | Detected on the page |
| Kaspire app (Android) | Phone | WalletConnect: scan the QR code with Kaspire on a computer, or tap Open Kaspire on the phone, then approve KasForge in the app |
Set your wallet to Kaspa mainnet (addresses start with kaspa:). KasForge asks Kasware and Kaspire to switch for you, and Kaspire's app switches on its own over WalletConnect. Install wallets only from their official sites; copycat extensions exist.
The bonding curve
The curve is constant product with virtual reserves. With x = virtual KAS + KAS raised and y = tokens left + virtual tokens:
price (KAS per token) = x / y
market cap = price × 1,000,000,000
progress = KAS raised / raise × 100
Buys push the price up, sells push it down. The virtual reserves are set from the chosen raise so that, at the raise, the curve has sold 80% of its tokens.
Orders and settlement
- The user signs an order: KAS (plus a 1 KAS token deposit and a small settlement tip) or tokens go into the order contract, with a minimum to receive from the slippage setting.
- The sequencer settles orders in sequence, usually within a few seconds. Bought tokens are added to the wallet's single balance of that coin.
- If the price moved past the order's minimum, the order waits. The owner can cancel it any time; it is refunded automatically after about 60 minutes.
Limits
| Rule | Value |
|---|---|
| Minimum buy | 5 KAS (/config → minBuyKas) |
| Fee minimum | 0.2 KAS per trade |
| Order expiry | About 60 minutes, then refunded |
| Token deposit | About 1 KAS stays with a token balance; it comes back when the tokens are sold |
| Settlement tip | 0.05 KAS per order, taken from the trade |
Swap any Kaspa token (Braid)
The Swap page has two tabs. KasForge coins trades KAS and KasForge coins through KasForge's own orders. All Kaspa tokens routes through BraidSwap: KAS, KasForge coins and tokens from KaspaRocket, KRON and KasSeal pools, in any direction (for example a KaspaRocket token straight into a KasForge coin). The same routes are also available on Braid's own site.
- Pick the two tokens and an amount. The quote shows what you receive, the minimum after your slippage, Braid's fee and the KasForge fee.
- Review and confirm in your wallet. You sign one deposit with fixed terms: you receive at least the minimum, or the deposit comes back to you.
- Braid executes the route; the page checks the result on chain and shows it in your swap history.
| Item | Value |
|---|---|
| KasForge fee | 0.5%, written into the swap's terms and paid only if the swap completes |
| Braid fee | A share of the improvement over trading on the venue directly (often none) |
| Network fee | A small amount of KAS per deposit, shown before you sign |
| Selling for KAS | Needs some KAS up front (the router coin, which comes back in the payout, plus the fee). If the wallet is short, the page suggests selling a small part first. |
| Token pieces | One swap spends up to 4 pieces of a token; the page shows the count and merges them in a few signed steps |
| If a swap isn't completed | The deposit comes back after its deadline (about 10 minutes); Braid's page for the swap shows how |
How fees are taken
Fees come out of the amount traded. A 100 KAS buy costs 100 KAS: the 1.5% fee and the 0.05 KAS tip are taken from it and the rest buys tokens. The refundable deposit and the network fee are on top. A sell pays its KAS minus the fee and tip.
Graduation
A coin graduates when its curve has raised the creator's chosen amount. Its liquidity moves into a pool and the coin keeps trading there.
80 / 20
- By the time the raise is reached, the curve has sold 80% of its tokens.
- The other 20% goes into the pool together with the KAS raised minus the 3% graduation fee, at the curve's last price. The price does not drop and nothing is burned at graduation.
- The graduation liquidity is locked permanently: nobody can withdraw it.
The buy that completes the raise
It buys the curve's last tokens at curve prices; any KAS beyond the target buys from the new pool in the same order. The quote shows both parts.
The pool
A constant-product pool (price = KAS / tokens). Anyone can add liquidity at the current ratio and receive pool shares (a KCC-20 token). 0.25% of every pool trade stays in the pool for providers.
Ids before and after
The coin keeps its token covenant id. The market moves from the curve covenant to a new pool covenant; market JSON shows kind (curve or pool), market (the live covenant), id (the curve id the coin was launched with) and graduation (ts, txid).
Fees and burns
A trade costs 1.5% wherever it happens. The split differs on the curve and in the pool.
Fee table
| Fee | Amount | Goes to |
|---|---|---|
| Platform fee, curve | 1% of the trade, min 0.2 KAS | KasForge, paid out automatically |
| Platform fee, pool | 0.75% of the trade | KasForge |
| LP fee, pool | 0.25% of the trade | Stays in the pool for liquidity providers |
| Creator fee | 0.5% of the trade | The coin's creator fee wallet(s) and holder rewards, after any buyback-and-burn |
| Launch fee | $5 in KAS | Platform, at launch |
| Graduation fee | 3% of the KAS raised, once | 2.5% platform, 0.5% creator |
| Free allocation fee | About $10 in KAS | Platform, at launch |
| Token locker | About $1 in KAS per lock for holders; about $10 for the coin's dev and fee wallets and wallets linked to them | Platform |
| Payment stream | About $5 in KAS per stream | Platform |
Creator fees
- The creator wallet (the launcher) never changes. It can share each claim with up to two other wallets, each with its own share.
- The fee authority may change the settings. It stays with the creator while the creator keeps any share; if the creator gives 100% away, it picks which receiver holds the authority.
- Creator fees are claimed by hand (from 0.2 KAS). One claim pays every wallet its share.
- One change, only from your own share. After launch the creator can change the settings once, and only by giving away more of their own share: what goes to holders, other wallets or the buyback can never be lowered or moved (enforced by the contract). A creator who keeps 0% at launch has nothing left to change: the settings are final. A community takeover gives the new team one change of its own share. If holder rewards are waiting to be sent to the holders' vault, they are sent first (within a few minutes) and the change can be made right after: what holders were already owed always reaches them by the settings it was earned under.
Holder rewards
A creator can give a share of the creator fees (0–100%) to the coin's holders, at launch or with the one settings change. That share goes to the coin's own rewards address on chain (a ForgeRewards contract) and is shared among holders by how many tokens they hold: the more they hold, the more they get.
- Who earns: tokens in holders' own wallets, and tokens they have locked or are vesting: those count for the wallet they unlock to, so locking never costs a holder their rewards. Left out: the creator wallet, the fee authority and fee receivers (their locks too), the curve and pool, orders and every other contract-held balance, and burned tokens.
- When: every hour the contract's
payHoldersstep (run by KasForge, open to anyone) moves the holders' share into the rewards vault on its own; nothing goes to the creator or the other fee wallets then, and their claims never include the holders' share. Right after it arrives, it is shared by each holder's balance at the previous round and now (the smaller one), so tokens bought just before a round start earning at the next one. The coin page shows what will go to the vault next and when. - Claiming: by hand, each holder for themselves: a holder's claim pays only that holder (from 0.5 KAS, on the coin page) and pays the network fee. The payout from the coin's rewards vault is signed by KasForge's service key: the signature fixes exactly who is paid and how much, so holder rewards rely on the KasForge service to pay out. Market JSON:
holderRewards(pct,address,creditedKas,paidKas); a wallet's part:/account→holderRewards.mine. - Holder rewards take one of the two receiving slots, so a coin with holder rewards can share with one other wallet.
- A community takeover keeps the holders' share (and the buyback); what is due to holders still goes to their vault. The contract enforces this: a takeover can't change, remove or add holder-reward receivers.
Coin details and logo
- The creator (or, after a community takeover, the new team) can edit the coin's description, website, X and Telegram on the coin page at any time with Edit details (a signed message, no KAS moves, no fee).
- The logo is stored on chain in the coin's launch transaction, so nobody can change it later: not the creator, not a team after a community takeover, not KasForge. KasForge and the public token list (
logoURI) always show that launch logo.
Buyback-and-burn
A share of the creator fees (0–100%) buys the coin on its curve or pool on the creator's schedule (every 5 minutes to 24 hours, default 10 minutes). A buyback runs one full interval after new fees arrive, so a trade never triggers an instant burn. The tokens bought stay locked inside the market for good. Market JSON reports fees.burnPct, fees.burnedTokens, fees.nextBuybackAt.
Protocol revenue
Platform fees accrue inside each market and are swept to the platform wallet automatically. On coins launched with v3.2 and later, the partners' revenue share is split out on chain in the same sweep.
Liquidity
Every graduated coin has a pool. Its graduation liquidity is locked; anyone can add liquidity of their own.
- Deposit KAS and the coin together at the pool's current ratio (
lp-add). You receive pool shares, a KCC-20 token. More deposits add to the same position. - Earn 0.25% of every pool trade, kept in the pool and shared by ownership. Nothing to claim.
- Withdraw any part (
lp-remove): KAS and tokens at the current ratio. - Risk: if the price moves, a withdrawal can be worth less than holding (impermanent loss). Fees may not make up for it.
Market JSON → liquidity: totalShares, lockedShares, providerShares, lpFeeBps, minDepositKas, tokensPerKas.
Locks, vesting and streams
Token locker
Lock tokens of any coin you hold for yourself or another wallet: a simple lock (one date), a cliff (up to three dates with their own shares) or linear (start, optional cliff, end). Only the receiving wallet can collect, and only after each date. Fee about $1 in KAS for holders, about $10 for the coin's dev and fee wallets and wallets linked to them (shown before you sign), plus about 1.2 KAS per date held with the lock and returned on collection. Every lock has a public page at /lock/<id>.
Payment streams
Stream KAS or any KasForge coin to a wallet, linearly between a start and an end (an hour to about 2,000 days), with an optional cliff. The receiver collects whenever they like. A cancellable stream can be stopped by the payer: the receiver keeps everything unlocked up to the block the cancel lands in, the payer gets the rest. Fee about $5 in KAS. Public page: /stream/<id>.
API: GET /streams, GET /stream/:id, and the build actions stream-create, stream-claim, stream-cancel, stream-settle.
Bubble map and chart markers
Every coin page shows who holds the coin, how those wallets are connected, and what the creator did on the chart, so you can judge a coin before you trade it.
Bubble map
Open a coin and pick the BUBBLE MAP tab. The map opens in its own window.
- Bubbles: the top 50 wallets. A bubble's area is its share of the whole supply, so hiding one never resizes the others.
- Links between holders: token transfers (solid line, read from Kascov's per-token history), KAS transfers (dashed line, from the Kaspa REST API), and a shared funder (dotted line to a small dot: one wallet sent KAS to several holders).
- Clusters: wallets joined by links share a colour and a total. Large shared sources such as exchanges are left out so they don't join everyone.
- Fresh wallets (🌱): a wallet whose whole KAS history starts less than 24 hours before its first trade in the coin.
- Creator (★) is marked on its bubble.
- Special holders start hidden but are always in the address list: the curve or pool, the dev vault, burned tokens, locks and vesting, and payment streams. Unhide the curve or pool to see who bought and sold on it.
Using the map
- Drag bubbles; they float, push each other, and stay where you drop them. Linked wallets follow the one you drag.
- Scroll, pinch or use + / − to zoom; ⤢ fits everything; Re-arrange lays the map out again.
- Click a bubble for its card: share, balance, cluster, every link, its trades on the curve or pool, a link to its profile.
- The address list (open by default on a computer) has search and an eye per row to hide or show a holder. Your choices are saved per coin.
- Balances refresh every 30 seconds while the map is open; links are rebuilt at most every 10 minutes. ↻ asks for both now.
Holders tab
The holder list shows the curve or pool, the dev vault and burned tokens on their own rows, and lists every payment stream, lock and vesting separately with the wallet it pays or unlocks to, so locked tokens are never counted as a wallet's free balance.
Chart markers
Turn them on and off under Indicators on the chart. Each marker sits at the trade's price on its candle; hover for the details and the transaction.
| Marker | Meaning |
|---|---|
| D (green / red) | The creator bought / sold |
| T | The creator moved tokens to another wallet |
| B / S | Your own buys and sells, plus a dashed line at your average entry |
| F | A trade by a wallet you follow |
| M | Migration: the coin graduated to its pool |
Several events in one candle become one marker with a count.
Verify on chain
You don't have to trust the site: every KasForge coin can be checked from the Kaspa chain itself.
The token is the official build
KasForge coins are KCC-20 tokens built from the official reference program, byte for byte, at the standard's Final text. Explorers that review that build recognise every KasForge coin as a standard token.
Names on chain
Each coin's name and ticker are written into its launch transaction in the KCC-23 format, so the token's id itself commits to them. Explorers show this as a verified name binding. Names are still not unique: always check the token id.
Kascov
Every coin page links to Kascov, the covenant explorer for Kaspa. For each coin it rebuilds the token's identity from its genesis, walks its whole history, and checks that the supply is conserved, then shows the coin as verified. It also lists where the supply sits: in wallets and in contracts.
Check it yourself
- Copy the coin's token id from its page (the Details tab) or from the token list.
- Open it on Kascov and compare the supply, holders and history with the coin page.
- For an integration, follow Reference token.
How KasForge is tested
Every contract version goes through the same checks before it reaches the site. Mainnet launches on v1, the final contracts (contracts 3.8 in the API); here is what they went through.
Read the security review (PDF)
On every version
- Kaspa's real consensus rules. Every action (launch, buys and sells, orders, fees, holder rewards, takeovers, graduation, liquidity, locks, vesting, streams) runs through Kaspa's own transaction validation, the same code nodes run.
- The real signing path. Transactions are signed the way Kasware and Kastle sign them, input by input, and tested live on Kaspa Testnet 10 with those wallets before mainnet.
- Tampered transactions. A fuzzer takes honest transactions and attacks them: changed amounts and outputs, swapped inputs, extra mints, spending another user's tokens, fake contracts. More than 190,000 tampered transactions so far, and none was accepted that broke a rule.
- Known attack patterns. The contracts were checked against every finding of a published security review of a similar Kaspa covenant project, and against the bug classes found in other UTXO launchpads and DEXes: one payment counted twice, foreign contracts or stray tokens riding along, unchecked inputs and outputs, positions chosen by the caller, timing, and transaction size limits.
- Old coins keep working. Each new version runs the full suite on the earlier versions too, so coins launched on them keep trading.
The final contracts (v1)
- Every check, removed one at a time. Each check line in every v1 contract was deleted on its own, and the test suite was run against the broken contract. Each deletion either makes a test fail, or the check is a second guard for another one (each of those was reviewed by hand). This added 56 new tests. The last changes before mainnet (a buy may name who receives its tokens once the first-minute window is over, a fee change first pays what is still owed to holders, and the market's own token coins must keep their 1 KAS) went through the same check, line by line, with new tests for each.
- Full suite. 301 tests (155 library tests plus the real-consensus, order-template, wallet and SDK test files), all passing on v1 and on the earlier testnet versions.
- Random trading. 150 random runs of buys, sells, orders, claims, buybacks, graduation and liquidity moves, every step checked against the model. A second campaign of 70 runs (about 25,000 transactions, each verified like a node does) found no tokens or KAS appearing or vanishing, the pool never losing value per share, and no buy-then-sell round trip making money.
- Two contracts in one transaction. Honest transactions were merged in pairs (two markets, a market and an order, two orders, a market and the allocation vault, a curve and a pool) and allowed to share outputs, so one payment can never be counted twice.
- Payment positions pinned. A check reads every contract and lists each place a transaction chooses where a payment goes; the list is fixed, so a change that adds an unchecked position fails the tests.
- Attacker model. A model searches combinations of transactions over curve, pool, orders and vault (stray coins, fake tokens, reused outputs, two markets at once) and checks that nobody takes what isn't theirs and that refunds and claims always stay possible.
- An auditor's view. What each service key can and can't sign, the size of every action under Kaspa's mass rules, the fee and price economics, and every reported case replayed as a real transaction.
- Published audits as checklists. Public audit reports of UTXO DEXes and launchpads on Cardano, Bitcoin Cash and Chia were read and each relevant bug class was turned into tests.
- Quotes match what settles. 24 random trades, each moving the price for the next: the quote equals the tokens or KAS the trade gets, to the sompi.
- Outside reviews. The source was reviewed from outside; every reported issue was rebuilt as a real transaction and tested, and v1 refuses every one. Attack transactions run in Kaspa's script engine against v1 (trades, fees, holder rewards, takeovers, orders, the allocation vault and the pool) all failed, and every honest case passed.
- kaspa-redteam. An open-source attack tool run against all v1 contract files and against 42 honest v1 transactions covering every launchpad action: no attack moved anyone else's KAS or tokens. Read the report.
- 43 attacks, all refused. The security review lists every attack tried against v1, by area (fees, trades, anti-snipe, orders, launch, graduation, allocation vault, takeover, liquidity, holder rewards), and what the KasForge service and site check before you sign. Open the PDF.
Found something? Report it in #support on the PumpForge Discord.
Security review (v1)
The public security review of the contracts every KasForge coin launches and trades on: what they enforce, what the keys KasForge runs can and can't do, how they were tested, and the notes integrators and users should know. Self-run by PumpForge, not an independent audit.
Open the security review (PDF)
Result
- No Critical, High, Medium or Low issue in the release; 12 informational notes, each explained.
- 301 tests passing on v1, every action run through Kaspa's own consensus code.
- Every check line of every contract removed one at a time to make sure a test catches it.
- 317 red-team attack transactions and a 43-attack catalogue: no attack moved anyone else's KAS or tokens.
- Keys and trust: the sequencer and admin keys can only do what the contracts allow; none can move a user's coins.
See also How KasForge is tested and the Redteam report.
Redteam report (v1)
Self-run test, not an audit. KasForge v1 is the contract set mainnet launches with (contracts 3.8 in the API). The runs were done locally on 3 November 2026; nothing was uploaded.
Result
No attack moved anyone else's KAS or tokens. Every transaction the tool flagged is a sender shrinking a deposit it pays from its own coins, a sender keeping the network-fee budget it already gets, or a user moving their own coins.
Tool
| Tool | kaspa-redteam 0.16.0 (commit 5ec2891), attack library 0.9.1 |
| Judge | rusty-kaspa consensus validator 2.1.0, in process (mempool relay policy not applied) |
| Compiler (source search) | SilverScript 15b7bc2, the tool's own build |
| Not run | mining and mempool packs (they need a local node) |
A finding is written only when consensus accepts an attack transaction the tool expected to be rejected, and it comes with the exact transaction so it can be replayed.
Three runs
- Source search on all 11 contract files as one project (61 minutes). The tool compiles each file, searches for an honest spend of every entry, then attacks what it found.
- Honest transactions from our test harness, attacked from an outsider's seat. 42 transactions, every launchpad entry, curve and pool, built on the v1 contracts. Each one is first checked by the tool's consensus judge exactly as given, then 317 attack transactions were built from them. This is the tool's baseline mode, for contracts its own search can't reach: covenants that carry state into the next coin, and a token next to its market.
- The same harness from a user's seat. The buyer's and order owner's throwaway keys were given to the tool, so it signs as that user: can a user take more than the contract allows?
What was attacked
| Contract | Entries attacked | How |
|---|---|---|
ForgeCurve | init (launch), buy, top-up buy, sell (order settle), buyback, claimCreator, claimPlatform (plain and with the partners' share), payHolders, setFees, proposeTakeover, cancelTakeover, finishTakeover, graduate | harness |
ForgePool | buy, top-up buy, sell (order settle), buyback, claimCreator, claimPlatform (both), payHolders, setFees, proposeTakeover, cancelTakeover, finishTakeover, bindLp, addLiquidity, removeLiquidity | harness |
ForgeBuyOrder | settle, cancel, refund | search and harness |
ForgeSellOrder | settle, cancel, refund | search and harness |
ForgeVault (allocation) | start (at graduation), release | harness |
ForgeTakeover | spend (in cancel and finish) | harness |
ForgeRewards | pay, recover | harness |
ForgeHold (dev buy) | seal, late | search |
ForgeLock, ForgeVest | unlock, claim | search and harness |
| KCC-20 token | transfer, delegator, all three borrow modes | search |
Attacks and results (outsider's seat)
| Attack | Result |
|---|---|
| OUT-01: correct value, attacker's script | refused (111 tries) |
| OUT-03: valid output 0, skim a later output | refused (53) |
| FEE-01: route value to the miner fee | refused (29) |
| IN-01: two covenant coins, one shared set of outputs | refused (58) |
| IN-02: attacker's coin at input 0, covenant moved behind it | refused (29) |
| OUT-02: correct script, reduced value | flagged twice, see below |
| OUT-04: keep what the fixed payouts leave over | flagged 6 times, see below |
The signature, secret, family and borrow packs had nothing to apply to in these transactions; they ran in the source search.
The flags, explained
- OUT-02, allocation vault release. A release creates a new token piece for the allocation's owner, with a 1 KAS deposit paid by whoever sends the release from their own coins. The tool cut that deposit to 0.1 KAS and kept 0.9 KAS of its own money. The vault's KAS and the owner's tokens are checked and did not move; when a release tops up an existing piece, the contract requires the piece to keep its KAS.
- OUT-02, pool buy for someone else. A buy may name who receives the new token piece (so a swap router can pay for its user). The tool sent a pool buy for the buyer's key paid entirely from its own coins, and put 0.1 KAS on the new piece instead of 1 KAS. The 0.9 KAS it "kept" was its own; the buyer received the tokens it paid for and lost nothing, and the market got the full price and fees.
- OUT-04, order refunds (buy and sell, curve and pool), graduation, vault release. Whoever sends these may keep at most 0.01 KAS that would otherwise go to the miner as the network fee (0.0098 KAS on a refund, about 0.001 KAS on graduation and release). On a refund that is the 0.01 KAS refund fee, the network-fee budget of whoever refunds; the order's owner still gets exactly what the order says.
User's seat
The only accepted changes were a buyer cutting the deposit on their own new piece, and an order owner cancelling their own order to themselves. Both move only the signer's own coins. ForgeVest from the beneficiary's seat shows the beneficiary moving the KAS deposit on their own vesting coins.
Transactions where the user signs inside a token piece (top-up buys, placing a sell order, adding and removing liquidity) can't be re-signed by the tool, so it rejects them before attacking. From the outsider's seat they were attacked like the rest.
Source search
0 findings and 70 attack transactions on the entries it could spend: KCC-20 (all paths), ForgeLock, ForgeHold, and the orders' cancel and refund. Its search does not reach covenant entries that carry state into the next coin, or the holder-rewards and vesting coins. (This run was made just before the last change to the curve and pool; every file it reaches is the same in v1.) That's why run 2 gives it our own honest transactions for those.
What this is and isn't
- A test tool run by us, on our own contracts. It is not an audit, and the contracts are not independently audited.
- It only finds the attack shapes in its library. Alongside it, v1 went through the checks on How KasForge is tested.
- Mining and mempool attacks (the node packs) were not run.
Community takeovers
When a coin's community asks (for example after the creator leaves), KasForge can move the coin's creator fees to a new wallet.
- Apply at /cto; you receive the policy and next steps by email.
- The creator wallet itself stays; KasForge gives the creator fees and the fee authority to the new wallet, keeping the buyback and the holder rewards shares (what is due to holders still goes to their vault). The new team can then change the fee settings once, giving away only its own share.
- The new team can edit the coin's description and links for free (from the coin page: Edit details). The logo is on chain from launch and can't be changed.
- Nothing else changes: not the tokens, not the pool, not the platform fees. Market JSON shows the latest takeover in
cto(ts,txid,from,to).
Risk disclosures
- Mainnet. KasForge runs on Kaspa L1 mainnet. Coins trade with real KAS; settings shown before you sign are the ones in force.
- Smart-contract risk. The contracts are tested extensively (see How KasForge is tested), but no software is guaranteed free of bugs. Only use amounts you can afford to lose.
- Sequencer liveness. Orders need the sequencer to settle. It cannot take funds, but if it is down orders wait; owners can cancel and orders are refunded after about 60 minutes.
- Market risk. Coins are launched by their creators, not by PumpForge. Prices can go to zero. Names, images and links are the creators' and are not checked.
- Impermanent loss for liquidity providers.
- Lookalikes. Names and tickers are not unique; always check the token covenant id.
- Nothing in these docs is financial advice or a promise of returns.
Network and endpoints
| Item | Value |
|---|---|
| Network | mainnet (addresses start with kaspa:) |
| App | https://kaspa.pumpforge.tech |
| Partner API (keys, trading) | https://kaspa.pumpforge.tech/api/v1 |
| Public data (token list, DEX feeds) | https://kaspa.pumpforge.tech/api/kaspa/forge |
| Explorer | kascov.io (mainnet) |
| Units | 1 KAS = 100,000,000 sompi. Tokens: 0 decimals. API amounts are in KAS unless a field says sompi. |
| Keys | pub = the wallet's 32-byte x-only public key (64 hex characters). From Kasware's getPublicKey() take the last 64 hex characters; Kaspire's getPublicKey() already returns the 64-character form. |
Wallets
Wallets sign KasForge transactions input by input. Bots and servers sign with the SDK's signer (Schnorr, SIGHASH_ALL, BIP-340).
| Wallet | Provider | Signing call |
|---|---|---|
| Kasware | window.kasware | signPskt({ txJsonString, options: { signInputs } }) |
| Kaspire extension | window.kaspire (isKaspire) | the same call as Kasware; networks are mainnet / testnet-10 |
| Kaspire app | WalletConnect v2, namespace kaspa, chains kaspa:mainnet / kaspa:testnet-10 | kaspa_signPskt with the same params; also kaspa_getAccounts, kaspa_getPublicKey |
| Kastle | window.kastle | signTx(network, txJson, scripts), one script entry per input to sign |
All of them return the signed transaction JSON, which goes to /submit unchanged.
Contracts
KasForge is a set of SilverScript covenant contracts on Kaspa L1. They hold every coin's market, tokens, orders, locks and streams, and enforce prices, fees and who may move what.
| Contract | Role |
|---|---|
ForgeCurve | A coin's bonding curve: its state, token inventory and fees, until graduation |
ForgePool | The coin's pool after graduation, with liquidity-provider shares |
ForgeToken | The KCC-20 token, used for coins and for pool shares |
ForgeBuyOrder / ForgeSellOrder | Orders the sequencer settles, cancellable by the owner, refunded after expiry |
ForgeVault | The creator's free allocation, released daily after graduation |
ForgeLock / ForgeVest | Token locker: single-date locks, cliff and linear vesting |
ForgeStream | Payment streams in KAS or tokens |
ForgeTakeover | The 24-hour timer of a community takeover |
ForgeRewards | One coin's holder rewards, paid out as holders claim |
Versions
New coins launch on contracts 3.8, which mainnet launches with as v1: market JSON keeps contracts as "3.8" (use it to pick templates), and contractsLabel is the name the site shows. A coin keeps the contracts it was launched with for life.
Ids
- Token covenant id (
covenantId): the coin. Stable for life. - Curve id (
id): the market the coin launched with; also the coin's URL id. - Market (
market): the live market covenant (the curve, then the pool). - Genesis (
genesisTxid): the launch transaction that created the token id.
Every id in the API accepts either the token id or a market id. Contract details are available to integration partners and reviewers on request.
Reading token state
Everything a front end needs is in the market JSON from GET /markets (all coins) and GET /market/:id (one coin).
const r = await fetch('https://kaspa.pumpforge.tech/api/v1/market/' + TOKEN_ID);
const { market } = await r.json();
console.log(market.name, market.tick, market.priceKas, market.mcapKas, market.progress);
Key fields
| Field | Meaning |
|---|---|
id, covenantId, market | Curve id, token id, live market covenant |
name, tick, logo, description, links | Creator's metadata |
kind, graduated, progress | curve or pool; raise progress in % |
priceKas, mcapKas, change24h | KAS per token, market cap in KAS, 24h change in % |
volume24h, trades24h, volume1h, trades1h, volumeTotal, tradesTotal | Volume in KAS and trade counts |
raisedKas, targetKas (curve) / pool.kas, pool.tokens (pool) | Reserves |
supply, circulating, holders | Supply figures |
fees | Split, receivers, burnPct, burnedTokens, claimableKas, nextBuybackAt, holdersPct, oneChange / changeUsed (the one settings change) |
holderRewards | pct, address, creditedKas, paidKas, owedKas, dueKas (next payment to the vault), nextPayTs (null: no holder rewards) |
allocation, devVesting, lockedTokens | Creator allocation and locks |
antiSnipe | active, maxPct |
contracts, contractsLabel | Contract version |
genesisTxid, graduation | Launch and graduation transactions |
Other reads
Trades, candles, holders, a wallet's account and portfolio: see Read endpoints. The token list for wallets and explorers: Token list.
Pricing and graduation math
Prices come straight from the reserves. Use /quote for exact trade estimates (fees, rounding and the curve/pool split at graduation included).
// curve (kind === 'curve'): virtual reserves included
price = (vKas + raisedKas) / (tokensLeft + vTokens) // = market.priceKas
// pool (kind === 'pool')
price = pool.kas / pool.tokens
mcap = price × supply // = market.mcapKas
progress = raisedKas / targetKas × 100 // = market.progress
graduation market cap ≈ market.graduationMcapKas
Fee math
platformFee = max(0.2, kas × feeBps / 10000) // feeBps = 100 on the curve
creatorFee = kas × creatorBps / 10000 // creatorBps = 50
// in the pool lpBps (25) of the platform fee stays with providers
Quote
GET /api/v1/quote/:id?side=buy&kas=100
GET /api/v1/quote/:id?side=sell&tokens=2500000
Returns receiveTokens or receiveKas, priceImpactPct, swapFeeKas, settleTipKas, tokenDepositKas, and for the buy that completes a raise completesRaise, curvePartKas, poolPartKas.
Token list
Every KasForge coin in the tokenlists.org shape, open to any origin.
Each entry: network, covenantId, symbol, name, decimals (0), logoURI and extensions (curveCovenantId, poolCovenantId, genesisTxid, graduationTxid, creator, supply, graduated, links, url). ?covenantId= returns one coin.
Reference token
A live coin to validate an integration against: read it from the API and compare with the explorer.
Check: the token id resolves in the token list, genesisTxid exists on the explorer, the price equals the reserves ratio, and its trades appear in the DEX feed.
API overview
One API for reading markets and for trading on behalf of users. The API prepares transactions; it never holds keys.
Open tier and partner keys
| Tier | Reads / min | Builds / min | Submits / min | From (30-day volume) |
|---|---|---|---|---|
| Open (no key, per IP) | 300 | 60 | 60 | — |
| Starter | 1,000 | 150 | 150 | every new partner |
| Growth | 3,000 | 400 | 400 | 50,000 KAS |
| Pro | 6,000 | 1,000 | 1,000 | 200,000 KAS |
Partners may burst to 1.5× their limit for a moment and are served first when the service is busy. One end-user wallet can build at most 30 transactions a minute. GET /info returns the live tiers and rules.
Errors and limits
400 bad request, 401 key required, 429 rate limit (read Retry-After and X-RateLimit-Remaining), 503 busy (retry after a few seconds).
How a trade works
- Build:
POST /buildwith the action and the user'spubreturnstxs[](each withtxJsonStringandsignInputs), abuildIdand asummaryto show the user. - Sign every transaction in
txs, in order: in the user's wallet, or on your server with the SDK. - Submit:
POST /submitwith{ buildId, signed: [...] }. A build is valid for a few minutes.
Read endpoints
:id accepts a token id or a market id. Try them live with Run.
Every coin's market JSON (see Reading token state).
One coin.
Trade estimate.
Recent transactions (buys, sells, buyback burns, liquidity), newest first; limit up to 200. Each: ts, type, volume (KAS), tokens, price, txid, trader.
Candles: 1m 5m 15m 1h 4h 1d.
Holders including the curve or pool, the dev vault and burned tokens. Payment streams (stream: true, streamId, payer, receiver) and locks or vesting (lock: true, vesting, beneficiary, unlockDaa) are their own rows, listed under the contract's address.
A wallet on one coin: balance, open orders, locks, liquidity.
One order, by the transaction that placed it (market optional): status is the open state (settling, waiting-price, retrying, expired, …, with statusText), filled or refunded (with txid, the transaction that did it), cancelled, closed (spent outside KasForge) or not-placed. Also side, amounts, expiryDaa, orderOutpoint.
A wallet across all coins: positions, PnL, created coins, activity. Each position lists its token pieces in cells ([{outpoint, amount}], largest first), the notes a router spends for a sale.
Payment streams.
One stream with its schedule and history.
Tiers, rules and the network.
Build and submit
Always: action, pub (x-only key, 64 hex). Most actions also take market (token or market id).
| Action | Body |
|---|---|
order-buy | kas, slippage (%), priority? |
order-sell | amount (tokens), slippage |
cancel | order |
send / send-kas | amount + receiver / kas + receiver |
lp-add / lp-remove | kas / holding?, amount? |
lock / unlock | amount, tranches, beneficiary? / holding |
claim / claim-all | Creator fees of one coin / every coin |
rewards-claim | The wallet's holder rewards on market (from 0.5 KAS) |
set-fees | redirect?, redirectPct?, redirect2?, redirect2Pct?, authority?, burnPct?, buybackMinutes?, holdersPct? (signed by the fee authority; once per coin) |
launch | name, ticker, raiseKas, devKas, image?, description?, website?, x?, telegram?, allocPct?, vesting, fee settings |
stream-create | receiver, amount, end, start?, cliff?, cancellable?, memo?, market? (token streams) |
stream-claim / stream-cancel / stream-settle | stream |
// response
{ "ok": true, "buildId": "…",
"txs": [ { "txJsonString": "…", "signInputs": [ { "index": 0, "sighashType": 1 } ] } ],
"summary": { "action": "order-buy", "payKas": 100, "receiveTokens": 2512340, "minTokens": 2437000, … } }
{ "buildId": "…", "signed": [ "<signed tx JSON>", … ] } → { "ok": true, "txid": "…" }
Websites: sign in the user's wallet
// keep the API key on YOUR server: proxy /build and /submit
const b = await myServer.build({ action: 'order-buy', pub, market, kas: 10, slippage: 3 });
const signed = [];
for (const t of b.txs) {
// window.kaspire.signPskt takes the same argument
signed.push(await window.kasware.signPskt({ txJsonString: t.txJsonString, options: { signInputs: t.signInputs } }));
}
const r = await myServer.submit({ buildId: b.buildId, signed });
summary, and verify the transaction itself: see Check before signing.Order data: check it, and get the funds back without us
For order-buy and order-sell, summary.order describes the order the transaction creates, so a wallet can check what it is paying into and the user can always get the funds back, even if KasForge is offline.
"order": {
"contract": "ForgeSellOrder", // or "ForgeBuyOrder", "ForgeSellOrder (v1, legacy)"
"redeemScript": "…", // the order contract (hex)
"scriptHash": "…", "scriptPublicKey": "aa20…87", "address": "kaspa:p…",
"state": { "owner", "market", "kcc20", "expiryDaa",
// buy: unitsIn, minTokens, refundFee, creatorBps, feeBps, feeMin, tokenDust, templateHash
// sell: minSompi, amount, tip, refundFee, refundGuard },
"output": { "index": 0, "outpoint": "<txid>:0", "sompi": … },
"tokens": { // sell orders: the tokens the order holds
"redeemScript": "…", "scriptPublicKey": "…", "covenantId": "…", "amount": …,
"owner": { "ownerScheme": 3, "owner": "<scriptHash>" },
"output": { "index": 0, "outpoint": "…", "sompi": … } },
"exits": { "cancel": "…", "refund": "…" }
}
- Check: BLAKE2b-256 of
redeemScriptisscriptHash, and the output atoutput.indexpays toscriptPublicKey. Rebuild the script from the order kit (source, artifacts and layouts) withstate, and compare byte for byte:ownermust be the user's key. - Outpoints are final. Signing does not change a Kaspa transaction id, so
output.outpointis where the order will be once sent. - In the SDK:
checkOrder(summary.order, txJsonString, pub)does all of this without a compiler (the order templates ship with the SDK), andkf.order(txid)follows the order until it is filled. - Getting the funds back: the owner can spend the order at any time with entry
cancel(ownerSig); afterexpiryDaaanyone can callrefund(), which returns the KAS (lessrefundFee) and any tokens to the owner. Keep theorderobject: it is everything those transactions need.
Partner program
Trading bots, terminals, wallets and sites earn from the trades they bring. Sign up yourself at /partners: sign in with Kasware, Kastle or Kaspire (one signed message, no fee), pick an id, get API keys (up to 3).
Two fee modes
| Mode | How it works |
|---|---|
| Revenue share | 25% of our platform fee on your volume. Your users pay the normal fee. On v3.2+ coins your share is split out on chain. |
| Your own fee | 0.1% to 1%, all yours, taken from the user's trade like the trading fee. Collected when an order fills, returned if it never fills. Shown in the cost summary. |
Switch modes once every 30 days. Trades are tagged kfref:<your-id> on chain and show your name under “Via” on KasForge.
Claims
Claim from the partner dashboard from 100 KAS, or 30 days after your last payout. Claims are usually paid straight away from the payout wallet, and each payout's small network fee comes out of it.
Revenue share is credited when the trade settles, but its KAS reaches the payout wallet with the coin's next platform-fee sweep (a coin is swept once its platform fees reach 5 KAS). Until then the dashboard shows it as Arriving; it moves to Claimable on its own. Own fees are claimable as soon as the order fills.
Your volume, earnings, balance, tier, limits and usage (needs your key).
Integration types
- Websites and terminals: build on your server, sign in the user's wallet, submit. Non-custodial.
- Telegram and Discord bots: sign on your server with the SDK. The bot holds its users' keys and is responsible for them.
- Wallets: build with the user's public key, sign inside the wallet, submit.
- Read-only tools: charts, scanners, trackers: read endpoints and feeds.
JavaScript SDK
@kasforge_official/sdk: an API client, a local signer and a transaction checker. Node 18+, MIT.
npm install @kasforge_official/sdk
Quick start
import { KasForge, trade } from '@kasforge_official/sdk';
const kf = new KasForge(); // open tier
// const kf = new KasForge({ apiKey: process.env.KASFORGE_API_KEY }); // partner
const r = await trade(kf, { action: 'order-buy', market: TOKEN_ID, kas: 10, slippage: 3 }, userKeyHex,
(summary) => confirmWithUser(summary), { maxSpendKas: 11.1 });
Client methods
| Method | Endpoint |
|---|---|
markets(), market(id) | GET /markets, /market/:id |
quote(market, { side, kas, tokens }) | GET /quote/:id |
trades(market, limit), ohlc(market, interval), holders(market) | Read endpoints |
account(pub, market), portfolio(pub), me() | Wallet and partner reads |
build(body), submit(buildId, signed) | POST /build, /submit |
buy, sell, cancel, send, sendKas | Build helpers |
setFees, claimFees, claimAllFees | Creator fees |
streamCreate, streamClaim, streamCancel, streamSettle, streams, stream | Payment streams |
Signer
signTransaction(txJsonString, signInputs, privateKeyHex) signs the listed inputs (Kaspa Schnorr sighash, SIGHASH_ALL, BIP-340), checked against rusty-kaspa test vectors. sighash(tx, index) and publicKeyOf(key) are exported too. Keys never leave your process.
trade()
trade(client, body, privateKeyHex, confirm?, guard?) builds, calls confirm(summary), runs checkTransaction with guard (maxSpendKas, allowRecipients, allowCovenantInputs), signs every transaction and submits.
Example: a payment stream
const end = Math.floor(Date.now() / 1000) + 30 * 86400;
await trade(kf, { action: 'stream-create', receiver: 'kaspa:…', amount: 300, end, memo: 'October' }, userKeyHex);
Check before signing
Never sign from the summary alone. checkTransaction(txJsonString, signInputs, { pub, maxSpendKas, allowRecipients, allowCovenantInputs }) enforces three rules from the transaction itself.
- Every input the user signs is the user's own plain coin, unless
allowCovenantInputs(sells, cancels, liquidity, locks, token streams). - No plain-address output pays anyone but the user (change), unless listed in
allowRecipients. - The user's coins in minus plain outputs back to the user is at most
maxSpendKas.
Spending caps per action
| Action | maxSpendKas | Other recipients |
|---|---|---|
order-buy | KAS amount + 1 (token deposit) + 0.01 | none |
order-sell | 1.2 (1.25 with a merge first) | none |
cancel | 0.01 | none |
send | 1.01 (1.06 with a merge) | none |
send-kas | KAS amount + 0.01 | the receiver |
lp-add / lp-remove | KAS amount + 1.01 / 1.1 | none |
lock | 1 KAS per locked part + 0.02 | none |
unlock, stream-claim, stream-cancel, stream-settle | 0.02 | none |
claim / claim-all | 0.05 per transaction | none |
set-fees | 0.01 | none |
launch | first buy + fees + about 2.5 deposits + 0.02 | the platform fee wallet (feeKey) |
stream-create | amount + stream fee + 0.02 | the platform fee wallet |
Exact input and output layouts per action are in the SDK's SPEC.md.
Holder map data
The data behind the bubble map: the top holders of a coin and the links between them. Public, no key.
| Field | Meaning |
|---|---|
holders | The top 50 wallets plus every special holder, each with kind: wallet, market (curve or pool), vault, burn, script (lock or vesting) or stream |
links | { a, b, type }: token (with amount, n), kas (with kas, n) or trade (a wallet's net trading on the curve or pool: bought, sold, kasIn, kasOut, n). special: true when one end is not a wallet |
funders | Wallets that sent KAS to two or more holders: { address, wallets } |
clusters | Holders joined by wallet-to-wallet links: { id, wallets, pct } |
fresh | Holders whose KAS history starts less than 24 hours before their first trade |
updatedAt, sources | When the links were built, and whether each source answered (kascov, rest) |
Links are built from Kascov's token history and the Kaspa REST API, and cached for 10 minutes per coin. Balances come from /holders.
DEX aggregator feeds
KasForge publishes its swaps and liquidity events in the formats DEX aggregators read: the GeckoTerminal / DEX Screener events API and the CoinGecko DEX API. Open to any origin, no key.
Blocks on Kaspa
Kaspa is a blockDAG with about 10 blocks a second, so there is no single block height. The feed's blockNumber is a DAA-score clock: anchored once to the node's DAA score and advancing 10 per second. Every event carries the block of the second it was recorded in, so numbers never change and only grow. txnId is the real Kaspa transaction; use it to locate an event on chain.
Pairs and assets
- Each coin has two pairs over its life: its bonding curve (pair id = the curve id) and, after graduation, its pool (pair id = the pool covenant id).
asset0= the coin (its token covenant id, 0 decimals),asset1=KAS.priceNative= KAS per token. Amounts are decimal strings. Reserves after each event are included (on the curve they include the virtual reserves that set the price).
GeckoTerminal / DEX Screener events API
{ "block": { "blockNumber": 412398120, "blockTimestamp": 1792490000 } }
{ "asset": { "id": "3846…1384", "name": "Nova", "symbol": "NOVA", "decimals": 0,
"totalSupply": "1000000000", "circulatingSupply": "412900000", "metadata": { … } } }
{ "pair": { "id": "…", "dexKey": "kasforge-pool", "asset0Id": "<token id>", "asset1Id": "KAS",
"createdAtBlockNumber": …, "createdAtBlockTimestamp": …, "createdAtTxnId": "…", "creator": "kaspa:…", "feeBps": 150 } }
Inclusive range, at most 7 days wide. Event types: swap (buys, sells, and buyback burns with metadata.burn), join and exit (liquidity).
{ "events": [
{ "block": { "blockNumber": 412398050, "blockTimestamp": 1792489993 }, "eventType": "swap",
"txnId": "…", "txnIndex": 0, "eventIndex": 0, "maker": "kaspa:…", "pairId": "…",
"asset1In": "250", "asset0Out": "1371428", "priceNative": "0.000182",
"reserves": { "asset0": "…", "asset1": "…" } },
{ "eventType": "join", "amount0": "5000000", "amount1": "90", … } ] }
CoinGecko DEX API
[{ ticker_id: "<token id>_KAS", base, target: "KAS", pool_id }]
ticker_id, base_currency, target_currency, pool_id, last_price, base_volume and target_volume (24h), liquidity_in_kas, liquidity_in_usd, high, low.
{ buy: [...], sell: [...] }, each with trade_id (txid), price, base_volume, target_volume, trade_timestamp (ms), type. Times in ms or seconds; limit up to 1,000.
Caching
Responses are cached for 2 to 60 seconds. Poll latest-block, then request events from your last block + 1.
Support and terms
- Telegram: the KasForge group, topic 🆘 Help & Support.
- Discord: #support on the PumpForge Discord (screenshot, time and what you clicked).
- X: @Pump_Forge_ for news. Email: contact@pumpforge.tech
- Partners: sign up at /partners; for higher limits or a self-built integration, contact us there.
- Safety: the team never DMs first and never asks for a seed phrase or private key. Only use addresses ending in
.pumpforge.tech.
Versioning
The API is versioned in its path (/api/v1). Contract versions are reported per coin (contracts). Older coins keep working on their own contracts.
Attribution
When you show KasForge data, link the coin to https://kaspa.pumpforge.tech/coin/<token id> and label it “KasForge”. Coins are launched by their creators, not by PumpForge.