Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,35 @@
"pages": [
"product-suite/swap",
"product-suite/swap/security-model",
{
"group": "Integration",
"pages": [
"product-suite/swap/integration/overview",
"product-suite/swap/integration/authorization",
"product-suite/swap/integration/user-flow"
]
},
{
"group": "API Reference",
"pages": [
"product-suite/swap/api/affiliates",
"product-suite/swap/api/networks-and-tokens",
"product-suite/swap/api/quotes",
"product-suite/swap/api/intents-and-approvals",
"product-suite/swap/api/swaps",
"product-suite/swap/api/affiliates"
"product-suite/swap/api/swaps"
]
},
{
"group": "Resolver Integration",
"pages": [
"product-suite/swap/resolver-integration/overview",
"product-suite/swap/resolver-integration/protocol-api",
"product-suite/swap/resolver-integration/resolver-api",
"product-suite/swap/resolver-integration/webhooks-and-lifecycle",
"product-suite/swap/resolver-integration/evm-tron-settlement",
"product-suite/swap/resolver-integration/solana-settlement",
"product-suite/swap/resolver-integration/bitcoin-settlement",
"product-suite/swap/resolver-integration/validation-gaps"
]
},
{
"group": "Integration",
"pages": [
"product-suite/swap/integration/overview",
"product-suite/swap/integration/authorization",
"product-suite/swap/integration/user-flow"
]
},
{
Expand Down
4 changes: 2 additions & 2 deletions mint/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ This direction moves USDT from your EVM wallet to the Bitcoin RGB layer, where y

### Step 1 — Enter the transfer details

On [transfer.dev.utexo.com](https://transfer.dev.utexo.com), set:
On [transfer.stage.utexo.com](https://transfer.stage.utexo.com), set:

- **Send:** Blockchain – Ethereum (or Tron / Solana), Token – USDT.
- **Receive:** Blockchain – Bitcoin (RGB), Token – USDT.
Expand Down Expand Up @@ -82,7 +82,7 @@ This direction burns USDT on the Bitcoin RGB layer and releases the equivalent U

### Step 1 — Enter the transfer details

On [transfer.dev.utexo.com](https://transfer.dev.utexo.com), set:
On [transfer.stage.utexo.com](https://transfer.stage.utexo.com), set:

- **Send:** Blockchain – Bitcoin (RGB), Token – USDT.
- **Receive:** Blockchain – Ethereum (or Tron / Solana), Token – USDT.
Expand Down
1 change: 1 addition & 0 deletions product-suite/swap.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Resolvers provide liquidity and perform the on-chain operations required to fulf
- [**Integration**](/product-suite/swap/integration/overview) explains access, authentication, and the end-to-end user flow.
- [**Security Model**](/product-suite/swap/security-model) defines escrow isolation, resolver permissions, and refund behavior.
- [**API Reference**](/product-suite/swap/api/networks-and-tokens) documents discovery, quotes, intents, swaps, and affiliates.
- [**Resolver Integration**](/product-suite/swap/resolver-integration/overview) documents resolver responsibilities, protocol-facing endpoints, webhook lifecycle events, and chain-specific settlement requirements.
- [**On-chain Helpers**](/product-suite/swap/on-chain-helpers/wrap-native-tokens) covers native-token wrapping and Permit2 token allowance.

## Glossary
Expand Down
2 changes: 1 addition & 1 deletion product-suite/swap/integration/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The following integration resources are available:

- Swagger and Swagger UI for endpoint discovery and direct request testing.
- TypeScript, Go, and Rust SDKs.
- `@hot-pot/hotpot-sdk-ts` for the current TypeScript Permit2 helpers.
- `@hot-pot/hotpot-sdk-ts` is the legacy package namespace used by the current TypeScript Permit2 examples. Confirm with the Utexo team that this package name and supported version remain current before integrating.

<Note>
Obtain the current Swagger or Swagger UI URL and the supported SDK distribution links and versions from the Utexo team.
Expand Down
2 changes: 1 addition & 1 deletion product-suite/swap/on-chain-helpers/wrap-native-tokens.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebarTitle: "Wrap Native Tokens"

## Overview

Utexo Swap interacts with token contracts rather than native blockchain assets. Wrap the native asset before executionfor example, wrap ETH into WETH on Ethereumand use the wrapped-token contract address as `sourceToken`.
For source inputs, Utexo Swap interacts with token contracts rather than native blockchain assets. Wrap the source asset before execution, for example, wrap ETH into WETH on Ethereum, and use the wrapped-token contract address as `sourceToken`. This requirement applies to source assets. On EVM destination chains, settlement can return native ETH by having the resolver supply WETH and the protocol unwrap it before transfer to the user.

```ts
import { ethers } from "ethers";
Expand Down
107 changes: 107 additions & 0 deletions product-suite/swap/resolver-integration/bitcoin-settlement.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
title: "Bitcoin Settlement"
description: "Settle Utexo Bitcoin swaps with Taproot HTLC PSBTs, script-path withdrawals, and cooperative fast refunds."
sidebarTitle: "Bitcoin"
---

Bitcoin settlement uses Taproot (P2TR) outputs and BIP 174 PSBTs. No smart contract is deployed on Bitcoin.

## HTLC lock output

Every deposit locks funds to a unique Taproot output with three script leaves:

| Leaf | Script |
| --- | --- |
| Resolver withdraw | `OP_HASH256 <secretHash> OP_EQUALVERIFY <resolverPubKey> OP_CHECKSIG` |
| Timelock refund | `<deadline> OP_CLTV OP_DROP <protocolPubKey> OP_CHECKSIG` |
| Fast refund | `<protocolPubKey> OP_CHECKSIG <resolverPubKey> OP_CHECKSIGADD 2 OP_EQUAL` |

- `secretHash` is double SHA-256 of the 32-byte secret.
- The internal key may be a NUMS point or a resolver-selected key, per source.
- The resolver returns the refund and fast-refund control blocks to Utexo and keeps the withdraw control block internally.

## Deposit transaction

### Intent tagging

Every deposit contains an `OP_RETURN` output that tags the intent:

```text
OP_RETURN <protocolPrefix> <flag> <intentID>
```

### PSBT inputs

| Field | Value |
| --- | --- |
| `WITNESS_UTXO` | Required for every input. |
| Sighash | `SIGHASH_ALL` (`0x01`). |
| `TAP_INTERNAL_KEY` | User's x-only public key. |
| Sequence | `0xFFFFFFFF` (no RBF). |

### Outputs

| Index | Output |
| --- | --- |
| `0` | `OP_RETURN` with `0` sats. |
| `1` | P2TR HTLC lock. The amount is the deposit minus a proportional share of network fees. |

<Warning>
The source states there are exactly two or three outputs, but does not define the optional third output. Do not invent change behavior; see [Validation Gaps](/product-suite/swap/resolver-integration/validation-gaps).
</Warning>

## Spend paths

### Key-spend path

Used for deposit input signing, fulfillment, and native transfers.

Witness:

```text
[schnorr_signature]
```

### Resolver withdraw (script-path)

Witness:

```text
[schnorr_signature, secret_preimage, tap_script, control_block]
```

### Fast refund (script-path)

Cooperative script-path spend co-signed by the protocol and the resolver.

### Timelock refund

Script-path refund after `deadline`.

<Note>
The source does not document the final witness stack for the timelock refund path. Confirm with the current implementation before constructing this witness.
</Note>

## Fee model

The resolver computes fees from a header plus per-input and per-output costs:

```text
header = 11 vBytes
size = header
+ sum(input_size + witness_size) * count
+ sum(output_size) * count
fee = size * fee_rate
```

Default fee rate: `3 sat/vB`.

### Size table

| Type | Input | Witness | Output |
| --- | --- | --- | --- |
| P2TR | 41 | 17 | 43 |
| P2WPKH | 41 | 27 | 31 |
| P2SH (2-of-3) | 43 | 254 | 32 |
| P2PKH | 41 | 107 | 34 |
| P2WSH (2-of-3) | 41 | 64 | 43 |
120 changes: 120 additions & 0 deletions product-suite/swap/resolver-integration/evm-tron-settlement.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
title: "EVM and Tron Settlement"
description: "Deploy resolver executors and settle Utexo swaps on EVM chains and Tron, including single-chain, cross-chain, DEX, and fast refund paths."
sidebarTitle: "EVM and Tron"
---

Utexo supports four settlement paths on EVM:

- Cross-chain swap
- Cross-chain swap with DEX
- Single-chain atomic swap
- Fast refund

Users sign Permit2 approvals. The resolver submits every on-chain transaction and pays gas.

## Onboarding

A protocol administrator registers each resolver in the `ResolversWhitelist` contract with:

- Executor contract address
- `depositAddresses` allow list
- `withdrawAddresses` allow list

The same resolver must own the authorized deposit and withdraw roles. The on-chain `checkSameResolver` check enforces this.

## Executor contract

Each resolver deploys an Executor implementing the `IExecutor` interface:

```solidity
function fulfill(
address token,
uint256 minAmount,
uint256 maxAmount,
bytes data
) external returns (uint256 amount);

function swap(
address outputToken,
uint256 minOutputAmount,
uint256 maxOutputAmount,
address inputToken,
uint256 inputAmount,
bytes data
) external returns (uint256 amount);

function dexSwap(
address outputToken,
uint256 minOutputAmount,
uint256 maxOutputAmount,
address inputToken,
uint256 inputAmount,
bytes data
) external returns (uint256 amount);
```

The protocol verifies that its own ERC-20 balance increased by exactly the amount returned by `IExecutor`.

### Method responsibilities

- `fulfill` transfers between `minAmount` and `maxAmount` to the caller and returns the actual transferred amount.
- `swap` receives input tokens already transferred to the Executor and returns a bounded output to `EscrowRouter`.
- `dexSwap` uses only deposited user tokens with non-empty routing `data`.

<Warning>
`dexSwap` must trade the deposited user tokens through the DEX. Do not fund the output from your own treasury liquidity.
</Warning>

## Fulfillment contract

The protocol deploys a Fulfillment contract once per resolver per destination chain. The resolver supplies:

- Executor address
- Authorized caller/operator addresses

## Cross-chain swap

<Steps>
<Step title="Deposit">
`EscrowRouter.deposit` deploys a deterministic CREATE2 proxy and transfers the user's input tokens into it using Permit2.
</Step>
<Step title="Fulfill">
On the destination chain, the resolver's Executor `fulfill` pays the user the destination amount within `[minAmount, maxAmount]`.
</Step>
<Step title="Withdraw">
After Utexo verifies fulfillment and reveals the secret, the resolver withdraws from the source-chain escrow.
</Step>
</Steps>

<Note>
The source does not fully document the withdraw signature and parameters. See [Validation Gaps](/product-suite/swap/resolver-integration/validation-gaps).
</Note>

## Cross-chain swap with DEX

Source-chain deposit transfers the user's input token to the Executor, calls `dexSwap`, validates the output against the declared bounds, and locks the resulting `tokenOut` in the proxy. The follow-on Order then uses `tokenOut` and `minAmountOut` on the destination.

## Single-chain atomic swap

`EscrowRouter.swap` atomically transfers the user's input to the Executor and sends a bounded output amount directly to the user. When the destination token is native ETH, the Executor supplies WETH and the protocol unwraps it before paying the user.

## Fast refund

Backend and resolver co-sign the following EIP-712 message in the `EscrowImplementation` domain:

```text
FastRefund(bytes32 orderHash)
```

The resolver signer must match `order.resolverDeposit`.

## Tron

Tron is architecturally aligned with EVM but uses TIP-712 with these differences:

- No `version` field in the domain.
- Domain type string: `EIP712Domain(string name,uint256 chainId,address verifyingContract)`.
- `chainId` is masked with `chainId & 0xffffffff`.

These rules apply to the deposit witness, fulfillment, and refund signing.
Loading