DEV Community

Baris Sozen
Baris Sozen

Posted on

BTC collateral vaults: how an agent posts native Bitcoin against an obligation without a custodian

Most "Bitcoin in DeFi" stories quietly route through a custodian or a wrapped representation. You send BTC somewhere, someone (or some bridge multisig) holds it, and you get an IOU on another chain. That works until the thing holding your BTC is the thing that fails. For an autonomous agent that has to post collateral against an obligation it can't babysit, "trust the custodian" is exactly the assumption we're trying to delete.

This post is about the alternative: a BTC collateral vault where native Bitcoin backs an obligation on another chain, the release is gated by a hashlock, and the worst case is a refund — not a loss. It's one of the primitives underneath Hashlock's settlement layer. I'll walk through the timelock ordering that makes it safe, the Bitcoin script that enforces it, and the failure modes you design around. Honest status up front: this is signet-validated, not BTC mainnet.

The problem in one sentence

An agent wants to commit BTC as collateral backing an action on Ethereum — settling a forward, anchoring one leg of a multi-leg trade, guaranteeing a payout — such that the BTC is released to the counterparty only if the corresponding obligation on Ethereum is fulfilled, and returns to its owner if it isn't. No third party should ever be able to hold, freeze, or abscond with the BTC in between.

That's a cross-chain conditional. Bitcoin can't read Ethereum state, and Ethereum can't read Bitcoin's. The only thing both chains can independently verify is a hash preimage. So the entire construction hangs on one shared secret.

The shared secret, and why timelock order is the whole game

Both legs lock to the same hash H = SHA256(s). Whoever knows the preimage s can claim. The instant s is revealed on one chain to claim a coin, it's public, and the other party copies it to claim the other coin. That's the atomic part: one preimage unlocks both legs or neither.

The danger isn't the hash. It's time. If both legs had the same expiry, the party who knows the secret could wait until the very last block, claim the counterparty's asset, and leave the counterparty no time to claim back. The fix is asymmetric timelocks, and getting the direction right is the single most important decision in the whole design.

Rule: the party who knows the secret takes the longer timelock.

Walk it through with Alice posting BTC collateral and Bob locking ETH:

  1. Alice picks secret s, computes H. She funds the BTC vault output, spendable by Bob if he presents s, refundable to Alice after T_A = 48h.
  2. Bob, seeing the BTC vault on-chain locked to H, funds the ETH-side HTLC, claimable by Alice if she presents s, refundable to Bob after T_B = 24h. Note T_B < T_A.
  3. Alice claims the ETH by revealing s on Ethereum — she must do this before the 24h mark.
  4. The moment Alice's claim lands, s is in a public Ethereum transaction. Bob reads it and uses it to claim the BTC, with the full window up to 48h to get his transaction mined.

If Alice never reveals, both legs refund: Bob after 24h, Alice after 48h. Nobody is stuck. The 24h gap exists precisely so Bob always has slack to react after Alice forces the reveal. Flip the timelocks and you hand the secret-holder a free option — they claim your asset and let yours expire. This is the classic atomic-swap safety argument, and a collateral vault is the same argument with the BTC leg held open longer as posted margin rather than swapped instantly.

What the Bitcoin side actually looks like

Bitcoin has no smart-contract VM, but it doesn't need one here. An HTLC is expressible directly in Script. The redeem condition is a simple if/else: spend by revealing the preimage and a signature from the claimant, or spend after an absolute locktime with a signature from the refunder.

OP_IF
    OP_SHA256 <H> OP_EQUALVERIFY
    <Bob_pubkey> OP_CHECKSIG
OP_ELSE
    <T_A> OP_CHECKLOCKTIMEVERIFY OP_DROP
    <Alice_pubkey> OP_CHECKSIG
OP_ENDIF
Enter fullscreen mode Exit fullscreen mode

The refund branch uses OP_CHECKLOCKTIMEVERIFY (CLTV, BIP-65) for an absolute block-height/time lock; you can use OP_CHECKSEQUENCEVERIFY (CSV, BIP-112) instead if you want the timelock to count from when the vault was funded rather than from a fixed wall-clock point. The claim branch requires s such that SHA256(s) == H, plus Bob's signature so a watcher who merely sees s can't redirect the funds to themselves.

Two implementation notes that matter in practice:

  • Wrap it in P2WSH, or better, a Taproot (P2TR) output. With Taproot you put the refund path in a tapleaf and the cooperative path as the key-spend, so a vault that closes happily looks like an ordinary single-sig spend on-chain — smaller, cheaper, and more private. The HTLC script only ever appears if you take the script-path.
  • The refund transaction must stay mineable. You pre-sign the refund with a fee that's still credible at expiry, or you keep CPFP/anchor outputs available, because a refund you can't get into a block is not a refund. On Bitcoin you cannot assume you'll just "bump it later" inside a tight timelock window.

Why "vault," not "swap"

A plain atomic swap reveals the secret almost immediately — both sides want to close fast. A collateral vault deliberately holds the BTC leg open as backing for a longer-lived obligation: a forward that settles next week, a multi-leg position where the BTC leg must clear in lockstep with two others, a payout guarantee an agent posts before doing work. The hashlock is still the release condition; the timelock is now sized to the obligation's lifetime, not to a few confirmations.

The property an agent actually cares about: at every instant, the BTC is in exactly one of three states — locked (backing a live obligation), released (the obligation was met, preimage revealed), or refunded (it expired, BTC home). There is no fourth state where someone else is "holding it for you." That's the difference between this and a custodied vault, and it's the entire pitch.

Failure modes you have to design around

This is infrastructure, so the interesting part is what goes wrong:

  • Reveal-and-stall race. Alice reveals on Ethereum at the 23h59m mark hoping Bob's BTC claim won't confirm before his fee is too stale. The 24h/48h gap is the budget for this; it has to be sized against realistic Bitcoin mempool conditions, not optimistic ones.
  • Block-time granularity. Bitcoin's ~10-minute blocks mean a "24h" timelock is really "≈144 blocks ± variance." Your safety margins have to absorb that variance, especially near difficulty epoch boundaries.
  • Fee spikes. A refund or claim transaction priced at funding time can become unmineable in a congestion spike. Pre-signed refunds with anchor outputs (CPFP) are the standard mitigation.
  • Chain reorgs on the short leg. You wait for enough confirmations on the reveal before treating the secret as final; a shallow reorg that un-mines the reveal shouldn't strand the long leg.

None of these are exotic — they're the well-trodden hazards of cross-chain HTLCs. The point of building it once, correctly, behind an MCP tool: an agent calling create_htlc doesn't re-derive the timelock math every trade.

How an agent touches this

In Hashlock, an agent doesn't write Script. It calls the MCP server — sealed-bid RFQ to find a counterparty and price, then HTLC creation to lock the legs, fused into one operation across six tools. The BTC collateral vault is the Bitcoin-leg instantiation of that HTLC: same preimage, same timelock-ordering discipline, expressed in Script instead of Solidity. Assets stay native the entire time — no wrapping, no bridge multisig, no custodian.

Status, stated honestly

The BTC leg is signet-validated: the script, the timelock ordering, and the refund paths have been exercised end-to-end on Bitcoin's signet test network. BTC mainnet wiring is pending — I'm not going to tell you native BTC settlement is live in production when it isn't. For the record, the current honest chain status across the protocol: ETH mainnet live end-to-end; Sui contracts deployed and CLI-tested (gateway wiring in progress); BTC signet-validated, mainnet pending. We say it in the same order every time because chain claims are the one place a settlement project cannot afford to drift.

If you want the formal write-up of the settlement primitive, the methodology page lays out the RFQ-plus-HTLC construction: hashlock.markets/methodology. Source is on GitHub at github.com/Hashlock-Tech/hashlock-mcp, the package is hashlock-tech/mcp (scoped), and the academic version is on SSRN.

One question I'd genuinely like answers to: for a BTC collateral leg, where would you set the timelock gap — and what mempool assumption are you sizing it against? Drop a number and your reasoning in the comments.

Top comments (0)