Four spending paths
| Leaf | Purpose | Required |
|---|---|---|
| A | Cooperative payout | Maker + taker |
| B | Taker wins dispute | Arbiter threshold + taker |
| C | Maker wins dispute | Arbiter threshold + maker |
| D | Late maker reclaim | Maker after timeout |
Taproot output (with SDK output introspection)
├── Internal key: NUMS point (provably unspendable)
│
├── Leaf A — Happy path (Maker + Taker cooperate)
│ <maker_pubkey> OP_CHECKSIGVERIFY
│ <taker_pubkey> OP_CHECKSIG
│
├── Leaf B — Arbiter releases to Taker (taker wins dispute)
│ ⚠ CLTV must come FIRST so the final OP_CHECKSIG result gates the script:
│ <bounty_deadline + Δ_dispute> OP_CHECKLOCKTIMEVERIFY OP_DROP
│ <panel_aggregate_key> OP_CHECKSIGVERIFY
│ <taker_pubkey> OP_CHECKSIG
│
├── Leaf C — Arbiter releases to Maker (maker wins dispute)
│ <bounty_deadline + Δ_dispute> OP_CHECKLOCKTIMEVERIFY OP_DROP
│ <panel_aggregate_key> OP_CHECKSIGVERIFY
│ <maker_pubkey> OP_CHECKSIG
│
└── Leaf D — Maker reclaim (taker never accepted or bounty deadline passed)
⚠ MUST mature AFTER Leaf B/C so the panel can act before maker reclaims.
<bounty_deadline + 5 days + 2 days> OP_CHECKLOCKTIMEVERIFY OP_DROP
<maker_pubkey> OP_CHECKSIG
(Δ_dispute=5d, Δ_reclaim=2d → Leaf D opens 7 days after bounty_deadline)
What “non-custodial” means here
The Ark Operator co-signs rounds but cannot satisfy a leaf alone. An arbiter threshold also cannot take the bounty: Leaves B and C require the winning party. SatCode holds no escrow key.
Ordering matters
Dispute leaves mature at the bounty deadline plus five days; maker reclaim at plus seven. Reversing that order could let a maker front-run a verdict. The taker must verify it.