# HTLC explained

Source: https://docs.settlemint.com/docs/user-guides/system-addons/xvp-settlement/htlc/htlc-explained
Understand how Hash Time-Locked Contracts enable trustless cross-chain asset exchanges.
Learn about hashlocks, timelocks, and why the mechanism is cryptographically secure.




Hash Time-Locked Contracts (HTLCs) enable trustless asset exchanges across different blockchains. This page explains how the mechanism works and why it provides strong security guarantees.

## The two core components [#the-two-core-components]

### Hashlock: the cryptographic lock [#hashlock-the-cryptographic-lock]

A hashlock is a cryptographic puzzle created by hashing a secret value:

```
hashlock = keccak256(secret)
```

Only someone who knows the original secret can "unlock" the hashlock. Think of it like a combination lock where only the secret holder knows the combination.

**Key properties of the hashlock:**

* No one can figure out the secret from the hashlock alone
* The same secret always produces the same hashlock

### Timelock: the deadline [#timelock-the-deadline]

A timelock is a deadline after which the settlement expires. It serves two purposes:

1. **Protection from stuck assets** - If something goes wrong, assets are not locked forever
2. **Coordination mechanism** - Creates a window during which the exchange must complete

## How HTLC ensures atomicity [#how-htlc-ensures-atomicity]

The best way to understand HTLC security is through a concrete example.

### Example: Bank sells bonds to an Investor [#example-bank-sells-bonds-to-an-investor]

**Setup:**

* Investor has 100,000 USDC on Polygon
* Bank has 1,000 BOND tokens on Ethereum
* They want to exchange these assets atomically

### Step 1: Bank generates the secret [#step-1-bank-generates-the-secret]

The Bank generates a random secret and computes the hashlock:

* **Secret:** `0x7a8b9c...` (only the Bank knows this)
* **Hashlock:** `keccak256(secret) = 0xdef456...` (shared with the Investor)

### Step 2: Bank creates settlement on Ethereum [#step-2-bank-creates-settlement-on-ethereum]

| Field    | Value                        |
| -------- | ---------------------------- |
| Flow     | Bank → Investor: 1,000 BOND  |
| Hashlock | `0xdef456...`                |
| Timelock | January 15, 2025 at 12:00 PM |

The Bank approves, locking 1,000 BOND into the settlement contract.

### Step 3: Investor creates settlement on Polygon [#step-3-investor-creates-settlement-on-polygon]

The Bank shares only the hashlock (not the secret) with the Investor.

| Field    | Value                                                   |
| -------- | ------------------------------------------------------- |
| Flow     | Investor → Bank: 100,000 USDC                           |
| Hashlock | `0xdef456...` (same as Ethereum)                        |
| Timelock | January 14, 2025 at 12:00 PM (24 hours before Ethereum) |

The Investor approves, locking 100,000 USDC into the settlement contract.

Both settlements are now in the **Armed** state, waiting for the secret.

### Step 4: The swap executes [#step-4-the-swap-executes]

1. **Bank reveals secret on Polygon** (January 13) - Settlement executes, Bank receives 100,000 USDC
2. **Secret is now public** - The Investor can see it on-chain
3. **Investor reveals secret on Ethereum** (January 13) - Settlement executes, Investor receives 1,000 BOND

Both parties received their assets. The exchange was atomic across chains.

## Why HTLC is secure [#why-htlc-is-secure]

### The Investor cannot cheat [#the-investor-cannot-cheat]

The Investor might try to claim the Bank's BOND on Ethereum without providing USDC. To do this, they would need to reveal the secret on Ethereum.

**But the Investor only knows the hashlock, not the secret.**

The hashlock is created using keccak256, a cryptographic hash function with these properties:

1. **One-way function** - Given the hashlock, it's computationally impossible to reverse-engineer the secret
2. **Brute force is impractical** - The secret is a 256-bit value with 2^256 possibilities. Even trying 1 trillion guesses per second would take longer than the age of the universe
3. **Collision resistance** - No other value produces the same hashlock

The only way the Investor can execute the Ethereum settlement is to wait for the Bank to reveal the secret on Polygon first.

### The Bank cannot cheat [#the-bank-cannot-cheat]

After revealing the secret on Polygon, the Bank cannot withdraw their BOND on Ethereum because:

* The Ethereum timelock doesn't expire until January 15
* The Investor has until then to use the (now public) secret
* The Bank's BOND remain locked in the settlement contract

### Timelock order is critical [#timelock-order-is-critical]

The timelocks must be staggered correctly:

<Mermaid
  chart="`
flowchart LR
  subgraph Polygon
      P1(Investor locks USDC) --> P2(Bank reveals secret)
      P2 --> P3(Bank gets USDC)
  end

  subgraph Ethereum
      E1(Bank locks BOND) --> E2(Investor reveals secret)
      E2 --> E3(Investor gets BOND)
  end

  P2 -.-> |secret becomes public| E2

  style P1 fill:#6ba4d4,stroke:#4a7ba8,stroke-width:2px,color:#fff
  style P2 fill:#5fc9bf,stroke:#3a9d96,stroke-width:2px,color:#fff
  style P3 fill:#5fc9bf,stroke:#3a9d96,stroke-width:2px,color:#fff
  style E1 fill:#6ba4d4,stroke:#4a7ba8,stroke-width:2px,color:#fff
  style E2 fill:#5fc9bf,stroke:#3a9d96,stroke-width:2px,color:#fff
  style E3 fill:#5fc9bf,stroke:#3a9d96,stroke-width:2px,color:#fff

`"
/>

**Correct order:** Polygon expires January 14, Ethereum expires January 15

The Investor has 24 hours after the secret is revealed on Polygon to use it on Ethereum.

**If timelocks were reversed:**

| Chain                            | Reversed Timelocks (UNSAFE) | Correct Timelocks    |
| -------------------------------- | --------------------------- | -------------------- |
| Polygon (Investor → Bank: USDC)  | January 15, 12:00 PM        | January 14, 12:00 PM |
| Ethereum (Bank → Investor: BOND) | January 14, 12:00 PM        | January 15, 12:00 PM |

**Setup (January 12):**

* Bank creates settlement on Ethereum with January 14 timelock (WRONG - too early)
* Investor creates settlement on Polygon with January 15 timelock
* Both settlements are Armed

**Bank waits strategically:**

* Bank does NOT reveal the secret yet
* Both settlements remain in Armed state

**The Exploit begins (January 14 at 12:01 PM):**

1. Ethereum timelock expires (January 14 deadline passed)
2. Bank calls `withdraw()` on Ethereum settlement
3. Bank receives their 1,000 BOND back (settlement expired without executing)

**The Exploit completes (January 14 at 12:30 PM):**

4. Polygon settlement is still valid (doesn't expire until January 15)
5. Bank reveals secret on Polygon
6. Bank receives 100,000 USDC from Polygon

**Final State:**

* Bank has: 100,000 USDC (claimed from Polygon) + 1,000 BOND (withdrawn from Ethereum)
* Investor has: Lost 100,000 USDC, received nothing
* Investor cannot claim BOND because Ethereum settlement already expired and was withdrawn

**The key rule:** When you don't have the secret, make sure the cutoff date of the HTLC that you create is before the cutoff date of the HTLC leg that has the secret. This ensures you have time to use the secret after it's revealed, before your settlement expires.

<Callout type="warn" title="Timelock rule">
  The settlement where you receive assets should have an earlier timelock than the settlement where you send assets.
  This ensures you have time to claim your assets after the secret is revealed.
</Callout>

## How XvP implements HTLC [#how-xvp-implements-htlc]

XvP settlements incorporate HTLC with these features:

| Feature                   | Implementation                                                          |
| ------------------------- | ----------------------------------------------------------------------- |
| **Secret generation**     | UI can generate secrets, or you can provide your own                    |
| **Hashlock verification** | Contract validates secret matches hashlock                              |
| **Armed state**           | All local senders must approve before secret can be revealed            |
| **Auto-execute**          | When enabled, settlement executes automatically when secret is revealed |
| **Cutoff date**           | Enforces the timelock expiration                                        |

The `revealSecret()` function:

1. Validates the provided secret matches the hashlock
2. Confirms all local senders have approved
3. If auto-execute is enabled, executes all local flows atomically
4. Records the secret on-chain for transparency

## Failure scenarios [#failure-scenarios]

| Scenario                           | What happens                                                              |
| ---------------------------------- | ------------------------------------------------------------------------- |
| Bank never reveals secret          | Both settlements expire, all parties withdraw their locked assets         |
| Investor never approves on Polygon | Bank's BOND remain locked until Ethereum timelock expires                 |
| Network congestion delays Investor | If Investor can't use secret before Ethereum expires, they lose the trade |

To mitigate network delays, set timelocks with sufficient buffer (24-48 hours between chains is recommended).

## Further reading [#further-reading]

<Cards>
  <Card title="HTLC walkthrough" href="/docs/user-guides/system-addons/xvp-settlement/htlc/walkthrough">
    Complete multi-party cross-chain settlement example.
  </Card>

  <Card title="Reveal secret" href="/docs/user-guides/system-addons/xvp-settlement/actions/reveal-secret">
    How to reveal the HTLC secret to trigger execution.
  </Card>
</Cards>

## Related [#related]

* [HTLC overview](/docs/user-guides/system-addons/xvp-settlement/htlc/overview)
* [HTLC walkthrough](/docs/user-guides/system-addons/xvp-settlement/htlc/walkthrough)
