Skip to content

Swap KAS and kUSDT

KasPool is a KAS⇄kUSDT pool on Kaspa L1. It holds a reserve of KAS and a reserve of kUSDT and prices every swap by the constant-product rule: after a swap, the product of the two reserves may not shrink. Each swap is a single Kaspa transaction.

  1. Get a quote. Your app reads the pool’s current state: the KAS reserve X and the kUSDT reserve Y.
  2. Build the transaction. The app builds a transaction that spends the pool UTXO, the pool’s kUSDT reserve and your own coins, and names the exact amount you receive.
  3. Sign and submit. Your wallet signs your inputs. The pool covenant accepts the transaction only if the reserves after the swap satisfy the constant-product rule with the fee applied.
A KasPool buy transaction (KAS in, kUSDT out)Inputs: #0 Pool (entry buy; KasPool leader); #1 kUSDT reserve (KCC20) (transfer leader; owner = pool ID); #2 Buyer's KAS coins (pay kas_in and the network fee). Outputs: #0 Pool (successor) (X + kas_in − cut; protocol KAS + cut); #1 kUSDT reserve (successor) (amount Y′ + protocol tokens); #2 Buyer's kUSDT state (amount = buyer_state.amount); #3 KAS change (plain output). The pool checks (X + 0.995·kas_in) · Y′ ≥ X · Y.InputsOutputsOne transactionPool.buy(kas_in, buyer_state)spends the exact pool UTXOit was built onchecks, in 128-bit integers:(X + 0.995·kas_in) · Y′≥ X · Y#0 Poolentry buy; KasPool leader#1 kUSDT reserve (KCC20)transfer leader; owner = pool ID#2 Buyer's KAS coinspay kas_in and the network fee#0 Pool (successor)X + kas_in − cut; protocol KAS + cut#1 kUSDT reserve (successor)amount Y′ + protocol tokens#2 Buyer's kUSDT stateamount = buyer_state.amount#3 KAS changeplain outputKasPool familykUSDT familyplain KAS (no covenant)X = KAS reserve, Y = kUSDT reserve, cut = 0.05 % protocol share
A buy: KAS in, kUSDT out. Two covenant families move in one transaction; the pool forces the reserve’s successor.

Every swap pays 0.50 % of its input: 0.45 % stays in the pool for liquidity providers, 0.05 % accrues to the protocol. The best amount a swap can return is:

effective = floor(input × 9 950 / 10 000)
output = floor(reserve_out × effective / (reserve_in + effective))

For a buy, the input is KAS, reserve_in is X and reserve_out is Y. For a sell, the input is kUSDT, reserve_in is Y and reserve_out is X. Asking for one base unit more than this quote is rejected.

Pool You send You receive (quote)
10 000 KAS and 1 000 kUSDT 100 KAS about 9.85 kUSDT

A round trip (KAS to kUSDT and back) returns a little less than you started with, about the 1 % paid in fees. You also pay the normal Kaspa network fee in KAS. The wallet shows about how much before you swap, at the feerate its Kaspa node names, and sends nothing if the node names more than half as much again by the time the swap is built. Nor does it send a swap that would leave the network change too small to keep (under 0.2 KAS, more at a high feerate) beyond what was shown: it tries other coins, or asks you to merge your KAS or change the amount a little. A buy of Max keeps 0.3 KAS for the fee, and the fee row then says “up to 0.3 KAS”.

A swap transaction spends the exact pool UTXO it was built on and names the exact amount you receive. Three things follow:

  • Nobody can worsen your price after you sign. If another swap lands first, it spends that pool UTXO. Your transaction then becomes invalid, rather than executing at a worse price.
  • You may need to retry. In a busy moment your app may have to re-quote and re-sign against the new pool state.
  • The wallet asks before a worse price. It goes ahead on its own only if the new quote is at least as good as the one you confirmed. Your slippage minimum stays the hard floor. kUSDT Wallet asks in its own window.

A sell is the mirror image. Your kUSDT state is an input, any remaining kUSDT returns to you as change, and the KAS goes to an output you choose.

A very small sale can be refused. The network keeps change only from 0.2 KAS up, and the wallet’s builders leave less than that to the network fee. When you sell a part of a kUSDT state and hold no other KAS, what the sale brings is that change: if less than 0.2 KAS of it is left after the network fee, all of it would go to the fee. The wallet refuses such a sale before it signs anything and says why. Sell more, sell all of that kUSDT (the 1.5 KAS under it then comes back with the proceeds), or hold some KAS first. It also refuses a sale whose network fee is as large as what the sale brings.

A KasPool sell transaction (kUSDT in, KAS out)Inputs: #0 Pool (entry sell; KasPool leader); #1 kUSDT reserve (KCC20) (transfer leader; owner = pool ID); #2 Seller's kUSDT state (transfer_delegator; owner signs). Outputs: #0 Pool (successor) (X − kas_out); #1 kUSDT reserve (successor) (amount Y′ + protocol tokens + cut); #2 Seller's kUSDT change (amount = change_state.amount); #3 KAS to the seller (plain output, less the network fee). The pool checks (Y + 0.995·in) · X′ ≥ Y · X.InputsOutputsOne transactionPool.sell(kas_out, change_state)spends the exact pool UTXOit was built onchecks, in 128-bit integers:(Y + 0.995·in) · X′≥ Y · X#0 Poolentry sell; KasPool leader#1 kUSDT reserve (KCC20)transfer leader; owner = pool ID#2 Seller's kUSDT statetransfer_delegator; owner signs#0 Pool (successor)X − kas_out#1 kUSDT reserve (successor)amount Y′ + protocol tokens + cut#2 Seller's kUSDT changeamount = change_state.amount#3 KAS to the sellerplain output, less the network feeKasPool familykUSDT familyplain KAS (no covenant)X = KAS reserve, Y = kUSDT reserve, cut = 0.05 % protocol share
A sell: kUSDT in, KAS out. The seller’s state is a delegator input; the reserve state leads the kUSDT transfer.

To bound a dump of forged kUSDT, the KAS sells take out of the pool, less what buys bring in, may be at most 10 % of its KAS reserve per hour (the circuit breaker). Buys are not limited, and each buy gives sells back the KAS it brought. If your sell is over what is left, the app tells you that the pool lets at most so much KAS out until about a given time. Sell less, or wait for the next window.

The bridge’s guardian pauses the pool on any alarm, with the vaults and the minter. While it is paused:

Stops Keeps working
Buys, sells and adding liquidity Removing liquidity: you can always withdraw your Position

Only the pool admin resumes it.

Anyone can add KAS and kUSDT in the current ratio and receive a Position: a covenant UTXO that records liquidity shares and the key that owns them. Burning the Position returns at most its share of each reserve. The owner can transfer a Position to another key. See KasPool for the exact rules.