Sepolia

Native BTC swap

A user with BTC on Bitcoin swaps it for a token on Ethereum by signing one Bitcoin transaction. A user with a token gets native BTC by sending one Ethereum transaction. In both directions TBVBTC is the hop in the middle, and the user does not need to know it is there. This is the experience TeleSwap gives with teleBTC; what holds it up here is different, and that difference is the point of this page.

Five repositories take part, and none of them can describe the whole thing alone:

Repository What it contributes
bivium-protocol-tbv FastPegOutBook (sell orders, bids, standing asks); the payout verifiers; FastPegOutRouter; the Bitcoin relay it proves against
bivium-protocol-mm the relay feeder; the market maker's two lanes: standing asks (sells TBVBTC for BTC and claims payments) and the buyer with bids (buys TBVBTC for BTC and pays)
bivium-protocol-frontend the Swap page with a BTC wallet beside the ETH wallet, and three relayer endpoints
bivium-protocol-cli nothing yet (see the end of this page)
bivium-deployments which book, verifier, router and relay belong together on each chain

The one exchange underneath: TBVBTC ⇄ native BTC

TBVBTC is the fungible claim on Delivered TBV lots (Lifecycle). Everything here is a market between TBVBTC on Ethereum and BTC on Bitcoin. That market is FastPegOutBook, and it has three ways to trade:

Who commits first Who pays BTC What proves it
Sell order A TBVBTC holder signs an order; a buyer reserves a piece with a bond the buyer the buyer's payment, recorded, then claimFill
Bid A BTC holder signs a bid and keeps credit in the book for bonds the bidder, to the address the seller names the bidder's payment, recorded, then claimFill
Standing ask A market maker deposits TBVBTC inventory the BTC holder, with no Ethereum transaction at all the payment, recorded, then claimAsk by anyone

Every payment carries one OP_RETURN, commitment(book, id, recipient) — a hash of chain id, book, order id and recipient. The verifier credits a payment only when the relay holds its block and the payment pays the order's destination in one output (the last such output is the one credited, not their sum). The book trusts nothing else: not the relayer, not the market maker, not the page.

BTC → token: one Bitcoin transaction

  1. Quote (frontend): the cheapest standing ask with room, then Uniswap's quoter along the configured hops from TBVBTC. The user sets a slippage limit.
  2. Commit (frontend, against tbv's encoding): the payment's recipient is the router, and its id is askPaymentId(askId, maxFee, keccak256(route)). The route is (recipient, tokenOut, minOutPerBtc, deadline, unwrapEth, path), encoded as six flat fields so that its first word is the final recipient. Before the wallet is asked to sign, the page checks the route against the router's own encodeRoute and the id against the book's askPaymentId.
  3. Pay (the user's BTC wallet): one PSBT, the amount to the ask's address plus the OP_RETURN. The page checks the signed transaction against the plan before it broadcasts.
  4. Describe (frontend relayer): the OP_RETURN is a hash, so a claimer needs its preimage. The page posts {txid, askId, maxFee, route, recipient} to /api/fast-pegout-ask-payments. The relayer stores it only if the transaction really carries that commitment.
  5. Relay (mm feeder → tbv relay): block headers reach the relay.
  6. Record and claim (mm asks lane, or anyone): recordPayment with a Merkle proof once the relay holds the block, then claimAsk once the verifier's confirmations are met. The claimer keeps min(maxFee, relayFee) units of TBVBTC.
  7. Swap (tbv router): the book delivers the rest to the router and calls onAskDelivery. The router swaps along the path and pays the final recipient. Below minOutPerBtc, past the deadline, or with a path that does not run TBVBTC→token, it forwards the TBVBTC instead: a payment always settles, and the worst case is TBVBTC rather than the token.

minOutPerBtc is a price, not an amount: an ask short of inventory delivers in two pieces (the claim, then the shortfall a refill credits), and each swaps at the same bound. The claimer chooses the gas, so the router gives the swap a fixed budget (SWAP_GAS) and refuses a delivery that cannot afford it. The claim then reverts with the payment unconsumed, rather than failing the swap into the fallback.

Token → BTC: one Ethereum transaction

  1. Bids (mm buyer lane → frontend relayer): the market maker signs a bid and posts it to /api/fast-pegout-bids. It keeps enough credit in the book to bond it. It sizes the bid to the BTC it holds, less what it already owes and what live bids could still be taken for, and limits each bid to a few pieces (it pays one piece at a time).
  2. Sell (frontend → tbv router): sellForBtc swaps the token for exactly the TBVBTC units, refunds what the swap did not use, and takes the bid for the user (takeBidFor), naming the user's BTC address. The user is the fill's maker.
  3. Pay, record, claim (mm buyer lane): the bidder pays the user's address with the commitment, records the payment and claims the TBVBTC. A lapse — the bidder did not pay within the window — returns the TBVBTC to the user, with half the bidder's bond.

TBVBTC → BTC: withdraw to a BTC wallet

For someone who already holds TBVBTC, "withdraw to BTC wallet" offers two speeds:

  • Fast: sell into a bid, or post a sell order. It is priced by the market maker at a small discount and done in a few blocks. This is the book above, without the swap.
  • Standard: a vault keeper pegs out a whole vault through Babylon, in about three to five days, at no discount. Babylon pays the payout to the keeper's registered script, never to the user, and only for whole vaults. So Standard has to be two steps: the keeper burns its own TBVBTC to redeem a vault (settleDelivered), then pays the user from what it receives. The app's redemption book is meant to carry the second step, but it has no reservation step yet, so a keeper who pays first can be raced.

Why there is no locker

TeleSwap lets a BTC holder mint teleBTC without anyone posting collateral first, because lockers hold the BTC and over-collateralise it. Here no one holds the BTC for the protocol. TBVBTC is backed by Babylon vaults, each a pre-signed Bitcoin covenant. The market maker pre-funds the side it sells: TBVBTC inventory in a standing ask, credit for bonds behind its bids. A BTC holder who pays an ask takes no counterparty risk beyond the market maker's inventory, which is already in the book; a seller into a bid is covered by the bond and gets the TBVBTC back if the bidder does not pay.

What this costs is concentration: liquidity in both directions sits with whoever makes the market. They need TBVBTC inventory for asks and BTC for bids, and they rebalance through minting (lock a vault, convert) and slow redemption (the Standard path).

Rules that hold between these repositories

  • The route encoding has three implementations, tbv's encodeRoute, frontend's and the one a CLI would add, and they must agree byte for byte. frontend pins its encoding, the payment id and the commitment against the deployed router, book and verifier in a test. A redeployed router re-pins it.
  • The bid typed data is signed in two places, mm (the bidder) and frontend (verifying in the relayer). Both pin the deployed book's bidDigest.
  • The relayer is a convenience, not an authority. It stores descriptions, sell orders and bids so that others can find them; the book and the verifier re-check everything. It is still trusted to list: a relayer that hid a market maker's live bids would let the market maker over-commit its BTC.
  • The relay's confirmations bound everything downstream: a payment is recordable one block below the relay tip and claimable at the verifier's MIN_CONFIRMATIONS. The page, the asks lane and the buyer lane each wait for the same thresholds, read from the verifier rather than assumed.
  • A payment to the market maker's own script (a seller naming it into a bid) must fold the change into the one output to that script. Otherwise the verifier credits the change output instead.

Vendored from bivium-protocol-doc 57ed1bdc6cfe, synced 2026-10-27. Where this and a repository disagree about that repository, the repository wins.