System Architecture
End-to-end view of how Bitcoin, the SPV Relayer, the four Soroban contracts, and the browser interact.
- Bitcoin — P2WSH locks collateral; two spending paths (cooperative co-sign or CLTV timelock)
- SPV Relayer — watches Bitcoin, produces Merkle inclusion proofs on demand
- Soroban contracts —
bitcoin-spv,zk-verifier,commitment-tree,private-lendverify proofs and manage positions - Browser — generates all ZK proofs locally; private witness values never leave the device
Deposit Flow
Step-by-step path from connecting a Bitcoin wallet to having an active position on Stellar.
- Connect Bitcoin wallet (Xverse) and Stellar wallet (Freighter)
- Derive unique P2WSH address from protocol key + user key + timelock height
- Send BTC to that address on-chain
- Relayer produces SPV proof (block headers + Merkle path)
- Browser generates Groth16 ZK proof binding commitment to the Bitcoin txid
commitment-tree.deposit()verifies SPV proof + ZK proof on Soroban- Admin calls
insert_commitment()— position becomes active
Borrow & Repay Flow
How the protocol updates the Merkle commitment on every borrow or repay, preserving privacy throughout.
- Borrow:
delta = amount_stroops,is_borrow = 1 - Repay:
delta = (FIELD_PRIME − amount) mod FIELD_PRIME,is_borrow = 0 - The nonce rotates on every action; the commitment
Poseidon(collateral, debt, secret, nonce)is replaced in the tree
BTC Release Flow (Path A)
Cooperative co-signed release after full repayment.
- The server (
/api/cosign) verifies the commitment is no longer pending before signing PROTOCOL_SIGNING_KEYis server-only — never exposed to the browser- Final witness:
[user_sig, protocol_sig, 0x01, redeemScript]
ZK Circuits
All three Groth16 circuits (Circom / BN254), their private inputs, public inputs, and public outputs.
| Circuit | Purpose |
|---|---|
deposit.circom | Binds a Poseidon commitment to a Bitcoin txid |
borrow_repay.circom | Proves Merkle inclusion + valid collateral ratio after state change |
liquidation.circom | Proves position is under-collateralized |
Commitment State Machine
Complete lifecycle of a position from pending to BTC release (or liquidation).
| State | Description |
|---|---|
| Pending | deposit() verified, waiting for insert_commitment() |
| Active · debt=0 | Commitment in Merkle tree, no outstanding debt |
| Active · debt>0 | USDC borrowed; nonce rotates on every partial repay |
| Closed | Full repayment done; old nullifier spent |
| Released | Path A PSBT finalized; BTC returned on Bitcoin |
| Liquidated | Ratio below 120%; keeper repaid debt |
Soroban Contract Interactions
How the four live testnet contracts call each other.
| Contract | Role |
|---|---|
bitcoin-spv | Verifies Bitcoin SPV proofs (block headers + Merkle path) |
zk-verifier | Groth16 verification via Protocol X-Ray host functions |
commitment-tree | Merkle tree of commitments; orchestrates all flows |
private-lend | USDC liquidity pool; lender deposits + borrower drawdowns |
Regenerating Diagrams
docs/diagrams/output/*.svg and *.png