epic: btc/qtc swaps through arbitrated multisig escrow #54
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
A swap between QTC and BTC that runs entirely on infrastructure we and the makers control, where makers set their own prices, and where no single party can take funds. The QTC leg is held in a per-trade 2-of-3 multisig (buyer, seller, arbiter) using the multisig pallet that exists on runtime 152, so nothing here waits on a runtime upgrade. The BTC leg is a plain payment observed by an automated judge on our own Bitcoin node.
This is trust-minimized, not trustless, and every screen and document says so: the escrow replaces the chain's enforcement with an arbiter who can never move funds alone and can never redirect them, only choose between the two outcomes the parties agreed to before funding.
Mechanism (facts from the pallet on 152)
create_multisig([buyer, seller, arbiter], threshold 2, nonce = trade id)yields a deterministic address any party can verify before funding. Creation costs 0.03 QTC, burned. Signers are sorted, so order is irrelevant.executeresubmits the bytes and the pallet checks equality, so what is displayed is what runs. Only the proposer can cancel. A proposal costs 0.05 QTC plus a 0.01 QTC refundable deposit, plus 1% per signer.utility.batch_all[ M → seller ], proposed by the seller at funding time with the trade deadline as expiry. Needs the arbiter (dispute) or the buyer (mutual abort).utility.batch_all[ M → buyer (amount − fee), M → fee account (fee) ], proposed by the buyer only after paying BTC. Needs the seller (happy path) or the arbiter (seller unresponsive, payment proven).Safety concerns, by party
Buyer (pays BTC, receives QTC)
Seller (funds QTC, receives BTC)
Arbiter (our infrastructure)
Makers (run their own daemon)
Everyone
Operator-owned decisions
Definition of done
On Planck plus Bitcoin signet, from an unmodified wallet against the deployed coordinator and arbiter: a taker buys QTC with BTC from a maker daemon and receives it after the seller's approval; a second trade where the maker goes silent resolves through the judge and the arbiter's approval; a third where the buyer never pays refunds through the seller's standing proposal and the arbiter; a fourth where the arbiter's hot signer is down resolves through the cold path. Each with measured wall-clock time and chain fees recorded on this epic. Then the same on mainnet with real BTC at the smallest sensible amount.
Children, in dependency order: #55 (multisig spike on a dev node) and #56 (bitcoind on our infra) can start now, in parallel → #57 (protocol document and entities) → #58 (wallet-arbiter), #59 (coordinator in wallet-api) → #60 (wallet-maker), #61 (taker flow in the wallet) → #62 (bonds and limits) → #63 (rehearsal on Planck plus signet, then mainnet).
Decisions this epic needs before #58: fee rate and fee account, confirmation tiers, caps and kill-switch holder, hosts for bitcoind and the arbiter. Bond sizes before #62. Recorded as comments on those issues when made.
Sequencing note: #57 depends on #55's measured facts, and #61 depends on #28 and #39 from the desktop and Intents epics, so the taker screens land after the v1 send flow exists.
Correction, 2026-09-15: no bonds
The epic body and the original #62 assumed Bisq-style security deposits from both parties. That does not fit this market: only miners and the team hold QTC, so a QTC bond is a barrier to entry for buyers, and buyers are the side without which nothing works. A seller bond adds nothing either, because the judge already denies a seller any gain from walking away once BTC is paid.
Bonds are removed from the design. What bounds a no-show instead, now specified in #62: a payment deadline measured in minutes and enforced as the refund proposal's expiry, automatic refund approval by the arbiter when the deadline passes unpaid, mempool acceptance extending the deadline into the confirmation window, and maker-declared exposure and per-taker limits enforced at trade creation. The seller's cost of a no-show becomes the payment window plus proposal fees, priced into the maker's spread.
Where the epic body says "bonds and unbonded caps" under the arbiter's griefing concern and lists a bond policy as an operator decision, read #62 instead; the body is left as written so this correction stays legible.
Sequencing decision, 2026-09-15
This epic is deferred to the end of the plan, after every other epic. It depends on the wallet being useful first: a swap needs takers who already hold and move QTC in this wallet, and the taker flow (#61) is built on the v1 send review (#28) and the order state machine (#39) in any case. Nothing here starts, including the spike (#55) and the Bitcoin node (#56), until the desktop, packaging and Intents epics have shipped and there are users to swap.
The design stays filed as written so the decisions and corrections above are not lost.