ForgeVaultDocs
Risks Open app
Guide

ForgeVault

ForgeVault locks and vests tokens on Kaspa L1. You choose the token, the amount, the wallet that receives it and the dates; your wallet signs; a contract on the chain holds the tokens and releases them on schedule. ForgeVault never holds your keys or your tokens.

At a glance

ItemValue
NetworkKaspa mainnet
TokensAny KCC-20 token (KasForge, KasSeal, KaspaRocket, standard KRON tokens) and KRON's own format
KindsTime lock (one date), cliff vesting (up to three dates), linear vesting. Payment streams: coming soon
Who can collectOnly the receiving wallet, once a date has passed
ChangesNone: a lock cannot be cancelled, shortened or redirected, not even by PumpForge
CustodyNone: every transaction is signed in your own wallet
AuditTested, not independently audited (see Risks)
Guide

Locks and vesting

Three kinds of lock, all enforced by a contract on the chain.

KindHow it releasesContract
Time lockEverything at one dateForgeLock
Cliff vestingUp to three dates, each releasing its own shareone ForgeLock per date
Linear vestingNothing before the cliff, then a straight line from the start to the end dateForgeVest

How far ahead

  • Time locks and cliff dates: each date up to 10 years away (a site rule; the time-lock contract itself has no maximum date).
  • Linear vesting: the site lets it end up to about 2000 days (about 5.5 years) from now. The contract itself allows at most 2000 days from the start to the end (it keeps the vesting arithmetic inside the numbers a Kaspa script can use); the site's rule is a little stricter and simpler. For longer schedules, use cliff dates.

Making a lock

  1. Connect your wallet and pick the token. ForgeVault lists the tokens your wallet holds.
  2. Enter the amount, the receiving wallet (yours by default) and the date or dates.
  3. Check the summary: the fee, the deposits and the network fee, and what your wallet will pay in total.
  4. Sign in your wallet. The lock gets its own public page as soon as the network accepts it.
Two signaturesFor a lock with three dates, when your token piece holds more than you lock, your wallet signs twice: the first transaction splits the piece so the exact amount can be locked, the second makes the lock. If you stop after the first, the tokens simply stay in your wallet.

Collecting

  • Only the receiving wallet can collect, from the lock's page, once a date has passed (linear vesting: whatever has vested so far, at any time).
  • Unlocked tokens wait in the contract until they are collected. Nothing expires.
  • One Collect takes every unlocked date of a lock at once (KRON's own format: one date at a time).

Dates and times

Kaspa contracts count time in DAA score, which rises about ten times a second. ForgeVault turns your dates into DAA scores, so a lock can open a little earlier or later than the clock time shown, more so for dates far away. The DAA score is the rule.

Nothing can be changed

A lock cannot be cancelled, shortened, extended or redirected once it is on the chain. Check the receiving wallet and the dates before you sign.

Guide

Payment streams

A stream pays a receiver second by second between two dates, in KAS or in a token. A cancellable stream can be stopped by the payer: the receiver keeps what has unlocked and the rest returns to the payer.

Coming soon on mainnetPayment streams run on Testnet 10 today. We will open them on mainnet when they are ready; until then the Streams pages on mainnet only say "coming soon".
Guide

Supported tokens

FormatWho uses itAvailable
KCC-20 reference formatKasForge, KasSeal, KaspaRocket and standard KRON tokensTime lock, cliff vesting, linear vesting
KRON's own formatCustom KRON tokensTime lock and cliff vesting (up to three dates)

The badge next to a token says which launchpad's programs it matches. It is not a review of the token: names, tickers and logos are set by the token's creator and can imitate other projects. Always check the token id.

Guide

What you sign

ForgeVault prepares each transaction; your wallet shows it and signs it. Nothing moves until you approve.

The check before your wallet opens

Before your wallet is asked to sign, the page checks the transaction ForgeVault prepared. It stops, and nothing is signed, unless all of this holds:

  • only your own coins and the token pieces you chose are signed, with the standard signature type (SIGHASH_ALL);
  • KAS goes only back to you, into the lock, and to the ForgeVault fee wallet, which receives exactly the fee shown;
  • in total, no more leaves your wallet than the fee, the deposits and the network fee shown.

The contracts themselves also accept only that signature type, so a collect signature always covers the whole transaction and can never be reused for one that sends the tokens somewhere else.

The check runs in your browser and guards against a fault or tampering on our side. It does not protect you from a fake site or a compromised device: use only vault.pumpforge.tech, and read what your wallet shows.

Prepared transactions

A prepared transaction is valid for 5 minutes and can be sent once. After that, start again.

Accepting the terms

The first time a wallet uses ForgeVault, it signs its acceptance of the Terms, Privacy Policy and Risk Disclosure: a message, or with wallets that cannot sign messages, a transaction that is never sent. No KAS moves. It is asked again only when the terms change.

Guide

Wallets and phones

WhereHow to connect
ComputerThe Kasware, Kastle or Kaspire browser extension, or the Kaspire app on your phone by scanning a QR code (WalletConnect)
Phone, Chrome or SafariPick Kaspire: the Kaspire app (Android) connects with WalletConnect. Your phone switches to Kaspire to approve, then back.
Phone, Kastle or Kasware appOpen vault.pumpforge.tech inside the app's own browser and connect there. ForgeVault shows the steps and copies the link for you.

Wallet names

Where a wallet has a .kaspa or .kas name, ForgeVault shows the name in place of the address. Names come from public name services and are for display only; the summary before you sign always shows the address itself.

Guide

Fees and deposits

ItemAmount
Lock or vestingAbout $10, paid in KAS at the last hour's average KAS price (shown before you sign)
Collecting, merging piecesNo ForgeVault fee
Network feeEvery transaction, usually a small fraction of a KAS
DepositsA small amount of KAS that each lock piece and lock coin needs to exist on the chain (about 1.2 KAS per date, up to 3 KAS). Not a fee: it comes back when the lock is collected.

The live amounts are on the Fees page.

Trust

Verify a lock

You don't have to trust this site: a lock is a contract on the chain, and anyone can check it.

How a lock holds tokens

A locked token piece is owned by a script, not a wallet: its owner is the hash of the lock contract (KCC-20 owner scheme 3, pay-to-script-hash; KRON: a script owner). The token then moves only together with a KAS coin locked to the same script, and that coin opens only by the contract's rules: the receiving wallet's signature, after the date.

Check it

  1. Open the lock's page and copy the token id; or find the lock in the locked tokens feed.
  2. In the feed, contract.redeemScript is the lock's contract. Its BLAKE2b-256 hash must equal holder.hash, and that must be the owner of the token piece on chain (open the token on Kascov and find the holder holder.address). On your own node, the piece at tokensOutpoint should show owner scheme 3 with that hash, and borrowing disabled (borrow scheme 0).
  3. Read the script: for a time lock it names the receiving wallet's key and the unlock DAA score (layout in Contracts).
  4. Or let a tool do steps 2 and 3 for every lock: the public repository has a Rust checker that rebuilds each lock's script from the published source with its arguments, and checks the feed's dates, wallets and token against it, and a quick JavaScript check for time locks. Values a script does not contain (a time lock's token and amount, a vesting's current balance) are shown as "feed only": confirm those on the chain.

If the hash matches, the script is the rule the chain enforces: no one, including PumpForge, can move the tokens any other way.

Trust

Risks

  • Not audited. The contracts are tested against Kaspa's own transaction rules and the live token programs they hold, but have not been independently audited. Only lock what you can afford to lose.
  • Final. A wrong amount, date or receiving wallet cannot be fixed.
  • Dates are estimates. The DAA score is the rule; clock times shown are estimates.
  • Tokens. A lock only proves tokens are held until a date; it says nothing about a token's value or team.
  • Keys. If the receiving wallet's key is lost, nobody can collect, including PumpForge.
  • Lock addresses. Never send tokens or KAS to a lock's address by hand: only locks made through ForgeVault are tracked, and KAS sent to a vesting's address after it is fully collected stays there.
  • Your device. Sign only on vault.pumpforge.tech and read what your wallet shows. A fake site or a compromised device can ask you to sign something else; no contract can protect against that.
  • Service. If ForgeVault is offline the contracts keep working and the tokens stay locked for the receiving wallet; collecting through the site waits until it is back.

The full text: Risk Disclosure.

Build

For explorers and indexers

When tokens are locked, the token's holder list shows the lock contract as a holder: a script address (kaspa:p…). ForgeVault publishes which of those holders are locks, so an explorer can show them as locked instead of as a wallet.

Marking locked holders

  1. Fetch GET /api/v1/locked (all open locks) or ?token=<token id> for one token, every few minutes.
  2. For each lock, holder.hash is the owner of a token piece (KCC-20: owner scheme 3 with that owner; KRON: script owner type 1). holder.address is the same as a kaspa:p… address.
  3. Check it: BLAKE2b-256 of contract.redeemScript must equal holder.hash (see the snippet). Never mark a holder from the feed alone.
  4. Show it, for example: Locked · unlocks 12 Mar 2027 · ForgeVault, linking to page. For linear vesting use linear.endAt and say "vesting".
Why the check mattersThe hash check proves the holder really is a contract with those rules. A wrong entry in the feed cannot make a wallet look locked, because a wallet's key is not the hash of a lock script.

What the feed covers

  • Open locks made through ForgeVault: time locks, cliff vesting dates and linear vestings.
  • A lock leaves the feed once its tokens are collected (they leave the script).
  • Unlocked but not yet collected tokens stay in the feed with status: "unlocked": they still sit in the contract.
  • Linear vestings made before 26 October 2026 used an older contract and are not listed.

The lock's KAS coin

Each lock also holds a small KAS coin (the deposit) at the same script address (lockCoinOutpoint). It is part of the lock, not anyone's balance.

Build

Locked tokens feed

Every open ForgeVault lock, with the holder it appears as and its contract script. Public, no key, readable from any origin (CORS *).

GET/api/v1/locked

Query parameters

ParameterMeaning
tokenOnly this token (64-hex token id)
holderOnly this holder: a kaspa:p… address or the 64-hex hash
beneficiaryOnly locks that release to this wallet address

Response

{
  "ok": true, "version": 1, "network": "mainnet",
  "daa": 412345678, "now": 1793049024, "count": 1,
  "locks": [{
    "id": "34f2…2752:0",            // the lock piece (stable id)
    "lock": "34f2…2752",             // the lock (one page; a cliff vesting has one piece per date)
    "page": "https://vault.pumpforge.tech/lock/34f2…2752",
    "token": "abab…abab", "format": "kcc20", "kind": "time-lock",
    "holder": {
      "address": "kaspa:pphwmvrd…zppa",
      "hash": "6eedb06d…cebbf",
      "owner": { "ownerScheme": 3, "owner": "6eedb06d…cebbf" }
    },
    "amount": "300000", "claimable": "0", "status": "locked",
    "beneficiary": "kaspa:qpx5…pmd", "creator": "kaspa:qqdc…q3",
    "unlockDaa": 418000000, "unlockAt": 1800000000, "linear": null,
    "tokensOutpoint": "34f2…2752:0", "lockCoinOutpoint": "34f2…2752:2",
    "createdTxid": "34f2…2752", "createdAt": 1793000000,
    "contract": { "name": "ForgeLock v4", "redeemScript": "76043f64…6a68",
      "args": [ { "name": "beneficiary", "type": "pubkey", "value": "4d4b…0766" }, { "name": "unlockDaa", "type": "int", "value": 418000000 } ] }
  }]
}

Fields

FieldMeaning
holder.hash, holder.addressThe token piece's owner: the lock script's hash, and the same as a script address
holder.ownerHow the token's state names it: KCC-20 {ownerScheme: 3, owner}; KRON {kronOwnerType: 1, owner}
amountTokens in the piece now, in base units, as a string (amounts can exceed 253)
claimableOf those, how many the receiver could collect now (null if the chain could not be read)
statuslocked, unlocking (linear vesting under way), unlocked (all collectable, not yet collected), unknown
kindtime-lock (also each date of a cliff vesting) or linear-vesting
unlockDaa, unlockAtUnlock DAA score (the rule) and its estimated unix time. Linear vesting: the end.
linearFor linear vesting: total, startDaa/cliffDaa/endDaa and the estimated startAt/cliffAt/endAt
contract.redeemScriptThe lock contract (hex). BLAKE2b-256 of it is holder.hash.
contract.argsThe arguments the script was compiled from (name, type, value, in the contract's order). Compiling the published source with them gives redeemScript byte for byte.

Stability and limits

  • /api/v1/… is versioned: fields are not removed or renamed in v1; new fields may be added.
  • Up to 600 requests a minute per address. One full fetch every few minutes is plenty.
  • Questions or a higher limit: contact@pumpforge.tech.
Build

Contracts

Locks use plain pay-to-script-hash contracts written in SilverScript. Their sources are public.

GET/api/v1/contracts

ContractUsed forArguments
ForgeLock v4Time locks and each date of a cliff vestingbeneficiary (32-byte x-only key), unlockDaa
ForgeVest v6Linear vestingbeneficiary, total, start/cliff/end DAA, the token's template, the token id and a salt

Compiler: SilverScript 1.0.0 (kaspanet/silverscript, commit 3ed97333). Compiling a source with a lock's arguments (contract.args) gives its redeemScript byte for byte.

Verify every lock yourselfThe contracts and two checkers are public at github.com/Pump-Forge/forgevault-contracts: a Rust tool that rebuilds each lock in the feed from source, and a quick JavaScript check that needs no compiler.

ForgeLock layout

A ForgeLock script is fixed bytes around its two arguments:

76043f64dcc7876375768201419d75   // fixed
<unlockDaa>                      // the unlock DAA score as a minimal script-number push
7600050088526a74a569b07676827c75519601419c6976014001417f010187697820
                                 // fixed (checks the SIGHASH_ALL byte; ends with a 32-byte push)
<beneficiary>                    // 32-byte x-only public key of the receiving wallet
ac69757551676a68                 // fixed

So the receiving wallet and the unlock score can be read straight from the script, and a script with other fixed bytes is not a ForgeLock.

Check a lock (JavaScript)

import { blake2b } from '@noble/hashes/blake2b';
const r = await fetch('https://vault.pumpforge.tech/api/v1/locked?token=' + TOKEN_ID);
const { locks } = await r.json();
for (const l of locks) {
  const h = Buffer.from(blake2b(Buffer.from(l.contract.redeemScript, 'hex'), { dkLen: 32 })).toString('hex');
  if (h !== l.holder.hash) continue;           // not proven: do not mark
  markLocked(l.holder.address, l);               // e.g. "Locked until …, ForgeVault"
}

Kaspa's pay-to-script-hash uses the same hash: the output script is OP_BLAKE2B OP_DATA_32 <hash> OP_EQUAL.

Build

Other endpoints

The site's own endpoints. They are public but shaped for ForgeVault's pages and may change; for integrations use /api/v1.

GET/api/status

Network, node, fees and counts.

GET/api/locks

Locks grouped as the pages show them. ?token=, ?address=.

GET/api/lock?id=

One lock with its dates and collects.

Build

Support and legal

Nothing in these docs is financial advice.