← Back to Docs

Swap Implementation Spec

Complete protocol specification for the trustless swap system.

Swap Flow

  1. Alice has L2 coins and wants BTC
  2. Alice creates a swap offer: "I'll give 100,000 L2 sats for 0.001 BTC to my address"
  3. Bob sends 0.001 BTC to Alice's address
  4. System monitors Bob's BTC transaction and waits for confirmations
  5. Bob claims Alice's 100,000 L2 sats

Swap States

Pending → WaitingConfirmations → ReadyToClaim → Completed
   |                                  |
Cancelled                          (on expiration)

Data Structures

SwapId

struct SwapId([u8; 32]);  // 32-byte identifier

// L2 → L1: blake3(l1_addr || l1_amount || l2_sender || l2_recipient)
// Deterministic: same parameters = same swap ID

Swap

struct Swap {
    id: SwapId,
    direction: SwapDirection,       // L1ToL2 or L2ToL1
    parent_chain: ParentChainType,  // BTC, BCH, LTC, etc.
    l1_txid: TxId,
    required_confirmations: u32,    // Default: 6 BTC, 3 others
    state: SwapState,
    l2_recipient: Address,
    l2_amount: Amount,
    l1_recipient_address: Option<String>,
    l1_amount: Option<Amount>,
    created_at_height: u32,
    expires_at_height: Option<u32>,
}

Transaction Types

enum TxData {
    SwapCreate {
        swap_id: [u8; 32],
        parent_chain: ParentChainType,
        l1_txid_bytes: Vec<u8>,        // [0u8; 32] placeholder for L2→L1
        required_confirmations: u32,
        l2_recipient: Address,
        l2_amount: u64,                 // satoshis
        l1_recipient_address: Option<String>,
        l1_amount: Option<u64>,
    },
    SwapClaim {
        swap_id: [u8; 32],
        proof_data: Option<Vec<u8>>,   // reserved for future
    },
}

Database Schema

Transaction Validation

SwapCreate Validation

  1. Swap ID: Recompute from parameters, must match tx
  2. Uniqueness: Swap with this ID must not exist
  3. Amount: l2_amount > 0
  4. Coin locking: No inputs already locked to another swap; sufficient input value
  5. Outputs: At least one output

SwapClaim Validation

  1. Existence: Swap must exist
  2. State: Must be ReadyToClaim
  3. Locked inputs: At least one input locked to this swap; all locked inputs to same swap
  4. Recipient output: At least one output to swap.l2_recipient

General Protection

All non-SwapClaim transactions: no inputs may be locked to any swap. Only SwapClaim can spend locked outputs.

Block Processing

SwapCreate (Block Connect)

  1. Reconstruct Swap object from tx data
  2. Verify swap ID matches
  3. Lock all outputs (for L2 → L1 swaps)
  4. Save swap to all databases

SwapClaim (Block Connect)

  1. Retrieve swap from database
  2. Verify ReadyToClaim state
  3. Unlock all inputs locked to this swap
  4. Mark swap Completed

Rollback (Block Disconnect)

API Endpoints

Create Swap

POST /create_swap
{
  "parent_chain": "BTC",
  "l1_recipient_address": "bc1q...",
  "l1_amount_sats": 100000,
  "l2_recipient": "0x...",
  "l2_amount_sats": 100000,
  "required_confirmations": 3
}
Response: { "swap_id": "abc...", "txid": "def..." }

Update L1 Transaction ID

POST /update_swap_l1_txid
{ "swap_id": "abc...", "l1_txid": "def..." }
Response: { "success": true }

Get Swap Status

GET /get_swap_status?swap_id=abc...
Response: {
  "id": "abc...", "state": "WaitingConfirmations",
  "current_confirmations": 2, "required_confirmations": 3,
  "l1_txid": "def...", "l2_amount": 100000
}

Claim Swap

POST /claim_swap
{ "swap_id": "abc..." }
Response: { "txid": "xyz..." }

List Swaps

GET /list_swaps
Response: [
  { "id": "abc...", "state": "ReadyToClaim", ... },
  { "id": "def...", "state": "Pending", ... }
]

Security Considerations

  1. Deterministic Swap IDs: Same parameters = same ID, preventing duplicate swaps
  2. Output Locking: Prevents double-spending of locked coins
  3. State Validation: Only valid transitions allowed
  4. Confirmation Requirements: L1 tx must be final before L2 coins release
  5. First-Come-First-Served: Race condition handled by blockchain consensus
  6. Rollback Safety: All operations properly reverted on block disconnection