Skip to content

Bridge USDT in

Bridging in turns USDT on Ethereum, or BSC-USD on BNB Chain, into kUSDT on Kaspa L1. You lock the USDT in the vault on that chain. After the deposit is final, the bridge signers approve it and kUSDT is created at your Kaspa address.

Item Why
USDT on Ethereum, or BSC-USD on BNB Chain The amount you bridge, between 10 and 8 000 USDT per deposit at the launch (see Limits)
An EVM wallet with some ETH or BNB: MetaMask, or a phone wallet through WalletConnect To pay gas for two transactions: approve and deposit
A Kaspa address Where your kUSDT will arrive: a normal (Schnorr) address, kaspa:q…, the one your wallet shows. The web app takes no other kind. It refuses a script address (kaspa:p…, which is also where an explorer shows each kUSDT coin) and an ECDSA address, because no wallet here can move or redeem kUSDT from either, and an address whose key is no point of the curve, which nothing could ever spend from (since run 21 round 2)

The vaults hold the real tokens: USDT on Ethereum, 0xdAC17F958D2ee523a2206206994597C13D831ec7 (6 decimals), and BSC-USD on BNB Chain, 0x55d398326f99059fF775485246999027B3197955 (18 decimals).

Bridge in: from a USDT deposit to kUSDT on KaspaThe user deposits USDT into the vault, which emits a Deposit event with a nonce. After the deposit's block is finalized, each of the five signers reads the event from its own RPC, checks it, and signs the mint digest. The coordinator collects at least three signatures and submits a mint transaction to BridgeMint on Kaspa. BridgeMint checks the quorum, the nonce and the limits, and creates the recipient's KCC20 state.UserEVM walletKusdtVaultEthereum or BNB ChainSigners (5)each on its own nodesCoordinatoruntrusted relayBridgeMintKaspa L1deposit(units, scheme, owner)after approving units × scale1emits Deposit(nonce, …,units, fee, minted)23Finality: wait until the deposit's block is at or below the chain's finalized blockreads the eventfrom the signer's own RPC4checks nonce, recipient, limits;Schnorr-signs the mint digest53 or more signaturesSchnorr, 64 bytes each6mint(chain, first_nonce, …)1 to 3 consecutive deposits7checks quorum, nonce, limits;creates KCC20 state(s)8kUSDT arrives in the recipient's KCC20 stateamount = minted9
Bridge in. Numbers match the steps on this page. Anyone may submit the mint transaction; the coordinator is only a convenience.
  1. Deposit. On the web app’s Bridge page, set From to your chain and To to Kaspa, then enter the amount and your Kaspa address. The app converts the address into a KCC-2 owner (see Kaspa recipients). Your EVM wallet then asks you to approve the vault to take exactly that amount, and then to make the deposit (depositAtLeast, which names the least kUSDT you accept: see What you receive). On Ethereum there can be a third prompt first: Ethereum’s USDT refuses to change a non-zero allowance, so the app resets an old allowance to 0 before it approves. The app then follows the deposit in its own window until it is minted. You can close the window: the bridge keeps going, and a tag stays in the corner of the page until it is done. Stay on the Bridge page until your wallet has sent the deposit itself: if you leave it between the approval and the deposit, the app stops there, asks your wallet for nothing more and tells you so (the approval stays in place for your next bridge, and no USDT has moved).
  2. The vault records it. The vault takes the USDT, keeps the fee, and emits a Deposit event with the next deposit number (the nonce) and the amount to mint.
  3. Finality. The bridge waits until the deposit’s block is at or below the chain’s finalized block, the point after which the chain does not reverse it. See Finality.
  4. Each signer reads the deposit from its own Ethereum or BNB Chain node. It never relies on what another party reports.
  5. Each signer checks and signs. A signer checks the event and signs the mint digest, a hash that names the kUSDT deployment, the chain, the nonce, your owner and the amount.
  6. The coordinator collects signatures. The coordinator is a relay that gathers at least 3 signatures.
  7. Mint. A mint transaction is submitted to BridgeMint on Kaspa. One transaction can mint 1 to 3 consecutive deposits of the same chain.
  8. BridgeMint checks everything on-chain: the 3 signatures, that the nonce is the next one for that chain, the rate limit, the hard cap, and the exact shape of the new kUSDT state.
  9. Your kUSDT arrives as a KCC-20 state owned by your Kaspa address, holding exactly the minted amount.

You receive minted = units − fee. The fee is 0.50 % of the deposit, at least 0.50 USDT, as long as the whole deposit fits under half of that vault’s deposit meter (below): on mainnet at the launch, as long as the meter and your deposit together come to at most 6 250 USDT. On an empty meter that is every deposit up to 6 250 USDT; the part of a larger one above that pays a little more (the 8 000 USDT row below). The proportional part rounds up to the next base unit (10⁻⁶ USDT).

With the meter empty (mainnet at the launch):

Deposit Fee kUSDT minted
10 USDT 0.50 9.50
100 USDT 0.50 99.50
250 USDT 1.25 248.75
1 000 USDT 5.00 995.00
8 000 USDT 44.90 7 955.10

Below 100 USDT the 0.50 USDT minimum applies. Above it, the 0.50 % rate applies, up to 6 250 USDT: 8 000 USDT pays 0.50 % on its first 6 250 and a little more on the last 1 750, which go in above half the meter.

When the day’s deposits have filled the meter past half, the fee is higher. With the mainnet values, the deposit fee rises with the deposits made on that chain in the last 24 hours. Each vault keeps a meter of them, 12 500 USDT at the launch (a quarter of the signers’ daily limit). The part of a deposit that goes in while the meter is under half full pays the plain 0.50 %. From half full the rate rises in a straight line, to 2.50 % when the meter is full. So 8 000 USDT pays 68.90 USDT (0.86 %) with 2 500 USDT already in the meter, and 137.50 USDT (1.71 %) with 6 250. The meter drains over a day, so the fee comes back down by itself. The rule and more examples are on Fees. Bridging back never pays more than the flat fee.

  • The page shows the fee you would pay now. When the day’s deposits have raised it, it says so, and names the usual fee.
  • You get what you were shown, or nothing is sent. Someone else’s deposit can land just before yours and raise your fee a little. The web app and the wallet tell the vault the least kUSDT you accept: what they showed you, less a quarter of a percent of the deposit. If the fee has risen by more, the vault refuses the deposit and takes no USDT (you pay only the gas of the failed transaction). The web app also reads the fee again right before you sign, and if it has moved too far it sends nothing and shows the new figures.

Your new kUSDT state also carries 1.5 KAS (the deployment’s token value). Kaspa requires every output to carry KAS in proportion to the storage it uses, and covenant outputs count double (see Storage mass). The coordinator’s Kaspa funding pays it, out of the deposit fee. From then on the KAS is yours: it stays in your token UTXO and travels with the token when you spend it.

The wait is mostly the source chain’s finality. After that, the signers, the coordinator and a Kaspa confirmation add a short delay. A busy day can add more: minting draws on an allowance of 100 000 USDT at the launch that refills over 24 hours, and a deposit waits if the allowance is used up. See Limits.

  • The deposit reverts. Nothing is taken. Common causes: an amount outside 10 to 8 000 USDT (the launch limits), a missing approval, the vault being paused, or a fee that rose past what you were shown (MintedBelowMinimum): look at the new figures and try again.
  • The deposit is never minted. Deposits are minted strictly in nonce order. If a deposit can never be minted, 4 of the 5 signers can skip its nonce on Kaspa, and the vault then refunds exactly the amount it would have minted to the address that made the deposit. See Refunds.

Developers can call the vault directly. units is the amount in base units of 10⁻⁶ USDT, whatever the token’s decimals:

// Approve units × scale of the token first. scale = 1 on Ethereum, 10^12 on BNB Chain.
uint64 nonce = vault.deposit(units, ownerScheme, owner);
// Or, to refuse a fee that rose since you read it (it reverts unless at least minMinted is minted):
// uint64 nonce = vault.depositAtLeast(units, ownerScheme, owner, minMinted);

vault.depositFeeOf(units) answers the fee a deposit of units would pay in the current block. With plain deposit you accept whatever the fee is when your transaction lands.

ownerScheme and owner come from your Kaspa address as described in Kaspa recipients. A wrong owner cannot be corrected after the mint, so check the conversion with a small deposit first.