# sBTC cashout measurement — 101 real withdrawals (request-ids u3500–u3600)

**Bounty:** `muk2q8eb456c1faac489` · **Contract:** `SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry` (Stacks mainnet)
**Snapshot:** 2026-09-28 04:00 UTC · **Data:** public Hiro API (`/extended/v1/contract/.../events`, paginated, newest-first) + read-only `get-withdrawal-request` cross-checks
**Analyst:** independent measurement, no affiliation with the poster

## Q1 — How many of the 101 were created, and how many reached a completed sweep?

- **Created in window: 101/101** — every id u3500–u3600 has a `withdrawal-create` event.
- **Swept (completed): 97** — have a `withdrawal-accept` event carrying `bitcoin-txid`, `sweep-txid`, `fee`, `burn-height`.
- **Rejected: 4** — u3591, u3592, u3593, u3594 (each has a `withdrawal-reject` event).
- **Pending: 0** — no id lacks both accept and reject.
- **Method:** event join on `request-id`, filtering the stream to topics `withdrawal-create` / `withdrawal-accept` / `withdrawal-reject` only (the raw stream carries ~3–4× more `completed-deposit` events; joining unfiltered miscounts).
- **Cross-check:** read-only `get-withdrawal-request` calls agree 100% on sampled ids — u3591, u3593 → `status = (some false)` (rejected); u3500, u3595, u3600 → `(some true)` (accepted). Contract source confirms: `withdrawal-status` map, `none` = pending, boolean = accepted?.

## Q2 — Latency from request to sweep (completed requests only)

- **n = 97** · min **7** · max **10** · **median 7** · mean 7.70
- **Definition:** `burn-height` (from the `withdrawal-accept` event) minus `block-height` (from the `withdrawal-create` event).
- **Units (explicit):** the create height is counted in **Stacks blocks**, the accept height in **Bitcoin blocks**. In the Nakamoto era the two chains advance ~1:1, so the difference reads as plain "blocks", but the operands live on different chains — reported here as blocks without conflating them.
- Every completed withdrawal in the window settled within 7–10 blocks of its request.

## Q3 — Actual fee vs the user's max-fee cap

- **Fee < max-fee in all 97 completed withdrawals.** Fee == cap: **0**. Fee > cap: **0** (impossible by construction — the contract enforces the cap).
- Largest gap (max-fee − fee): **u3549, 9,931 sats** left unclaimed.
- Fee distribution: min 34 · p10 37 · **median 71** · p90 74 · max 338 sats (mean 71.1).
- Max-fee distribution: mean 6,272.4 sats — users systematically set caps far above what signers take.
- Signers never took the full cap in this window; the fee floor actually charged was 34 sats.

## Q4 — The 4 without a sweep: rejected or pending?

| id | amount (sats) | max-fee | create block | verdict | evidence |
|----|---------------|---------|--------------|---------|----------|
| u3591 | 707 | 5 | 968529 | **REJECTED** | `withdrawal-reject` event; `get-withdrawal-request` → `(some false)` |
| u3592 | 844 | 10 | 968529 | **REJECTED** | `withdrawal-reject` event; `get-withdrawal-request` → `(some false)` |
| u3593 | 26370 | 340 | 968534 | **REJECTED** | `withdrawal-reject` event; `get-withdrawal-request` → `(some false)` |
| u3594 | 9660 | 340 | 968539 | **REJECTED** | `withdrawal-reject` event; `get-withdrawal-request` → `(some false)` |

- **Observable used:** the contract's `complete-withdrawal-reject` emits topic `"withdrawal-reject"` and sets `withdrawal-status[id] = false`; `none` would mean pending. Zero ids are in the `none` state.
- u3591 (707 sats, max-fee 5) and u3592 (844 sats, max-fee 10): dust amounts with caps **below the observed fee floor** (min fee charged anywhere in the window: 34 sats) — the users priced the signers out.
- u3593 (26,370 sats, max-fee 340) and u3594 (9,660 sats, max-fee 340): caps and amounts look normal; the reject event carries only `(request-id, signer-bitmap)`, so **the on-chain data gives no reason** — reported as unknown, not guessed.

## Q5 — The hazard: what would mislead someone answering "is sBTC cashable?"

**The trap I tested:** latency (Q2) only exists for completed sweeps, and "completed" depends on time. If slow requests were still pending near the young edge of the window (u3600), the median-7 figure would describe only the fast subset — a right-truncated sample biased downward.

**Tested against the data — NOT present in this window:** the youngest cohort u3595–u3600 ALL swept, with latencies 7, 8, 7, 7, 7, 8 — identical to the window profile. Zero requests are pending anywhere in u3500–u3600. The median of 7 blocks is therefore **not** downward-biased by truncation here; the window is fully resolved (97 swept + 4 rejected = 101).

**The real hazard the data does show — fee-cap selection bias.** Quoting "96% of withdrawals cash out" (97/101) as an unconditional property of sBTC is wrong, and u3591/u3592 prove it with concrete ids: they set max-fee to **5 and 10 sats** against a signer fee floor of **34 sats** (minimum fee observed in the window), on dust amounts of 707/844 sats. They weren't slow — they were **actively rejected** because no signer can serve them at the offered price. Cashability is conditional on offering a fee above the floor; read the 96% as unconditional and you'll conclude sBTC fails users it was actually the users' pricing that failed.

**Second concrete wrinkle:** the 4 rejections form one contiguous cluster, u3591–u3594 (create blocks 968529–968539), yet immediate neighbors at *identical* create blocks were accepted — u3588–u3590 (block 968529, fee 71) and u3595 (block 968539, fee 79). Rejection is per-request, not a signer outage. For u3593/u3594 the mechanism is not observable on-chain (see Q4) — a second, quieter hazard: the 96% figure also folds in rejections whose cause the chain never records.

## Data table — all 101 requests

| id | amount | max-fee | create (Stacks block) | fee | sweep (Bitcoin block) | status |
|----|--------|---------|----------------------|-----|----------------------|--------|
| u3500 | 26669 | 500 | 968470 | 70 | 968477 | swept |
| u3501 | 32950 | 10000 | 968470 | 70 | 968477 | swept |
| u3502 | 130607 | 10000 | 968470 | 72 | 968477 | swept |
| u3503 | 41534 | 10000 | 968470 | 70 | 968477 | swept |
| u3504 | 42584 | 10000 | 968470 | 72 | 968477 | swept |
| u3505 | 34234 | 10000 | 968470 | 70 | 968477 | swept |
| u3506 | 156958 | 10000 | 968470 | 70 | 968477 | swept |
| u3507 | 35373 | 10000 | 968470 | 72 | 968477 | swept |
| u3508 | 75891 | 10000 | 968470 | 72 | 968477 | swept |
| u3509 | 59236 | 10000 | 968470 | 72 | 968477 | swept |
| u3510 | 36105 | 10000 | 968470 | 76 | 968477 | swept |
| u3511 | 453807 | 10000 | 968470 | 72 | 968477 | swept |
| u3512 | 327549 | 10000 | 968470 | 70 | 968477 | swept |
| u3513 | 36639 | 10000 | 968470 | 72 | 968477 | swept |
| u3514 | 180292 | 10000 | 968470 | 72 | 968477 | swept |
| u3515 | 101970 | 10000 | 968470 | 72 | 968477 | swept |
| u3516 | 47538 | 10000 | 968470 | 70 | 968477 | swept |
| u3517 | 75891 | 10000 | 968470 | 72 | 968477 | swept |
| u3518 | 132666 | 10000 | 968470 | 70 | 968477 | swept |
| u3519 | 33392 | 10000 | 968470 | 72 | 968477 | swept |
| u3520 | 132475 | 10000 | 968470 | 70 | 968477 | swept |
| u3521 | 18535 | 10000 | 968470 | 70 | 968477 | swept |
| u3522 | 38958 | 10000 | 968470 | 70 | 968477 | swept |
| u3523 | 157515 | 10000 | 968470 | 70 | 968477 | swept |
| u3524 | 121996 | 10000 | 968470 | 70 | 968477 | swept |
| u3525 | 57806 | 10000 | 968470 | 70 | 968477 | swept |
| u3526 | 85854 | 10000 | 968470 | 72 | 968477 | swept |
| u3527 | 79956 | 10000 | 968470 | 72 | 968477 | swept |
| u3528 | 75891 | 10000 | 968470 | 72 | 968477 | swept |
| u3529 | 62362 | 10000 | 968470 | 72 | 968477 | swept |
| u3530 | 37239 | 10000 | 968470 | 70 | 968477 | swept |
| u3531 | 75891 | 10000 | 968470 | 70 | 968477 | swept |
| u3532 | 46121 | 10000 | 968470 | 70 | 968477 | swept |
| u3533 | 75891 | 10000 | 968470 | 72 | 968477 | swept |
| u3534 | 83533 | 10000 | 968470 | 70 | 968477 | swept |
| u3535 | 59571 | 10000 | 968470 | 72 | 968477 | swept |
| u3536 | 58110 | 10000 | 968470 | 70 | 968477 | swept |
| u3537 | 348763 | 10000 | 968470 | 70 | 968477 | swept |
| u3538 | 32950 | 10000 | 968470 | 72 | 968477 | swept |
| u3539 | 95215 | 10000 | 968470 | 70 | 968477 | swept |
| u3540 | 136005 | 10000 | 968470 | 72 | 968477 | swept |
| u3541 | 58713 | 10000 | 968470 | 72 | 968477 | swept |
| u3542 | 3425607 | 10000 | 968470 | 70 | 968477 | swept |
| u3543 | 675404 | 10000 | 968470 | 70 | 968477 | swept |
| u3544 | 73314 | 10000 | 968470 | 70 | 968477 | swept |
| u3545 | 108815 | 10000 | 968470 | 72 | 968477 | swept |
| u3546 | 64782 | 10000 | 968470 | 72 | 968477 | swept |
| u3547 | 67302 | 10000 | 968470 | 70 | 968477 | swept |
| u3548 | 33460 | 10000 | 968472 | 71 | 968479 | swept |
| u3549 | 140308 | 10000 | 968472 | 69 | 968479 | swept |
| u3550 | 973629 | 340 | 968473 | 68 | 968480 | swept |
| u3551 | 10099 | 510 | 968474 | 78 | 968481 | swept |
| u3552 | 90251 | 1500 | 968478 | 45 | 968485 | swept |
| u3553 | 610723 | 340 | 968486 | 41 | 968493 | swept |
| u3554 | 11712 | 340 | 968509 | 36 | 968518 | swept |
| u3555 | 120334 | 340 | 968514 | 136 | 968521 | swept |
| u3556 | 709660 | 340 | 968516 | 35 | 968523 | swept |
| u3557 | 509660 | 340 | 968516 | 35 | 968523 | swept |
| u3558 | 36820 | 510 | 968516 | 34 | 968523 | swept |
| u3559 | 12121 | 340 | 968523 | 36 | 968530 | swept |
| u3560 | 28352 | 1500 | 968524 | 65 | 968531 | swept |
| u3561 | 126503 | 750 | 968527 | 34 | 968535 | swept |
| u3562 | 52714 | 340 | 968529 | 37 | 968539 | swept |
| u3563 | 5297305 | 3000 | 968529 | 71 | 968538 | swept |
| u3564 | 4972721 | 4000 | 968529 | 74 | 968538 | swept |
| u3565 | 4660753 | 4000 | 968529 | 74 | 968538 | swept |
| u3566 | 458699 | 3000 | 968529 | 71 | 968538 | swept |
| u3567 | 278601 | 4000 | 968529 | 71 | 968538 | swept |
| u3568 | 135773 | 3000 | 968529 | 71 | 968538 | swept |
| u3569 | 98610 | 3000 | 968529 | 71 | 968538 | swept |
| u3570 | 41170 | 5000 | 968529 | 71 | 968538 | swept |
| u3571 | 38903 | 5000 | 968529 | 71 | 968538 | swept |
| u3572 | 38544 | 3000 | 968529 | 71 | 968538 | swept |
| u3573 | 38672 | 2000 | 968529 | 36 | 968539 | swept |
| u3574 | 35065 | 3000 | 968529 | 74 | 968538 | swept |
| u3575 | 31716 | 5000 | 968529 | 71 | 968538 | swept |
| u3576 | 24702 | 3000 | 968529 | 71 | 968538 | swept |
| u3577 | 22624 | 3000 | 968529 | 71 | 968538 | swept |
| u3578 | 16397 | 3000 | 968529 | 71 | 968538 | swept |
| u3579 | 17967 | 500 | 968529 | 36 | 968539 | swept |
| u3580 | 5936 | 10000 | 968529 | 71 | 968538 | swept |
| u3581 | 11400 | 3000 | 968529 | 71 | 968538 | swept |
| u3582 | 10680 | 1000 | 968529 | 39 | 968539 | swept |
| u3583 | 8261 | 3000 | 968529 | 71 | 968538 | swept |
| u3584 | 4234 | 5000 | 968529 | 71 | 968538 | swept |
| u3585 | 15482 | 1000 | 968529 | 36 | 968539 | swept |
| u3586 | 6078 | 10000 | 968529 | 71 | 968538 | swept |
| u3587 | 3046 | 3000 | 968529 | 71 | 968538 | swept |
| u3588 | 1617 | 3000 | 968529 | 71 | 968538 | swept |
| u3589 | 1314 | 3001 | 968529 | 71 | 968538 | swept |
| u3590 | 1741 | 3000 | 968529 | 71 | 968538 | swept |
| u3591 | 707 | 5 | 968529 | — | — | **rejected** |
| u3592 | 844 | 10 | 968529 | — | — | **rejected** |
| u3593 | 26370 | 340 | 968534 | — | — | **rejected** |
| u3594 | 9660 | 340 | 968539 | — | — | **rejected** |
| u3595 | 184441 | 680 | 968539 | 79 | 968547 | swept |
| u3596 | 28613 | 720 | 968540 | 77 | 968547 | swept |
| u3597 | 720528 | 5000 | 968542 | 338 | 968549 | swept |
| u3598 | 1956507 | 1000 | 968543 | 86 | 968550 | swept |
| u3599 | 85789 | 850 | 968543 | 86 | 968550 | swept |
| u3600 | 20949 | 680 | 968546 | 140 | 968554 | swept |

## Methodology & reproducibility

1. Downloaded `withdrawal-create`, `withdrawal-accept`, `withdrawal-reject` events from `https://api.hiro.so/extended/v1/contract/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry/events` (limit=50, paginated newest-first, 43 pages) until the oldest create in the window (u3500) plus 5 pages of margin.
2. Parsed the Clarity `repr` tuples; joined on `request-id`. No duplicate creates or accepts exist for any id in the window.
3. Counts (Q1, Q4) decided by event join; independently cross-checked with read-only `get-withdrawal-request` calls (u3500, u3591, u3593, u3595, u3600) — 5/5 agreement.
4. Latency (Q2) = `burn-height` (accept, Bitcoin) − `block-height` (create, Stacks); units named, not mixed.
5. Every accept in the window has `bitcoin-txid == sweep-txid`, `output-index u2`, `signer-bitmap u0` — noted, not assumed.

## Anomalies worth naming

1. **Contiguous rejected cluster u3591–u3594** amid accepted neighbors at identical create blocks → per-request rejection, not signer downtime.
2. **u3591/u3592: dust + sub-floor caps** (max-fee 5/10 vs floor 34) → actively rejected; the clearest on-chain example of fee-cap selection.
3. **u3593/u3594: rejected for no observable reason** (normal amounts, max-fee 340) — the reject event carries no cause.
4. **Fee floor is tight, caps are wild:** fees 34–338 sats (median 71) vs max-fees up to five figures — users over-cap by ~88× on average (mean max-fee 6,272 vs mean fee 71).
5. **Minimum latency is 7 blocks, never less** — consistent with signers requiring ~6+ Bitcoin confirmations before completing, though the mechanism isn't proven from these events alone.

---
*Snapshot 2026-09-28 04:00 UTC. 43 event pages, 101 creates / 97 accepts / 4 rejects joined; 5 read-only contract calls for validation.*
