FAQ: What Happens If a Hashlock Markets Swap Fails or Stalls?
A short Saturday FAQ from the team at Hashlock Markets — the intent-based crypto trading platform that uses sealed-bid RFQs and HTLC atomic settlement across Ethereum, Bitcoin, and Sui.
People reading our HTLC deep-dives sometimes come away with the happy-path version of cross-chain settlement and an unanswered question: "What if it doesn't work?"
That is the right question to ask of any execution protocol, and it is especially the right question to ask of one that promises trustless, bridge-free, cross-chain swaps. So this Saturday, instead of another deep-dive, we are answering the failure-mode questions directly.
The short version: every Hashlock Markets swap is engineered so that either both sides settle, or both sides get refunded. There is no third outcome where one party walks away with both legs of the trade. Below is how each of the realistic failure modes plays out in practice.
The protocol-level guarantee
Before walking through cases, it is worth restating the property the protocol gives you, because every "what if" answer rests on it.
A Hashlock swap is two Hash Time-Locked Contracts — one on each chain — locked by the same SHA-256 hash of a single 32-byte secret (H = sha256(s)). Each contract has two ways to resolve:
-
Claim path — anyone who can present
ssuch thatsha256(s) == Hbefore the timelock expires can withdraw the locked funds. - Refund path — after the timelock expires, the original funder can reclaim their funds.
Crucially, the originator's timelock T is longer than the taker's timelock T'. The asymmetry matters: it is what makes the two-contract construction atomic. If the originator reveals the secret and claims the taker's contract, the taker still has time to use that revealed secret to claim the originator's contract. If neither reveals, both refund. There is no ordering of events that lets one side claim and the other side fail to either claim or refund.
Everything below is a corollary of that property.
Case 1 — No taker accepts your RFQ
What happens: The RFQ has an expiry. If no market maker submits a firm quote within the window, or if you do not accept any of the quotes that come back, the RFQ simply expires. No funds have been moved on chain at this point. No HTLC exists yet. There is nothing to refund.
What you do: Re-post the intent with adjusted parameters (size, slippage tolerance, expiry) or wait for better market conditions.
Cost to you: Zero. Sealed-bid RFQs do not charge per-attempt fees.
Case 2 — Counterparty disappears after you funded
This is the case that actually worries people, and it is the case the protocol was specifically designed for.
What happens: You created the RFQ, accepted a firm quote, and called create_htlc to fund the originator-side contract on chain A. The market maker is supposed to mirror with their own HTLC on chain B, but they go silent. They never fund. They never reveal a secret. They are just gone.
What the chain does for you: Your originator-side timelock T keeps ticking. When it expires, the claim path on your contract is closed forever and the refund path opens. You call refund_htlc with the contract ID, and the chain returns your funds to your address.
What it costs you: Network gas on chain A. The notional you locked up was never at risk of being lost — only of being temporarily unavailable until T elapsed. The market maker, if they had funded their side, would forfeit any collateral they posted when their (shorter) timelock T' expires.
MCP tool: refund_htlc is exposed by the Hashlock Markets MCP server alongside the other five tools. An agent script can poll get_htlc to watch the status, and call refund_htlc automatically when the contract enters the refundable state.
Case 3 — You revealed the secret, then the network got congested
What happens: You went first because you were the originator. You revealed s to claim funds from the taker's contract on chain B. Their relayer or watcher is now in possession of s (it is on chain, public). They mirror by claiming your originator-side contract on chain A — but the chain is congested and their tx sits in the mempool.
Why this is fine: The originator timelock T is set to be larger than T' plus the worst-case confirmation latency for chain A. The taker has time. Even if they miss the window for some reason, the refund path on your contract does not open until T expires, by which point they have either confirmed or you simply have a pending claim against your own already-funded contract that can be unwound by you calling refund_htlc.
The system never relies on a chain being uncongested. Timelocks are sized assuming you might lose a block-or-two of confirmation time on either side.
Case 4 — You lose the secret
The originator generates the secret s and is the only party that needs to keep it until they claim. The taker only needs s after the originator reveals it on chain (at which point they read it from the on-chain withdraw_htlc event).
What happens if the originator loses s before they claim: They wait for their own timelock T to expire and call refund_htlc. The trade does not settle, but no funds are lost. The taker's funds also refund automatically when their shorter timelock T' expires.
What happens if the taker loses s: Not possible in the normal flow — the taker only receives s by reading the originator's claim transaction on chain B, where it is permanently recorded. As long as their refund timelock T' has not passed, the secret is recoverable from chain history.
Case 5 — A quote is filled at a price you didn't expect
What happens: Hashlock uses sealed-bid RFQ pricing. The taker submits a single firm quote in private. You see the quote before you accept it. You sign nothing until you have looked at the price.
Implication: There is no slippage, no last-look, no front-running of an in-flight order. If the price moves between quote-time and accept-time, the quote is invalid and you re-RFQ. If you do accept, the price is locked in cryptographically — the HTLC pair encodes the exact amounts.
Failure mode that doesn't exist: "I executed at a price I didn't expect." The protocol forbids it by construction.
Case 6 — Smart-contract-level failure of one of the chains
What happens: This is the catastrophic-event question. If chain A or chain B halts, censors transactions, or undergoes a deep reorg, what then?
What the protocol does: Both refund paths are unconditional once the timelock has elapsed in chain time. A reorg that re-organises a confirmed create_htlc is a problem at the underlying chain's security level, not the protocol's — Hashlock does not introduce additional reorg risk on top of the chains it settles against. A halt of one chain will eventually time out the contract on the other chain via the refund path; users get back the funds they put in on the still-live chain. The funds on the halted chain are recoverable when the chain resumes.
What the protocol does not do: Hashlock does not bridge tokens or hold custody. There is no cross-chain wrapped representation that could be deflated by a chain halt — there is only the same native asset on each chain that the user already had.
Why this matters for AI agents
Most of this article is the same answer the protocol would give a human user. The reason it matters for agents specifically is that an agent driving Hashlock through MCP — Claude, GPT, Cursor, Windsurf, a custom executor — needs failure handling that is legible to it. The six MCP tools (create_rfq, respond_rfq, create_htlc, withdraw_htlc, refund_htlc, get_htlc) map cleanly onto the six things an agent has to do across the lifecycle of a swap, including the failure cases:
- Watch the contract state with
get_htlc. - Call
refund_htlcwhen the contract enters refundable state. - Re-RFQ on the taker side if no quote is accepted.
- Handle congestion the same way it handles every other on-chain wait — by polling, not by panicking.
There is no out-of-band exception handling. There is no "support ticket" path. The state machine is the support ticket.
Try it
Hashlock Markets ships an MCP server you can wire into any MCP-capable host. Two transports are available:
-
stdio, for local agent workflows:
npx -y @hashlock-tech/mcp(use the npmjs.com page for the scoped package: https://www.npmjs.com/package/@hashlock-tech/mcp) -
Streamable HTTP, for production agents:
https://hashlock.markets/mcp
Authentication is SIWE — Sign-In with Ethereum — for both transports. No API keys to leak.
The full docs and protocol spec live at hashlock.markets. Source for the MCP server is on GitHub at Hashlock-Tech/hashlock-mcp. The MCP Registry entry is io.github.Hashlock-Tech/hashlock.
If your concern about going trustless was "what if something breaks" — the answer is that the protocol was designed assuming things break.
Hashlock Markets is an intent-based crypto trading platform that uses sealed-bid Request for Quote (RFQ) auctions and Hash Time-Locked Contract (HTLC) atomic settlement to make cross-chain trades trustless, slippage-free, and immune to information leakage. Supported chains today: Ethereum, Bitcoin, and Sui.
Top comments (2)
Great breakdown of the failure modes — the timelock asymmetry between T and T' is exactly the right design for atomicity. One gap worth flagging from the agent execution layer: the article notes that an agent should "poll get_htlc, call refund_htlc when refundable, re-RFQ if no quote is accepted." All correct — but there's a step before that. If create_rfq or create_htlc times out mid-call and the agent retries, it can fire the same action twice before the state machine has confirmed the first one landed. The HTLC layer stays safe, but you now have duplicate RFQs in flight or a double-funded attempt. That's the pre-protocol layer the article calls "polling, not panicking" — SafeAgent handles it by making each action idempotent at the execution level before it ever touches your MCP tools. Happy to share how it would sit above your six-tool interface if useful.
I replied to this at the other post