Skip to content

KCC-20 tokens

KCC-20 (“Fungible Token Covenant Specification”) is the Kaspa convention for fungible tokens. It fixes the token state, the transfer interface and the program information that wallets and indexers read. kUSDT’s token actor is the unmodified KCC-20 reference implementation (argent-lang/kcc20-reference).

Every token UTXO carries one KCC20State:

Field Type Meaning In kUSDT
amount int Token quantity, never negative Base units of 10⁻⁶ kUSDT
owner byte[32] Who owns it, read through owner_scheme See Owner schemes
owner_scheme byte The KCC-2 scheme of owner 0x00 to 0x04
borrow_scheme byte Whether and how others may borrow the UTXO 0x00 (disabled) in every minted state
borrow_guard byte[32] Data for the borrow scheme 32 zero bytes in every minted state
extension_commitment byte[32] Hash of application-specific extended state Always 32 zero bytes

States are fungible with each other only if their extension_commitment is equal. Every kUSDT state uses zero, so all kUSDT is one fungible token.

The default KCC-20 configuration has two entrypoints:

transfer(KCC20State[] next_states, byte[] witness) // the leader
transfer_delegator(byte[] witness) // every other token input

In a transfer, the first token input of the family is the leader. It checks the whole transition:

  • next_states lists every token output of the family, in order, and each output carries exactly that state;
  • the total amount out equals the total amount in;
  • every output uses a supported owner scheme, so no transfer can create an unspendable state;
  • every input and output has the same extension_commitment.

Each other token input is a delegator and checks only that its own owner approved.

The first byte of the leader’s witness selects the path: 0x00 is a normal owner-approved transfer, 0x01 is a borrowed receive. The rest of the witness carries the owner’s authentication:

Owner scheme Authentication bytes
p2pk-schnorr/v1 A 65-byte transaction signature
p2pkh-schnorr/v1 The 32-byte public key, then a 65-byte transaction signature
p2pkh-ecdsa/v1 The 33-byte compressed public key, then a 65-byte transaction signature
p2sh/v1 One byte: the index of the authority input
covenant-id/v1 Nothing

A transfer has 1 to 3 token inputs and 1 to 3 token outputs.

KCC-20 standardizes transfers, not issuance. The reference ships a KCC20PublicMint app that lets anyone mint; kUSDT does not use it. In kUSDT the only way new tokens appear is BridgeMint, which needs 3 of the 5 signers. See BridgeMint.

TokenSeed is a reference actor that creates zero-amount token states, so someone can prepare a receiving UTXO. Its create entry requires the new state’s amount to be exactly 0, so it cannot issue tokens. Its other entries split a seed, let the seed’s owner rebalance its KAS deposit, and reclaim extra seeds, always leaving one seed alive. kUSDT’s genesis creates one TokenSeed.

Each KCC-20 covenant publishes a program artifact: the information needed to decode its state and build transfers (ABI types, state location, entrypoints, templates, supported owner schemes and transfer bounds). kUSDT’s artifact is checked into the repository at bridge/kaspa/artifacts/kusdt.json, and a test fails if it no longer matches the contracts.