| Seller confirms |
Seller received fiat payment and attests RELEASE. Buyer claims BTC to pre-approved address. Fee (input x bp / 10000) enforced. Buyer amount enforced (input - fee). |
<buyer> OP_CHECKSIGVERIFY <introspector> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG |
<seller> OP_CHECKSIGFROMSTACK(RELEASE) OP_VERIFY OP_INSPECTNUMINPUTS 1 OP_EQUALVERIFY 0 OP_INSPECTOUTPUTSCRIPTPUBKEY <buyer_ver> OP_EQUALVERIFY <buyer_prog> OP_EQUALVERIFY 1 OP_INSPECTOUTPUTSCRIPTPUBKEY <fee_ver> OP_EQUALVERIFY <fee_prog> OP_EQUALVERIFY OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE <bp> OP_MUL64 OP_VERIFY <10000> OP_DIV64 OP_VERIFY OP_SWAP OP_DROP 1 OP_INSPECTOUTPUTVALUE OP_SWAP OP_GREATERTHANOREQUAL64 OP_VERIFY OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE 1 OP_INSPECTOUTPUTVALUE OP_SUB64 OP_VERIFY 0 OP_INSPECTOUTPUTVALUE OP_SWAP OP_GREATERTHANOREQUAL64 |
| Buyer cancels |
Buyer voluntarily cancels the trade. Full amount returns to pre-approved seller address. No fee. Amount enforced (seller gets >= input). |
<seller> OP_CHECKSIGVERIFY <introspector> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG |
<buyer> OP_CHECKSIGFROMSTACK(CANCEL) OP_VERIFY 0 OP_INSPECTOUTPUTSCRIPTPUBKEY <seller_ver> OP_EQUALVERIFY <seller_prog> OP_EQUALVERIFY OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE 0 OP_INSPECTOUTPUTVALUE OP_SWAP OP_GREATERTHANOREQUAL64 |
| Topup |
Anyone adds more BTC to the escrow (e.g. top-up or consolidation). No fee. |
<buyer> OP_CHECKSIGVERIFY <introspector> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG |
OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTSCRIPTPUBKEY OP_1 OP_EQUALVERIFY 0 OP_INSPECTOUTPUTSCRIPTPUBKEY OP_1 OP_EQUALVERIFY OP_EQUALVERIFY OP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE 0 OP_INSPECTOUTPUTVALUE OP_LESSTHAN64 |
| Arbitrator releases to buyer |
Dispute resolved in buyer's favor. Arbitrator signs the transaction directly, controlling exact outputs and fee. No Arkade script. |
<buyer> OP_CHECKSIGVERIFY <arbitrator> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG |
— |
| Arbitrator refunds seller |
Dispute resolved in seller's favor. Arbitrator signs the transaction directly, controlling exact outputs. No Arkade script, no fee. |
<seller> OP_CHECKSIGVERIFY <arbitrator> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG |
— |
| Seller self-release (CLTV) |
After CLTV expires, seller reclaims funds if buyer and arbitrator are absent. No introspector, no Arkade script, no fee. |
<locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP <seller> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG |
— |
| Mutual exit (CSV) |
Buyer and seller mutually agree to exit without operator/introspector. Available after relative timelock. No fee. |
<sequence> OP_CHECKSEQUENCEVERIFY OP_DROP <buyer> OP_CHECKSIGVERIFY <seller> OP_CHECKSIG |
— |
| Seller-only recovery (CSV) |
Last resort if buyer, arbitrator, and operator are all unresponsive. Available after double relative timelock. No fee. |
<sequence> OP_CHECKSEQUENCEVERIFY OP_DROP <seller> OP_CHECKSIG |
— |
P2P Exchange Escrow Contract
A self-enforcing P2P Bitcoin exchange escrow using the introspector's Taproot + CSFS + transaction introspection opcodes.
Design goals
Entities
Parameters
sellerPubKeybuyerPubKeyarbitratorPubKeybuyerSpkOP_INSPECTOUTPUTSCRIPTPUBKEYon SellerConfirmsellerSpkOP_INSPECTOUTPUTSCRIPTPUBKEYon BuyerRefundfeeSpkOP_INSPECTOUTPUTSCRIPTPUBKEYfeeBasisPointsOP_MUL64/OP_DIV64computationcltvTimeoutcsvTimeouttradeIDOracle messages
SHA256(0x01 || tradeID)— attested by seller (payment received) via CSFSSHA256(0x02 || tradeID)— attested by buyer (voluntary refund) via CSFSVTXO taproot tree
Each row is one spendable path. Tapscript opcodes are the Bitcoin Script in the tapscript itself. Arkade script opcodes are validated by the introspector engine inside that tapscript.
<buyer> OP_CHECKSIGVERIFY <introspector> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG<seller> OP_CHECKSIGFROMSTACK(RELEASE) OP_VERIFYOP_INSPECTNUMINPUTS 1 OP_EQUALVERIFY0 OP_INSPECTOUTPUTSCRIPTPUBKEY <buyer_ver> OP_EQUALVERIFY <buyer_prog> OP_EQUALVERIFY1 OP_INSPECTOUTPUTSCRIPTPUBKEY <fee_ver> OP_EQUALVERIFY <fee_prog> OP_EQUALVERIFYOP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE <bp> OP_MUL64 OP_VERIFY <10000> OP_DIV64 OP_VERIFY OP_SWAP OP_DROP1 OP_INSPECTOUTPUTVALUE OP_SWAP OP_GREATERTHANOREQUAL64 OP_VERIFYOP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE 1 OP_INSPECTOUTPUTVALUE OP_SUB64 OP_VERIFY0 OP_INSPECTOUTPUTVALUE OP_SWAP OP_GREATERTHANOREQUAL64<seller> OP_CHECKSIGVERIFY <introspector> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG<buyer> OP_CHECKSIGFROMSTACK(CANCEL) OP_VERIFY0 OP_INSPECTOUTPUTSCRIPTPUBKEY <seller_ver> OP_EQUALVERIFY <seller_prog> OP_EQUALVERIFYOP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE 0 OP_INSPECTOUTPUTVALUE OP_SWAP OP_GREATERTHANOREQUAL64<buyer> OP_CHECKSIGVERIFY <introspector> OP_CHECKSIGVERIFY <operator> OP_CHECKSIGOP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTSCRIPTPUBKEY OP_1 OP_EQUALVERIFY0 OP_INSPECTOUTPUTSCRIPTPUBKEY OP_1 OP_EQUALVERIFY OP_EQUALVERIFYOP_PUSHCURRENTINPUTINDEX OP_INSPECTINPUTVALUE 0 OP_INSPECTOUTPUTVALUE OP_LESSTHAN64<buyer> OP_CHECKSIGVERIFY <arbitrator> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG<seller> OP_CHECKSIGVERIFY <arbitrator> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG<locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP<seller> OP_CHECKSIGVERIFY <operator> OP_CHECKSIG<sequence> OP_CHECKSEQUENCEVERIFY OP_DROP<buyer> OP_CHECKSIGVERIFY <seller> OP_CHECKSIG<sequence> OP_CHECKSEQUENCEVERIFY OP_DROP<seller> OP_CHECKSIGKey design decisions
Checksigs outside Arkade script: Transaction authorization (CHECKSIG) lives in the tapscript closure. CSFS attestations + introspection live in Arkade scripts validated by the introspector.
Arbitrator uses OP_CHECKSIG, not CSFS: The arbitrator signs the transaction directly, controlling exact outputs (who gets what, fee amounts). No need for CSFS attestations or Arkade script fee enforcement on arbitrator paths. This gives the arbitrator full control over dispute resolution outcomes.
Three closure types: Buyer-keyed closures with introspector (SellerConfirm, Topup), seller-keyed closure with introspector (BuyerRefund), and arbitrator closures without introspector (ArbitratorToBuyer, ArbitratorToSeller).
Percentage-based fees: Fee scales with escrow value using on-chain 64-bit arithmetic (
OP_MUL64/OP_DIV64). Basis points allow fine-grained control (e.g., 200 = 2%).External trade ID: Not derived from pubkeys — allows the same parties to have multiple concurrent trades.
CSV unilateral exits are additive: Always available alongside collaborative paths. Seller can always recover.
Seller CLTV self-release: If buyer and arbitrator both disappear, seller can reclaim funds after the CLTV absolute timelock expires via the operator only. No introspector or Arkade script needed — pure multisig with timelock.
Pre-approved destinations: Buyer and seller destination addresses are locked into the contract at creation. SellerConfirm enforces output[0] goes to
buyerSpk, BuyerRefund enforces output[0] goes tosellerSpk. This prevents fund diversion even if CSFS attestation keys are compromised.Implementation
OP_MUL64/OP_DIV64ReadArkadeScriptsupports all closure types (MultisigClosure, CLTVMultisigClosure, etc.)