# REST API authentication
Source: https://docs.saucerswap.finance/api-reference/authentication
Request a SaucerSwap REST API key, authenticate requests with the x-api-key header over HTTPS, and read the monthly quota headers on every response.
Every REST API endpoint requires an API key. Keys are provisioned by the SaucerSwap team and carry a monthly request quota.
This page covers the REST data API only. The V3 Orderbook API uses wallet challenge authentication and short-lived JWTs instead — see [Orderbook authentication](/api-reference/orderbook/authentication).
## Get an API key
Email [support@saucerswap.finance](mailto:support@saucerswap.finance) to request a key. The team provisions keys manually — there is no self-serve signup — and your monthly request quota is agreed during that conversation. Provisioned keys are UUID strings.
Store your key in server-side secret storage. Do not embed it in frontend code or commit it to a repository: anyone holding the key consumes your quota.
## Authenticate requests
Pass your key in the `x-api-key` header with every request over HTTPS:
```bash theme={null}
curl -i -H "x-api-key: YOUR_API_KEY" \
--url https://api.saucerswap.finance/tokens
```
A successful response returns `200` with your current quota state in the response headers:
```text theme={null}
HTTP/2 200
content-type: application/json; charset=utf-8
x-ratelimit-limit: 10000
x-ratelimit-remaining: 8250
x-ratelimit-additional-total: 0
x-ratelimit-reset: 1746071999999
```
## Quota headers
| Header | Meaning |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `x-ratelimit-limit` | Total requests allowed per month, set when your key is provisioned. |
| `x-ratelimit-remaining` | Requests left this month. Decreases with each request; use it to alert or self-throttle. |
| `x-ratelimit-additional-total` | Requests made over your monthly limit, when overage has been arranged with the team. |
| `x-ratelimit-reset` | Time when usage statistics reset, as a unix timestamp in milliseconds. Typically the end of the current month. |
If you expect to occasionally need more requests than your quota, raise it with the team in advance — overage requests are then counted in `x-ratelimit-additional-total` instead of being rejected.
## Next steps
Understand tinybar, smallest-unit amounts, timestamps, and interval endpoints.
Handle 401, 403, and 429 responses and build quota-aware retry logic.
Start with the token list, then explore pools, farms, and stats.
Make your first authenticated call in under five minutes.
# REST API conventions
Source: https://docs.saucerswap.finance/api-reference/conventions
How the SaucerSwap REST API represents money and time: tinybar prices, smallest-unit amounts as strings, unix timestamps, and interval endpoints.
The REST API represents amounts, prices, and time the same way across every endpoint. Read this page once before parsing any response.
Every REST API request requires an API key in the `x-api-key` header. Request a key by emailing [support@saucerswap.finance](mailto:support@saucerswap.finance), then see [REST API authentication](/api-reference/authentication) for setup and quota details.
## Identifiers
| Identifier | Format | Example |
| ----------- | -------------------------------------------------------- | -------------------- |
| Token id | Hedera entity id (`shard.realm.num`) | `0.0.731861` (SAUCE) |
| Account id | Hedera entity id (`shard.realm.num`) | `0.0.12345` |
| Contract id | Hedera entity id (`shard.realm.num`) | `0.0.1465865` |
| Pool id | SaucerSwap-assigned integer, unique per protocol version | `1` |
V1 and V2 pool ids are separate sequences: `/pools/{poolId}` and `/v2/pools/{poolId}` are different pools even when the id matches.
## Units and amounts
HBAR-denominated values are expressed in tinybar, the smallest unit of HBAR: 1 HBAR = 100,000,000 tinybar. TVL, volume, and token `price` fields are all tinybar values.
Token amounts are expressed in each token's smallest unit, determined by its `decimals` field. SAUCE has 6 decimals, so a reserve of `"242601707456381"` is 242,601,707.456381 SAUCE.
Large integers are returned as JSON strings. Fields such as `price`, `tvl`, `volume`, `liquidity`, and reserves exceed JavaScript's safe-integer range, so keep them as strings or parse them with `BigInt` — casting to `Number` silently loses precision.
| Field pattern | Type | Meaning |
| ------------------------------------------------------- | ------ | -------------------------------------------------- |
| `price` | string | Price of one whole token, in tinybar |
| `priceUsd` | number | Price of one whole token, in USD |
| `volume`, `liquidity`, `*Reserve*` | string | Amounts in the smallest unit of the relevant token |
| `tvl`, `volumeTotal` | string | Protocol-wide values in tinybar |
| `tvlUsd`, `volumeTotalUsd`, `volumeUsd`, `liquidityUsd` | number | USD values as floats |
## Timestamps
| Format | Where it appears | Example |
| ----------------------------------- | -------------------------------------------------------------------------------------- | ---------------------- |
| Unix seconds (integer) | `timestampSeconds`, `startTimestampSeconds`, and the `from`/`to` query parameters | `1697616900` |
| Unix `seconds.nanoseconds` (string) | Consensus-derived fields such as farm `timestamp` and position `createdAt`/`updatedAt` | `1682469351.387795003` |
| Unix milliseconds (integer) | The `x-ratelimit-reset` response header | `1746071999999` |
Candlestick objects carry both `startTimestampSeconds` (interval start) and `timestampSeconds` (interval end); point-in-time fields such as `liquidity` are measured at the interval end.
## Interval endpoints
Historical endpoints take a required `from` and `to` in unix seconds plus an `interval`:
| Endpoint family | Supported intervals |
| ----------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| Token and pool candlesticks (`/tokens/prices/...`, `/pools/conversionRates/...`, `/v2/pools/conversionRates/...`) | `FIVEMIN`, `HOUR`, `DAY`, `WEEK` |
| Platform history (`/stats/platformData`) | `HOUR`, `DAY`, `WEEK` |
| HBAR price history (`/stats/hbarHistoricalPrices`) | Minutely, no `interval` parameter |
Each candlestick family also has a `latest` variant that returns the most recent candle without a time range: [latest token candlestick](/api-reference/rest/tokens/token-price-latest), [latest candlesticks for all tokens](/api-reference/rest/tokens/ohlcv-latest), and [latest V1 pool candlestick](/api-reference/rest/pools-v1/pool-conversion-rates-latest).
Pool conversion-rate endpoints accept an optional `inverted` flag to flip the quote direction of the pair.
## Pagination
REST API endpoints do not paginate: list endpoints return the full result set in one response. Bound the size of historical queries with `from` and `to` instead of requesting long ranges you do not need.
The Orderbook API trade tape is the exception in the SaucerSwap API family — it takes `page` and `limit` parameters. See [Orderbook market data](/api-reference/orderbook/market-data).
## Next steps
Handle 401, 403, and 429 responses and monitor your monthly quota.
Put the interval conventions to work on OHLCV candlestick data.
Request an API key and read the quota headers on every response.
A curl ladder from token list to pool data to your first quote.
# REST API errors and rate limits
Source: https://docs.saucerswap.finance/api-reference/errors
Interpret REST API error statuses including 401, 403, and 429, monitor monthly quota headers, and build retry logic that respects your limits.
The REST API uses standard HTTP status codes. This page covers the statuses you should handle, the quota headers to monitor, and how to retry safely.
## Status codes
| Status | Meaning | What to do |
| ------ | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `200` | Success | Parse the JSON body. |
| `400` | Invalid request — a malformed or missing parameter, such as an out-of-range `from`/`to` or an unsupported `interval` | Fix the request; do not retry unchanged. |
| `401` | Missing or invalid `x-api-key` header | Check that the key is present, unexpired, and sent on every request. |
| `403` | The key is not authorized for the request | Contact [support@saucerswap.finance](mailto:support@saucerswap.finance) about your key's access. |
| `404` | Unknown resource, such as a token or pool id that does not exist | Verify the id against the corresponding list endpoint. |
| `429` | Rate limited — the monthly quota is exhausted or requests are arriving too fast | Back off and retry later; see below. |
| `5xx` | Server error | Retry with exponential backoff. |
## Quota headers
Every response reports your monthly quota state. The quota is set when your key is provisioned — see [REST API authentication](/api-reference/authentication).
| Header | Meaning |
| ------------------------------ | --------------------------------------------------------------------- |
| `x-ratelimit-limit` | Total requests allowed per month |
| `x-ratelimit-remaining` | Requests left this month |
| `x-ratelimit-additional-total` | Requests counted over the limit, when overage has been arranged |
| `x-ratelimit-reset` | Unix timestamp in milliseconds when usage resets, typically month end |
## Retry guidance
1. Read `x-ratelimit-remaining` on every response and self-throttle before you hit zero — alerting at a threshold such as 10% remaining gives you time to react.
2. On `429`, wait and retry with exponential backoff and jitter. The monthly quota does not refill until `x-ratelimit-reset`, so tight retry loops only waste requests.
3. Cache stable responses. Token metadata and pool lists change rarely; candlestick history for a closed interval never changes.
4. If you expect sustained higher volume, arrange a larger quota or overage with [support@saucerswap.finance](mailto:support@saucerswap.finance) before you need it, rather than after requests start failing.
The V3 Orderbook API has its own error format — a JSON body of `{ "error": "message string" }` — and its own rate and policy limits. See [Orderbook limits and errors](/api-reference/orderbook/limits-and-errors).
## Next steps
Request an API key and understand how quotas are provisioned.
Parse amounts, prices, and timestamps correctly before debugging errors.
Policy limits and error handling for the V3 Orderbook API.
# Orderbook API authentication
Source: https://docs.saucerswap.finance/api-reference/orderbook/authentication
Authenticate with the SaucerSwap V3 Orderbook API: the challenge and verify JWT flow, supported account and key types, and how to protect your tokens.
The Orderbook API uses wallet challenge authentication and short-lived JSON Web Tokens (JWTs). You prove control of a trading account by signing a server-issued challenge, then attach the resulting JWT to protected calls.
Prerequisites:
* A Hedera account (`0.0.X`) or EVM account (`0x...`) with a supported key type — see [supported account identifiers](#supported-account-identifiers)
* The API base URL for your environment — see [environments](/api-reference/orderbook/overview#environments)
## Public and protected endpoints
Endpoints split into two groups:
| Group | Endpoints |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Public (no JWT) | `GET /books`, `GET /depth/:orderbookId`, `GET /trades/:orderbookId`, `GET /books/:id/quote/exact-input`, `GET /books/:id/quote/exact-output`, and `GET /signature/domain`. Call these without authenticating. |
| Authenticated (JWT required) | Fee rates, onboarding status, order listing and history, build/save/cancel, and both WebSocket streams — everything scoped to an account or mutating state. |
Protected endpoints require a JWT issued by the `/auth` flow. Attach the JWT to REST calls with:
```http theme={null}
Authorization: Bearer
```
## Authentication flow
Submit your `accountId` to `POST /auth/challenge` and receive a nonce message to sign.
Challenge request:
```json theme={null}
{ "accountId": "0.0.123456" }
```
Challenge response:
```json theme={null}
{ "message": "..." }
```
Sign the challenge message client-side with the account key.
Submit `accountId` and `signature` to `POST /auth/verify` and receive a JWT.
Verify request:
```json theme={null}
{
"accountId": "0.0.123456",
"signature": "0x..."
}
```
Verify response:
```json theme={null}
{ "token": "jwt" }
```
## Supported account identifiers
| Account format | Supported key types | Notes |
| -------------- | ---------------------------- | --------------------------------------------------- |
| `0.0.X` | `ED25519`, `ECDSA_SECP256K1` | Key type is resolved through the Hedera Mirror Node |
| `0x...` | `ECDSA_SECP256K1` | Treated as an EVM account |
## Token lifetime
JWTs are short-lived. Re-authenticate before a long-running session expires or whenever a protected call returns `401`. Re-authenticate before each WebSocket reconnect attempt — see [WebSockets](/api-reference/orderbook/websockets).
Never put a primary wallet private key in a bot process. Use a dedicated integration account, store secrets server-side, and start on testnet before placing mainnet orders.
WebSocket streams pass the JWT in the `token` query parameter, so WebSocket URLs are as sensitive as the token itself. Avoid logging full WebSocket URLs in production.
## Next steps
Use your JWT to build, sign, and save orders through the placement flow.
Connect both authenticated streams and handle reconnects and token renewal.
Read the public endpoints that need no JWT: books, depth, trades, and quotes.
Handle `401` renewals, rate limits, and the shared error response format.
# Orderbook API limits and errors
Source: https://docs.saucerswap.finance/api-reference/orderbook/limits-and-errors
SaucerSwap V3 Orderbook API policy limits, the error response format, common HTTP status codes, and a production readiness checklist for clients.
Production users should expect rate and service-protection limits. Teams planning sustained high-volume traffic should contact [support@saucerswap.finance](mailto:support@saucerswap.finance) so we can coordinate limits and support.
## Policy limits
The API applies these limits automatically:
| Constraint | Value |
| --------------------------------- | ------------------- |
| Max open orders per wallet | `5,000` |
| Min order deadline | 30 seconds from now |
| Max order deadline | 90 days from now |
| Max orders per build/save request | `250` |
| Max orders per cancel request | `500` |
If a requested deadline exceeds the max, the server may clamp the returned order deadline. Always sign the deadline in the built order response — see [place orders](/api-reference/orderbook/orders#place-orders).
## Error format
Errors are returned as:
```json theme={null}
{ "error": "message string" }
```
Common statuses:
| Status | Meaning |
| ------ | ---------------------------------------------------------- |
| `400` | Invalid request |
| `401` | Missing or expired JWT |
| `403` | Authenticated account is not allowed to perform the action |
| `404` | Resource not found |
| `429` | Rate limited |
| `500` | Server error |
On `401`, re-run the [authentication flow](/api-reference/orderbook/authentication#authentication-flow) and retry with a fresh JWT.
## Production checklist
Before placing sustained mainnet flow, confirm your client can:
* re-authenticate after `401` responses
* reconnect WebSockets with backoff
* rebuild local books from snapshot plus buffered diffs
* treat cancellation `202` responses as acknowledgements, not final states
* keep all `uint256` values as strings through signing and saving
* use the order book token decimals when converting raw amounts for display or order sizing
* store JWTs and private keys only in server-side secret storage
* monitor open order count, deadlines, and rate-limit responses
* reconcile user events with `GET /orders/:orderId/history` after reconnects
## Next steps
Handle JWT expiry and `401` renewals with the challenge and verify flow.
Implement reconnects, backoff, and snapshot-plus-diff book rebuilds.
Review deadline handling, batch caps, and cancellation finality in context.
Return to the integration flow and the full endpoint summary.
# Orderbook API market data
Source: https://docs.saucerswap.finance/api-reference/orderbook/market-data
Read public SaucerSwap V3 market data: order book discovery, depth snapshots, the trade tape, exact-input and exact-output quotes, and pip fee units.
The endpoints on this page are designed to be public — callable without a JWT. Market discovery gives you the token identifiers and increments you need before [building orders](/api-reference/orderbook/orders); quotes let you simulate a market order against the live book first.
Unauthenticated access and the trade-tape and quote routes ship with the July 2026 Orderbook API deployment, which is rolling out network by network. Until the rollout reaches a network, its endpoints return `401 Missing Authorization header` without a JWT (and `404` for routes that are not yet mounted). Test current availability with a keyless `GET /books` against the [environment](/api-reference/orderbook/overview#environments) you target; if it returns `401`, use [wallet authentication](/api-reference/orderbook/authentication) in the meantime.
## Market discovery
Use `GET /books` to discover tradable order books before building orders. Key market fields include token identifiers, market status, trading increments, and the current AMM-routing flag:
```typescript theme={null}
interface OrderbookItem {
id: number
baseTokenId: string
quoteTokenId: string
baseTokenEvmAddress: string
quoteTokenEvmAddress: string
status: string // 'OPEN' | 'CLOSED'
isAMMEnabled: 0 | 1 // whether AMM liquidity is routed into this book
isMarketHalted: 0 | 1
baseTokenSymbol: string | null
quoteTokenSymbol: string | null
baseTokenDecimals: number | null // token decimals, e.g. 8 for WBTC
quoteTokenDecimals: number | null // token decimals, e.g. 6 for USDC
tickStep: string
sizeStep: string
lotSize: string
minNotional: string
}
```
Additional price, volume, and timestamp fields may also be present.
Use the returned EVM token addresses for `inputToken` and `outputToken` when building orders. Use `baseTokenDecimals` and `quoteTokenDecimals` when converting between human-readable display amounts and raw token amounts. Keep the build, sign, and save path on raw token units. If `isAMMEnabled` is `1`, AMM liquidity can be routed into that book when an order request also opts into AMM-backed settlement.
## Depth snapshots
`GET /depth/:orderbookId` returns a full depth snapshot for a market. For a live view, pair the REST snapshot with the `/ws/depth` stream and apply the snapshot-plus-buffered-diffs procedure described in [WebSockets](/api-reference/orderbook/websockets#reliable-depth-handling).
## Trade tape
`GET /trades/:orderbookId` returns recent fills for a single market, most-recent first by default. It is public, market-wide data — not scoped to any account.
```text theme={null}
GET /trades/3?sort=desc&page=1&limit=50
```
| Query param | Type | Default | Description |
| ----------- | ----------------- | ------- | --------------------- |
| `sort` | `'asc' \| 'desc'` | `desc` | Order fills by time |
| `page` | number | `1` | 1-indexed page number |
| `limit` | number | `10` | Page size |
```typescript theme={null}
interface RecentTradesResult {
orderbookId: string
timestamp: number // server time of the response
trades: Trade[]
total: number
page: number
limit: number
}
interface Trade {
timestamp: number
price: string // human-readable quote-per-base price
amountBase: string // human-readable base token amount, already decimals-adjusted (e.g. "125.5" HBAR — NOT raw smallest units)
direction: string // 'buy' | 'sell' (taker side)
transactionHash: string
}
```
An invalid `sort`, or a negative `page` or `limit`, returns `400` (zero and non-numeric values fall back to the defaults). Responses are served from a short-lived cache of recent fills, so poll rather than hammer.
## Market quotes
Simulate a market order against the current book before building it. Both endpoints are public; authentication is optional — anonymous callers get a lightly-cached quote, an authenticated caller gets a fresh one. The `suggested*` amount each returns is safe to pass directly into a subsequent `POST /orders/build` request.
### Exact input
You specify what you spend, and the response tells you what to expect to receive:
```text theme={null}
GET /books/3/quote/exact-input?inputToken=0x...&inputAmount=1000000
```
| Query param | Type | Required | Description |
| ------------- | ------ | -------- | ----------------------------------------- |
| `inputToken` | string | Yes | EVM address of the token being spent |
| `inputAmount` | string | Yes | Raw token units (integer string) to spend |
```typescript theme={null}
interface ExactInputQuoteResult {
outputToken: string
snappedInputAmount: string // input floored to the lot/size grid (submit THIS)
consumedInputAmount: string // how much of snappedInputAmount the book absorbed
expectedOutputAmount: string // raw expected fill, no slippage
suggestedOutputAmount: string // use as outputAmount in POST /orders/build
slippageBps: number // the applied slippage buffer (a fixed server-side tolerance), not a market-impact prediction
fillable: boolean // false when no liquidity exists at all
}
```
### Exact output
You specify the receive side, and the response returns the input required, with slippage applied upward as a safe ceiling:
```text theme={null}
GET /books/3/quote/exact-output?outputToken=0x...&outputAmount=500000
```
| Query param | Type | Required | Description |
| -------------- | ------ | -------- | ------------------------------------------- |
| `outputToken` | string | Yes | EVM address of the token to receive |
| `outputAmount` | string | Yes | Raw token units (integer string) to receive |
```typescript theme={null}
interface ExactOutputQuoteResult {
inputToken: string
requestedOutputAmount: string // echo of what was asked
snappedOutputAmount: string // what you'll actually get (= requested when on-grid)
expectedInputAmount: string // raw cost, no slippage
suggestedInputAmount: string // bumped UP by slippage — use as inputAmount in POST /orders/build
slippageBps: number // the applied slippage buffer (a fixed server-side tolerance), not a market-impact prediction
fillable: boolean // false when book depth < outputAmount
}
```
A missing required query param, or an unknown order book, returns `400`.
## Fee units
Fee rates are expressed in pips (1 pip = 1e-6 = 0.0001%), matching the `takerFeePips` / `makerFeePips` / `capFractionPips` field names. They are not basis points.
Authenticated accounts can fetch their fee rates for an order book side with `GET /fees/:orderbookId?side=maker` — this endpoint requires a JWT. See [authentication](/api-reference/orderbook/authentication).
## Next steps
Turn a quote into a signed order with the build, sign, save flow.
Keep a local book live with depth diffs layered over REST snapshots.
Obtain a JWT for fee rates, onboarding status, and fresh quotes.
Review request validation errors, rate limits, and the error format.
# Orderbook API orders
Source: https://docs.saucerswap.finance/api-reference/orderbook/orders
Place and cancel SaucerSwap V3 orders: fetch the EIP-712 domain, build orders, sign with the mode-byte prefix, save them, and confirm cancellations.
Order placement is a build, sign, save flow against the reactor contract's EIP-712 domain. Cancellation is asynchronous and confirmed through order events, with the on-chain reactor as the source of truth.
Prerequisites:
* A valid JWT — see [authentication](/api-reference/orderbook/authentication)
* Token EVM addresses and decimals for your market from `GET /books` — see [market discovery](/api-reference/orderbook/market-data#market-discovery)
Programmatic order placement is governed by the separate API terms of service, not the web app's in-app acceptance gate — see [legal terms](/api-reference/orderbook/overview#legal-terms).
The `client` calls in the examples below use the wrapper surface described in the [TypeScript bot client](/developers/orderbook/typescript-client); you can also call the REST endpoints directly.
## Place orders
The signing domain is environment-specific. Fetch it once with `GET /signature/domain` and cache it for the session.
```typescript theme={null}
const domain = await client.getDomain()
// { name, version, chainId, verifyingContract }
```
`verifyingContract` is the reactor contract address used for signatures, and `chainId` identifies the Hedera network.
Build orders with `POST /orders/build`:
```typescript theme={null}
const orders = await client.buildOrders([
{
orderbookId: '3',
type: 'LIMIT',
deadline: String(Math.floor(Date.now() / 1000) + 3600),
inputToken: '0xbase-token-evm-address',
inputAmount: '1000000',
outputToken: '0xquote-token-evm-address',
outputAmount: '950000',
makerOnly: false,
takerOnce: false,
isAMMEnabled: true,
},
])
```
The server assigns each order nonce and returns the serialized order struct to sign. Always sign the returned order object, not your original request object.
| Field | Type | Required | Description |
| -------------- | ------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `orderbookId` | `string` | Yes | Market ID |
| `type` | `LIMIT` or `MARKET` | Yes | Order type |
| `deadline` | `string` | LIMIT only | Unix timestamp in seconds. Omit for market orders. |
| `inputToken` | `string` | Yes | EVM address of the token being sold |
| `inputAmount` | `string` | Yes | Raw token amount, in smallest units. For an exact-input market order, use the quote's `snappedInputAmount`; for exact output, use `suggestedInputAmount`. |
| `outputToken` | `string` | Yes | EVM address of the token being bought |
| `outputAmount` | `string` | Yes | Minimum raw output amount. For an exact-input market order, use the quote's `suggestedOutputAmount`. For an exact-output order, use `snappedOutputAmount` and set `inputAmount` to `suggestedInputAmount`. |
| `recipient` | `string` | No | Output recipient EVM address |
| `makerOnly` | `boolean` | No | Restrict order to maker fills |
| `takerOnce` | `boolean` | No | Allow only one taker fill |
| `isAMMEnabled` | `boolean` | No | Permit AMM-backed settlement |
Quote the current book immediately before building a market order and continue only when `fillable === true`. For exact input, submit `snappedInputAmount` and `suggestedOutputAmount`; for exact output, submit `suggestedInputAmount` and `snappedOutputAmount`. Never use `"1"` as a market order's `outputAmount`: that removes practical price protection from the signed order. Keep all integer quantities as strings, and do not cast nonces, deadlines, or raw token amounts to JavaScript numbers before signing. See [Market quotes](/api-reference/orderbook/market-data#market-quotes).
Sign only the EIP-712 order fields. Exclude metadata returned by the API.
The signature wire format starts with a one-byte mode prefix:
| Prefix | Mode | Typical use |
| ------ | -------------------- | -------------------------------------------------------------------------------------------- |
| `0x00` | EIP-712 | ECDSA bot clients and ED25519 bot clients signing the EIP-712 hash |
| `0x01` | Hedera personal sign | Wallet flows that return a HIP-632 `SignatureMap` for a HIP-820 Hedera personal-sign payload |
Do not strip the prefix. The reactor and backend use the prefix to choose the verifier.
```typescript theme={null}
const signature = await client.signOrder(orders[0], privateKey, domain)
```
For concrete `ECDSA_SECP256K1` and `ED25519` signing steps, see the [TypeScript bot client signing behavior](/developers/orderbook/typescript-client#signing-behavior).
Submit signed orders with `POST /orders/save`:
```typescript theme={null}
const { orders: saved } = await client.saveOrders([
{
order: orders[0],
signature,
orderbookId: '3',
type: 'LIMIT',
},
])
```
The response returns an `orders` array with saved order objects and `meta.status` populated. If `ocoLinks` were supplied, the response may also include an `oco` block with link status.
## OCO orders
`POST /orders/save` also supports optional one-cancels-the-other (OCO) metadata through `ocoLinks`. OCO links are server-side transport metadata; they are not included in the EIP-712 digest and are not submitted to the reactor.
Each link pairs two items in the same save request:
```json theme={null}
{
"items": [
{ "order": {}, "signature": "0x...", "orderbookId": "3", "type": "LIMIT" },
{ "order": {}, "signature": "0x...", "orderbookId": "3", "type": "LIMIT" }
],
"ocoLinks": [
{ "a": 0, "b": 1 }
]
}
```
OCO pairs must share the same `orderbookId` and swapper, and currently only `LIMIT` orders are supported in OCO pairs.
## Cancellations
Cancellation endpoints are asynchronous. A `202 Accepted` response means the cancellation request was accepted; it does not mean the order is already canceled.
Use the [user-event WebSocket](/api-reference/orderbook/websockets#user-events) or `GET /orders/:orderId/history` to confirm the final `ORDER_CANCELED` event.
`POST /cancel` accepts up to 500 order IDs per request. Split larger cancellation batches into multiple requests and reconcile each accepted order through the user-event stream or order history.
| Endpoint | Description |
| ------------------ | ---------------------------------------------- |
| `POST /cancel` | Request cancellation for one or more order IDs |
| `POST /cancel/all` | Emergency cancel by nonce floor |
The on-chain reactor remains the source of truth. Advanced clients can also submit on-chain cancellations directly to the reactor, then rely on indexer reconciliation.
## Next steps
Track fills and cancellation finality on the user-event stream.
Check order deadline bounds, batch size caps, and the production checklist.
See the full flow — authenticate, build, sign, save, cancel — as working code.
Quote a market order first and feed the suggested amounts into the build call.
# Orderbook API overview
Source: https://docs.saucerswap.finance/api-reference/orderbook/overview
Integrate with the SaucerSwap V3 Orderbook API: the integration flow, testnet and mainnet environments, and a full endpoint summary with auth requirements.
The SaucerSwap V3 Orderbook API is designed for programmatic trading clients, market makers, wallets, dashboards, analytics surfaces, and other integrations that need order placement, cancellation, account order state, and live order book data.
Public market data — the order book list, depth snapshots, the trade tape, market quotes, and the EIP-712 signature domain — requires no authentication. Anything that reads per-account data or mutates state requires [wallet authentication](/api-reference/orderbook/authentication). Production users should expect rate and service-protection limits. Teams planning sustained high-volume traffic should contact [support@saucerswap.finance](mailto:support@saucerswap.finance) so we can coordinate limits and support.
Unauthenticated market-data access ships with the July 2026 Orderbook API deployment and is rolling out network by network. Until the rollout reaches a network, its read endpoints still require a JWT. Test availability with a keyless `GET /books`; see [market data](/api-reference/orderbook/market-data) for details.
This API is separate from the legacy SaucerSwap REST API. The [legacy REST API](/api-reference/authentication) uses `x-api-key` authentication. The V3 Orderbook API uses wallet challenge authentication and short-lived JWTs.
## Integration flow
| Phase | What your client does | Primary API surface |
| ------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| Discover markets | List order books — no authentication needed | `GET /books` |
| Read market data | Fetch depth, the trade tape, and market quotes; subscribe to diffs | `GET /depth/:orderbookId`, `GET /trades/:orderbookId`, `GET /books/:id/quote/exact-input`, `/ws/depth` |
| Authenticate | Sign a challenge with the trading account | `POST /auth/challenge`, `POST /auth/verify` |
| Check account state | Fees and onboarding status for the account | `GET /fees/:orderbookId`, `GET /onboarding/:orderbookId/status` |
| Place orders | Build, sign, and save orders | `GET /signature/domain`, `POST /orders/build`, `POST /orders/save` |
| Reconcile | Track order events and recover state after reconnects | `/ws/user-events`, `GET /orders`, `GET /orders/:orderId/history` |
| Cancel | Request cancellation or submit on-chain cancellation | `POST /cancel`, `POST /cancel/all`, reactor cancellation |
Each phase has a dedicated page: [authentication](/api-reference/orderbook/authentication), [market data](/api-reference/orderbook/market-data), [orders](/api-reference/orderbook/orders), [WebSockets](/api-reference/orderbook/websockets), and [limits and errors](/api-reference/orderbook/limits-and-errors).
Authenticate first, then use testnet before moving the same flow to mainnet. Move to mainnet after your client handles authentication renewal, WebSocket reconnects, cancellation finality, and integer string handling correctly.
## Environments
| Environment | API base URL | Hedera Mirror Node |
| ----------- | -------------------------------------------------- | --------------------------------------- |
| Testnet | `https://testnet-orderbook-api.saucerswap.finance` | `https://testnet.mirrornode.hedera.com` |
| Mainnet | `https://orderbook-api.saucerswap.finance` | `https://mainnet.mirrornode.hedera.com` |
WebSocket streams use the same host with the `wss://` scheme.
## Endpoint summary
| Category | Endpoint | Auth | Description |
| ------------ | ------------------------------------- | ------ | ------------------------------------------------------ |
| Markets | `GET /books` | Public | List available order books |
| Market data | `GET /depth/:orderbookId` | Public | Fetch a full depth snapshot |
| Market data | `GET /trades/:orderbookId` | Public | Recent fills (the public trade tape) |
| Quotes | `GET /books/:id/quote/exact-input` | Public | Simulate a market order from the spend side |
| Quotes | `GET /books/:id/quote/exact-output` | Public | Simulate a market order from the receive side |
| Signing | `GET /signature/domain` | Public | Fetch the EIP-712 domain for the active environment |
| Fees | `GET /fees/:orderbookId?side=maker` | JWT | Fetch fee rates for an order book side, in pips (1e-6) |
| Onboarding | `GET /onboarding/:orderbookId/status` | JWT | Check whether the account can trade a market |
| Orders | `GET /orders` | JWT | List authenticated account orders |
| Orders | `GET /orders/:orderId/history` | JWT | Fetch per-order event history |
| Placement | `POST /orders/build` | JWT | Build unsigned orders with server-assigned nonces |
| Placement | `POST /orders/save` | JWT | Submit signed orders |
| Cancellation | `POST /cancel` | JWT | Request cancellation for specific order IDs |
| Cancellation | `POST /cancel/all` | JWT | Emergency cancel by nonce floor |
| WebSocket | `/ws/depth` | JWT | Subscribe to live order book depth diffs |
| WebSocket | `/ws/user-events` | JWT | Subscribe to authenticated order events |
Fee rates are expressed in pips, not basis points — see [fee units](/api-reference/orderbook/market-data#fee-units).
## Legal terms
The web app requires users to accept in-app legal terms before creating orders. The API does not — programmatic consumers are governed by the separate API terms of service, and `POST /orders/save` bypasses the in-app acceptance gate. There is no legal-acceptance call to make before placing orders through the API.
## Next steps
Run the challenge and verify flow to obtain a JWT for protected endpoints.
Discover markets, read depth and the trade tape, and simulate orders with quotes.
Build, sign, and save orders, then cancel them and confirm finality.
Follow a reference client pattern for server-side bots and market makers.
# Orderbook API WebSockets
Source: https://docs.saucerswap.finance/api-reference/orderbook/websockets
Subscribe to SaucerSwap V3 Orderbook API WebSocket streams: depth diffs and user events, token authentication, and snapshot-plus-diff book handling.
The Orderbook API exposes two WebSocket streams: `/ws/depth` for live order book depth diffs and `/ws/user-events` for authenticated order events. Both require authentication.
Prerequisites:
* A valid JWT — see [authentication](/api-reference/orderbook/authentication)
* Order book IDs from `GET /books` — see [market discovery](/api-reference/orderbook/market-data#market-discovery)
## Connection
Both streams require a valid JWT in the `token` query parameter, and take the target markets as a comma-separated list in the `books` query parameter:
```text theme={null}
wss:///ws/depth?token=&books=,
wss:///ws/user-events?token=&books=,
```
The host is the API base URL for your environment with the `wss://` scheme — see [environments](/api-reference/orderbook/overview#environments).
| Stream | Purpose |
| ----------------- | ---------------------------------------- |
| `/ws/depth` | Subscribe to live order book depth diffs |
| `/ws/user-events` | Subscribe to authenticated order events |
Treat WebSocket URLs as sensitive because they contain the JWT. Avoid logging full URLs in production.
## Reliable depth handling
For reliable depth handling:
Open `/ws/depth` for the books you track.
Buffer incoming diffs while fetching the REST depth snapshot from `GET /depth/:orderbookId`.
Replay the buffered diffs on top of the snapshot to bring the local book current.
Keep applying live diffs as they arrive.
## User events
The user-event stream carries order events for the authenticated account. Use it — or `GET /orders/:orderId/history` — to confirm the final `ORDER_CANCELED` event after a [cancellation request](/api-reference/orderbook/orders#cancellations), and to track order events and recover state after reconnects alongside `GET /orders`.
## Reconnects and token expiry
Re-authenticate before each reconnect attempt. Active WebSocket connections are verified at handshake time; a connection can remain open after its original JWT expires.
## Next steps
Place orders, then confirm fills and cancellations on the user-event stream.
Fetch the REST depth snapshot that anchors your snapshot-plus-diff book.
Meet the production checklist for reconnects, backoff, and book rebuilds.
See a working depth-stream subscription with connection handlers.
# SaucerSwap API reference
Source: https://docs.saucerswap.finance/api-reference/overview
Orientation for SaucerSwap's two HTTP APIs — the REST data API and the V3 Orderbook API — with base URLs, authentication models, and an endpoint index.
SaucerSwap exposes two separate HTTP APIs. The REST API serves protocol data: tokens, prices, candlesticks, pools, positions, farms, and statistics. The Orderbook API serves the V3 order book: market data, quotes, order placement, cancellation, and WebSocket streams.
## Two APIs at a glance
| API | Best for | Authentication | Mainnet base URL |
| ------------- | ------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------ |
| REST API | Prices, charts, pools, positions, farms, protocol stats | `x-api-key` header on every request | `https://api.saucerswap.finance` |
| Orderbook API | V3 order book market data, quotes, and trading | Public reads; wallet-JWT for account endpoints | `https://orderbook-api.saucerswap.finance` |
## Authentication comparison
The two APIs use different access models. Keys and tokens are not interchangeable between them.
| Access model | Applies to | Credential | How you get it |
| ------------ | ---------------------------------------------------------------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| API key | Every REST API endpoint | `x-api-key` header | Email [support@saucerswap.finance](mailto:support@saucerswap.finance); see [REST API authentication](/api-reference/authentication) |
| Public read | Orderbook API market data: books, depth, trades, quotes, and the signature domain | None | No signup; see [Orderbook market data](/api-reference/orderbook/market-data) |
| Wallet JWT | Orderbook API account endpoints: fees, onboarding, orders, cancels, and both WebSocket streams | `Authorization: Bearer ` | Sign a challenge with your account key; see [Orderbook authentication](/api-reference/orderbook/authentication) |
## Base URLs
REST API:
| Hedera network | Base URL |
| -------------- | ------------------------------------- |
| Mainnet | `https://api.saucerswap.finance` |
| Testnet | `https://test-api.saucerswap.finance` |
Orderbook API:
| Environment | Base URL |
| ----------- | -------------------------------------------------- |
| Mainnet | `https://orderbook-api.saucerswap.finance` |
| Testnet | `https://testnet-orderbook-api.saucerswap.finance` |
Orderbook WebSocket streams use the same hosts with the `wss://` scheme.
## Endpoints by capability
| I want to... | Start here |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Get token prices and metadata | [List all tokens](/api-reference/rest/tokens/list-tokens) |
| Build price charts (OHLCV candlesticks) | [Token price history](/api-reference/rest/tokens/token-price-history) and [latest candlesticks for all tokens](/api-reference/rest/tokens/ohlcv-latest) |
| Read V1 pool reserves and history | [List V1 pools](/api-reference/rest/pools-v1/list-pools) |
| Read V2 pools, positions, and LARI rewards | [List V2 pools](/api-reference/rest/pools-v2/list-v2-pools) and [V2 positions by account](/api-reference/rest/pools-v2/v2-positions-by-account) |
| Read farm emissions and staked amounts | [List active farms](/api-reference/rest/farms/list-farms) |
| Get protocol-wide TVL, volume, and staking stats | [General statistics](/api-reference/rest/stats/general-stats) |
| Read the V3 order book, trade tape, and quotes | [Orderbook market data](/api-reference/orderbook/market-data) |
| Place and cancel V3 orders programmatically | [Orderbook orders](/api-reference/orderbook/orders) |
| Stream live depth and order events | [Orderbook WebSockets](/api-reference/orderbook/websockets) |
## Rate limits
The REST API enforces a monthly request quota per API key, agreed when your key is provisioned, and reports usage through `x-ratelimit-*` response headers. See [REST API errors and rate limits](/api-reference/errors).
The Orderbook API applies rate and service-protection limits and returns `429` when they are exceeded, plus policy limits on order counts and deadlines. See [Orderbook limits and errors](/api-reference/orderbook/limits-and-errors). Teams planning sustained high-volume traffic should contact [support@saucerswap.finance](mailto:support@saucerswap.finance) to coordinate limits.
## Next steps
Request an API key and make your first authenticated call.
Understand tinybar, smallest-unit amounts, timestamps, and intervals.
Integrate with the V3 order book, from market data to order placement.
Make your first API call in under five minutes.
# REST API: Farm LP totals by account
Source: https://docs.saucerswap.finance/api-reference/rest/farms/farm-totals-by-account
GET /farms/totals/{accountId}
Retrieve the LP token amounts a Hedera account has staked in each SaucerSwap farm, with farm id, pool id, and the timestamp of the latest update.
# REST API: List active farms
Source: https://docs.saucerswap.finance/api-reference/rest/farms/list-farms
GET /farms
List all active SaucerSwap yield farms with farm and pool ids, SAUCE and HBAR emission rates per second, and total staked LP token amounts per farm.
# REST API: Daily metrics for all V1 pools
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/all-pools-daily
GET /pools/daily
Retrieve daily volume and liquidity datapoints for all SaucerSwap V1 pools, in each pool's smallest unit, keyed by pool id and unix timestamp.
# REST API: Monthly metrics for all V1 pools
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/all-pools-monthly
GET /pools/monthly
Retrieve monthly volume and liquidity datapoints for all SaucerSwap V1 pools, in each pool's smallest unit, keyed by pool id and unix timestamp.
# REST API: Weekly metrics for all V1 pools
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/all-pools-weekly
GET /pools/weekly
Retrieve weekly volume and liquidity datapoints for all SaucerSwap V1 pools, in each pool's smallest unit, keyed by pool id and unix timestamp.
# REST API: Yearly metrics for all V1 pools
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/all-pools-yearly
GET /pools/yearly
Retrieve yearly volume and liquidity datapoints for all SaucerSwap V1 pools, in each pool's smallest unit, keyed by pool id and unix timestamp.
# REST API: Default listed V1 pools
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/default-listed-pools
GET /pools/known
List default listed SaucerSwap V1 pools, the pools whose tokens completed due diligence, with contract ids, token metadata, and current reserves.
# REST API: Get V1 pool by id
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/get-pool
GET /pools/{poolId}
Retrieve detailed data for one SaucerSwap V1 pool by pool id, including contract id, paired token metadata, current reserves, and LP token details.
# REST API: List V1 pools (compact)
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/list-pools
GET /pools
List all SaucerSwap V1 liquidity pools in compact form, with pool and contract ids, paired token summaries, current reserves, and LP token metadata.
# REST API: List V1 pools (detailed)
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/list-pools-full
GET /pools/full
List all SaucerSwap V1 liquidity pools with full token detail, including descriptions, websites, prices in tinybar and USD, and current reserves.
# REST API: V1 pool price history (candlesticks)
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/pool-conversion-rates
GET /pools/conversionRates/{poolId}
Query historical candlestick conversion rates for a V1 pool between two unix-second timestamps, with optional pair inversion and four interval sizes.
# REST API: Latest V1 pool candlestick
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/pool-conversion-rates-latest
GET /pools/conversionRates/latest/{poolId}
Retrieve the latest candlestick conversion rate for a V1 pool at a chosen interval, with open, high, low, close, volume, and liquidity fields.
# REST API: Daily metrics for a V1 pool
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/pool-daily
GET /pools/daily/{poolId}
Retrieve daily volume and liquidity history for a single SaucerSwap V1 pool by pool id, in smallest units, with unix-second timestamps per point.
# REST API: Monthly metrics for a V1 pool
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/pool-monthly
GET /pools/monthly/{poolId}
Retrieve monthly volume and liquidity history for a single SaucerSwap V1 pool by pool id, in smallest units, with unix-second timestamps per point.
# REST API: Weekly metrics for a V1 pool
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/pool-weekly
GET /pools/weekly/{poolId}
Retrieve weekly volume and liquidity history for a single SaucerSwap V1 pool by pool id, in smallest units, with unix-second timestamps per point.
# REST API: Yearly metrics for a V1 pool
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v1/pool-yearly
GET /pools/yearly/{poolId}
Retrieve yearly volume and liquidity history for a single SaucerSwap V1 pool by pool id, in smallest units, with unix-second timestamps per point.
# REST API: Get V2 pool by id
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v2/get-v2-pool
GET /v2/pools/{poolId}
Retrieve one SaucerSwap V2 pool by pool id, including contract id, token pair detail, fee tier, current tick, sqrt price ratio, and liquidity.
# REST API: LARI rewards by account
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v2/lari-rewards-by-account
GET /v2/rewards/account/{accountId}
Retrieve estimated LARI rewards accrued by a Hedera account for the current epoch, updated hourly, with pool id, token id, and an epoch-final flag.
# REST API: List V2 pools (compact)
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v2/list-v2-pools
GET /v2/pools
List all SaucerSwap V2 concentrated-liquidity pools in compact form, with fee tier, current tick, sqrt price ratio, liquidity, and token amounts.
# REST API: List V2 pools (detailed)
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v2/list-v2-pools-full
GET /v2/pools/full
List all SaucerSwap V2 concentrated-liquidity pools with full token metadata alongside fee tier, current tick, sqrt price ratio, and liquidity.
# REST API: V2 pool price history (candlesticks)
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v2/v2-pool-conversion-rates
GET /v2/pools/conversionRates/{poolId}
Query historical candlestick conversion rates for a SaucerSwap V2 pool between two unix-second timestamps, with optional inversion of the pair.
# REST API: V2 liquidity positions by account
Source: https://docs.saucerswap.finance/api-reference/rest/pools-v2/v2-positions-by-account
GET /v2/nfts/{accountId}/positions
List all SaucerSwap V2 liquidity positions for a Hedera account, with NFT serials, tick ranges, liquidity, fee growth, and tokens owed per position.
# REST API: General statistics
Source: https://docs.saucerswap.finance/api-reference/rest/stats/general-stats
GET /stats
Retrieve protocol-wide SaucerSwap statistics in one call: circulating SAUCE supply, total swap count, TVL in tinybar and USD, and all-time volume.
# REST API: Historical HBAR prices
Source: https://docs.saucerswap.finance/api-reference/rest/stats/hbar-historical-prices
GET /stats/hbarHistoricalPrices
Query minutely historical HBAR prices in USD between two unix-second timestamps, for charting, backtesting, and converting tinybar values to dollars.
# REST API: Platform liquidity and volume history
Source: https://docs.saucerswap.finance/api-reference/rest/stats/platform-data
GET /stats/platformData
Query historical platform-wide liquidity or volume in tinybar over hourly, daily, or weekly intervals between two unix-second timestamps you choose.
# REST API: Single-sided staking statistics
Source: https://docs.saucerswap.finance/api-reference/rest/stats/sss-stats
GET /stats/sss
Retrieve single-sided staking statistics: the current xSAUCE to SAUCE ratio, 5-day average APR, and staked SAUCE and xSAUCE amounts in smallest units.
# REST API: Daily metrics for all tokens
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/all-tokens-daily
GET /tokens/daily
Retrieve daily price, volume, and liquidity datapoints for all SaucerSwap tokens, with prices in tinybar and amounts in each token's smallest unit.
# REST API: Monthly metrics for all tokens
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/all-tokens-monthly
GET /tokens/monthly
Retrieve monthly price, volume, and liquidity datapoints for all SaucerSwap tokens, prices in tinybar and amounts in each token's smallest unit.
# REST API: Weekly metrics for all tokens
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/all-tokens-weekly
GET /tokens/weekly
Retrieve weekly price, volume, and liquidity datapoints for all SaucerSwap tokens, with prices in tinybar and amounts in each token's smallest unit.
# REST API: Yearly metrics for all tokens
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/all-tokens-yearly
GET /tokens/yearly
Retrieve yearly price, volume, and liquidity datapoints for all SaucerSwap tokens, with prices in tinybar and amounts in each token's smallest unit.
# REST API: Pools containing a token
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/associated-pools
GET /tokens/associated-pools/{tokenId}
List every SaucerSwap V1 pool that contains a given token, with pool contract ids, paired-token metadata, current reserves, and LP token details.
# REST API: Default listed tokens
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/default-listed-tokens
GET /tokens/known
List default listed tokens, the tokens that have completed SaucerSwap due diligence, with full metadata, prices in tinybar and USD, and decimals.
# REST API: Price changes for default listed tokens
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/default-token-price-changes
GET /tokens/default
Retrieve hourly, daily, and weekly price change percentages plus USD price and liquidity for every default listed token on SaucerSwap in one call.
# REST API: Get token by id
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/get-token
GET /tokens/{tokenId}
Retrieve detailed data for one token by Hedera token id, including price in tinybar and USD, decimals, description, website, and due-diligence flags.
# REST API: List all tokens (compact)
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/list-tokens
GET /tokens
List every token traded on SaucerSwap in compact form: token id, symbol, decimals, icon path, price in tinybar and USD, and due-diligence flags.
# REST API: List all tokens (detailed)
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/list-tokens-full
GET /tokens/full
List every token traded on SaucerSwap with full detail per token: description, website, X handle, sentinel report link, prices, and decimal places.
# REST API: Latest candlesticks for all tokens
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/ohlcv-latest
GET /tokens/ohlcv/latest
Retrieve the latest OHLCV candlestick for every SaucerSwap token in one call at a chosen interval, the bulk endpoint for price and chart refreshes.
# REST API: 24-hour price change map
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/price-change-map
GET /tokens/price-change
Retrieve a mapping from Hedera token id to 24-hour price change percentage for tokens on SaucerSwap, suited to fast dashboard and ticker updates.
# REST API: Daily metrics for a token
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/token-daily
GET /tokens/daily/{tokenId}
Retrieve daily price, volume, and liquidity history for a single token by Hedera token id, with prices in tinybar and unix-second timestamps.
# REST API: Monthly metrics for a token
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/token-monthly
GET /tokens/monthly/{tokenId}
Retrieve monthly price, volume, and liquidity history for a single token by Hedera token id, with prices in tinybar and unix-second timestamps.
# REST API: Token price history (candlesticks)
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/token-price-history
GET /tokens/prices/{tokenId}
Query historical OHLCV candlestick data for a token between two unix-second timestamps at five-minute, hourly, daily, or weekly interval sizes.
# REST API: Latest token candlestick
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/token-price-latest
GET /tokens/prices/latest/{tokenId}
Retrieve the most recent OHLCV candlestick for a token at a chosen interval, with open, high, low, close, and average prices in tinybar and USD.
# REST API: Weekly metrics for a token
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/token-weekly
GET /tokens/weekly/{tokenId}
Retrieve weekly price, volume, and liquidity history for a single token by Hedera token id, with prices in tinybar and unix-second timestamps.
# REST API: Yearly metrics for a token
Source: https://docs.saucerswap.finance/api-reference/rest/tokens/token-yearly
GET /tokens/yearly/{tokenId}
Retrieve yearly price, volume, and liquidity history for a single token by Hedera token id, with prices in tinybar and unix-second timestamps.
# Changelog
Source: https://docs.saucerswap.finance/changelog
Dated record of notable SaucerSwap protocol, app, API, and documentation changes, including the V3 order book launch and the 2026 documentation overhaul.
Notable changes to the SaucerSwap protocol, web app, APIs, and these docs, newest first. Forward-looking plans live on the [roadmap](/roadmap).
These docs were rebuilt end to end: new information architecture across Learn, Protocol, Developers, API Reference, and Resources tabs, a full rewrite to one style guide, generated REST API reference pages from the OpenAPI spec, dedicated Orderbook API reference pages, and removal of stale content — including stale instructions and active-route references to the decommissioned Hashport bridge. Redirects from all previous URLs are in place.
SaucerSwap V3 launched on Hedera mainnet: a central limit order book with off-chain matching and on-chain settlement, limit and market orders on the trade page, and the public Orderbook API for programmatic trading. See [How SaucerSwap V3 works](/protocol/saucerswap-v3) and the [Orderbook API reference](/api-reference/orderbook/overview).
Halborn completed its audit of the SaucerSwap V3 smart contracts ahead of the mainnet launch. The report is linked from the [audits page](/developers/security/audits).
The web app shipped a comprehensive redesign, updating navigation (trade, swap, explore, pool, stake, govern, dashboard, bridge), the token menu, and the transaction flow. Tutorials in these docs reflect the current interface.
## Deprecation notices
When a documented feature, endpoint, or integration path is deprecated or shut down, a dated entry appears here describing the replacement path, and the affected pages receive a warning callout. Entries stay in the changelog permanently so integrators can reconstruct when behavior changed.
## Next steps
See what SaucerSwap Labs is working on next, and what has shipped.
Understand the order book that headlined the June 2026 launch.
Review every security audit of the protocol, from V1 to V3.
# Contact SaucerSwap
Source: https://docs.saucerswap.finance/contact
How to reach SaucerSwap Labs: user support through Discord and email, business development for partnerships, and the official social channels.
Pick the channel that matches your need — support requests, business inquiries, and community discussion each have a dedicated path.
Get help with a transaction, the web app, or your account via Discord or email.
Reach the business development team about integrations and co-marketing.
Follow the verified official SaucerSwap channels and avoid impersonators.
List your token, submit an icon, and apply for farm or LARI incentives.
The SaucerSwap Labs team will never DM you first, and will never ask for your seed phrase, private key, or funds. Verify any interaction against the official accounts listed on the [socials page](/contact/socials).
# Partnership inquiries
Source: https://docs.saucerswap.finance/contact/partnership-inquiries
Contact the SaucerSwap Labs business development team for partnerships, integrations, and co-marketing, or jump to the token listing guide for projects.
For partnership, integration, and co-marketing inquiries, email [outreach@saucerswap.finance](mailto:outreach@saucerswap.finance). Include what your project does, what you are proposing, and links the team can verify.
If you are a token project, most of what you need is self-serve and documented:
* Listing a token — pool creation, token classes, and icon submission are covered in [For projects](/resources/for-projects). Listing is permissionless; you do not need to contact anyone to make your token tradable.
* Farm and LARI incentives — incentive campaigns are governance actions; the application path is described in [For projects](/resources/for-projects) and the [governance process](/governance/overview).
* Market making — professional trading firms should start with the [market makers page](/resources/market-makers).
* API access — developers can start with the [developer overview](/developers/overview); high-volume API consumers should contact [support@saucerswap.finance](mailto:support@saucerswap.finance).
## Next steps
List your token, submit an icon, and apply for farm or LARI incentives.
Onboard to the V3 order book and coordinate limits for sustained flow.
See how incentive proposals move from RFC to on-chain vote.
# Socials
Source: https://docs.saucerswap.finance/contact/socials
The verified official SaucerSwap channels on Discord, X, Reddit, Telegram, Medium, YouTube, Threads, Instagram, and LinkedIn — trust nothing else.
These are the official SaucerSwap channels. Bookmark this page and verify accounts against it — impersonation accounts are common in DeFi.
| Channel | Link |
| --------------------------- | ------------------------------------------------------------------------------ |
| Discord | [SaucerSwap Discord server](https://saucerswap.finance/discord) |
| X (formerly Twitter) — main | [@SaucerSwapLabs](https://x.com/SaucerSwapLabs) |
| X — status updates | [@SaucerStatus](https://x.com/SaucerStatus) |
| X — Korean | [@SaucerswapK](https://x.com/SaucerswapK) |
| X — Japanese | [@SaucerswapJ](https://x.com/SaucerswapJ) |
| X — Spanish | [@SaucerSwapEs](https://x.com/SaucerSwapEs) |
| Reddit | [r/SaucerSwap](https://www.reddit.com/r/SaucerSwap) |
| Telegram | [SaucerSwap on Telegram](https://t.me/SaucerSwapLabs) |
| Medium | [SaucerSwap on Medium](https://medium.com/@saucerswap) |
| YouTube | [SaucerSwap on YouTube](https://www.youtube.com/@saucerswap) |
| Threads | [SaucerSwap on Threads](https://www.threads.net/@saucerswaplabs) |
| Instagram | [SaucerSwap on Instagram](https://www.instagram.com/saucerswaplabs/) |
| LinkedIn | [SaucerSwap Labs on LinkedIn](https://www.linkedin.com/company/saucerswaplabs) |
The SaucerSwap Labs team will never DM you first, and will never ask for your seed phrase, private key, or funds. Treat any account not listed here as unofficial.
## Next steps
Open a Discord ticket or email support for help with the app or a transaction.
See who builds SaucerSwap and their official channels.
Download official logos and icons for posts and listings.
# User support
Source: https://docs.saucerswap.finance/contact/user-support
Get help with SaucerSwap: check the troubleshooting guide, open a support ticket in the official Discord server, or email the support team directly.
If you have a question or hit an issue with the SaucerSwap contracts or web app, work through these channels in order.
Most failed transactions are one of a handful of known errors — missing token associations, insufficient HBAR, or slippage. The [troubleshooting page](/resources/troubleshooting) is keyed by error name.
Open a support ticket in the [official Discord server](https://saucerswap.finance/discord). Tickets are the fastest support path and keep your details out of public channels.
Alternatively, contact [support@saucerswap.finance](mailto:support@saucerswap.finance). Include your account ID, the transaction ID if you have one, and what you expected to happen.
The SaucerSwap Labs team will never DM you first, and will never ask for your seed phrase, private key, or funds. Always confirm you are interacting with the official accounts listed on the [socials page](/contact/socials).
## Next steps
Fix common errors like failed swaps and missing token associations yourself.
Browse answers to the most common questions about the protocol and app.
Verify the official SaucerSwap channels before trusting any account.
# Careers
Source: https://docs.saucerswap.finance/contributors/careers
Open positions at SaucerSwap Labs and how to send a speculative application to the team building DeFi infrastructure on the Hedera network.
We currently have no open positions at SaucerSwap Labs. However, we are always on the lookout for talented individuals who are passionate about growing the Hedera DeFi ecosystem. Keep an eye on this section for new job postings as they become available.
If you believe you have skills that could benefit our team even though there are no positions currently open, we encourage you to be proactive and send in your CV to [hiring@saucerswap.finance](mailto:hiring@saucerswap.finance).
# Community
Source: https://docs.saucerswap.finance/contributors/community
Where to find the SaucerSwap developer community, including the public Discord server and how to get involved in protocol governance discussions.
If you are a developer working with SaucerSwap's contracts or interface, you can join the conversation in the #dev-chat channel of the [public Discord server](https://discord.com/invite/saucerswap).
For those interested in contributing to SaucerSwap's development and ecosystem, please refer to [Governance](/governance/overview).
# SaucerSwap Labs team
Source: https://docs.saucerswap.finance/contributors/saucerswap-labs
The SaucerSwap Labs company and team: who builds the SaucerSwap protocol and web app, each person's role, and one official channel per team member.
SaucerSwap Labs is the company that contributes to the SaucerSwap open-source protocol and develops and maintains the [web app](https://www.saucerswap.finance/). Company channel: [SaucerSwap Labs on LinkedIn](https://www.linkedin.com/company/saucerswaplabs).
Team members are listed with one official channel each. Nobody from the team will DM you first or ask for your seed phrase, private key, or funds; report impersonators through [user support](/contact/user-support).
## Business
| Name | Role | Channel |
| ----------------- | ----------------------------------- | ---------------------------------------------------------------- |
| Peter Campbell | Co-Founder, Operations & Marketing | [LinkedIn](https://www.linkedin.com/in/peter-sinclair-campbell/) |
| Joseph Bergvinson | Co-Founder, Operations & Tokenomics | [LinkedIn](https://www.linkedin.com/in/joseph-bergvinson/) |
| Markus Bergvinson | CSO, Operations & Tokenomics | [LinkedIn](https://www.linkedin.com/in/markus-bergvinson/) |
| Nube | Project Manager | [X @nubeasado](https://x.com/nubeasado) |
## Engineering
| Name | Role | Channel |
| ------------- | -------------------------------- | ----------------------------------------------------- |
| John O'Connor | VP of Infrastructure Engineering | [LinkedIn](https://www.linkedin.com/in/oconnorjohn/) |
| Jeremy Tong | Principal Frontend Engineer | [LinkedIn](https://www.linkedin.com/in/tongjeremy/) |
| Nathan Pinger | Senior Back-End Engineer | [LinkedIn](https://www.linkedin.com/in/nathanpinger/) |
## Community and media
| Name | Role | Channel |
| ---------------------------------- | ------------------------------------ | ------------------------------------------------------------- |
| Gabe | Designer | [X @ftzgabe](https://x.com/ftzgabe) |
| pine\_apple | Social Manager | [X @ss\_pine\_apple](https://x.com/ss_pine_apple) |
| Mango | Social Manager | [X @mangorimbo](https://x.com/mangorimbo) |
| Brandon Hargreaves (The HBAR Bull) | Ecosystem Correspondent & Media Host | [YouTube — HederaForum](https://www.youtube.com/@HederaForum) |
## Next steps
Reach the right channel for support, partnerships, or community questions.
Follow the verified official SaucerSwap channels.
See what the team has built, from the AMMs to the V3 order book.
# Build with AI
Source: https://docs.saucerswap.finance/developers/ai
Build on SaucerSwap with AI coding tools: llms.txt indexes, the docs MCP server, per-client setup, and a rules file with canonical endpoints and gotchas.
These docs are machine-readable. Point your coding agent at the indexes and MCP server below, and drop the rules file into your project so the agent starts with the endpoints and Hedera-specific gotchas it would otherwise get wrong.
## Machine-readable docs
| Surface | URL | Use |
| ----------------- | ----------------------------------------------- | ----------------------------------------------- |
| Page index | `https://docs.saucerswap.finance/llms.txt` | Compact index of every page for context loading |
| Full content | `https://docs.saucerswap.finance/llms-full.txt` | The entire docs site as one plain-text file |
| Per-page Markdown | Append `.md` to any page URL | Fetch a single page as clean Markdown |
## MCP server
The docs are also served over the Model Context Protocol at `https://docs.saucerswap.finance/mcp`, giving agents a search tool over this documentation.
```bash theme={null}
claude mcp add --transport http saucerswap-docs https://docs.saucerswap.finance/mcp
```
Add to `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):
```json theme={null}
{
"mcpServers": {
"saucerswap-docs": {
"url": "https://docs.saucerswap.finance/mcp"
}
}
}
```
Add to `.vscode/mcp.json` in your workspace:
```json theme={null}
{
"servers": {
"saucerswap-docs": {
"type": "http",
"url": "https://docs.saucerswap.finance/mcp"
}
}
}
```
## Rules file for coding agents
Copy this block into your agent rules file (`CLAUDE.md`, `.cursor/rules`, `AGENTS.md`, or equivalent). It encodes the canonical endpoints and the mistakes agents most often make on Hedera.
```markdown theme={null}
# SaucerSwap integration rules
## Canonical endpoints
- REST data API (mainnet): https://api.saucerswap.finance — requires `x-api-key` header
- REST data API (testnet): https://test-api.saucerswap.finance
- Orderbook API (mainnet): https://orderbook-api.saucerswap.finance
- Orderbook API (testnet): https://testnet-orderbook-api.saucerswap.finance
- Hedera mirror node (public, no key): https://mainnet.mirrornode.hedera.com
- Docs: https://docs.saucerswap.finance (llms.txt available)
## Canonical mainnet IDs
- SAUCE token: 0.0.731861 (6 decimals) · xSAUCE token: 0.0.1460200
- WHBAR token: 0.0.1456986 (8 decimals) · WhbarHelper: 0.0.5808826
- V1 router (SaucerSwapV1RouterV3): 0.0.3045981
- V2 SwapRouter: 0.0.3949434 · V2 QuoterV2: 0.0.3949424
- Mothership (SAUCE staking): 0.0.1460199 · Masterchef (farms): 0.0.1077627
- Full list: https://docs.saucerswap.finance/developers/contracts
## Hard rules
- ALWAYS quote before swapping: QuoterV2 (V2), getAmountsOut/In (V1), or
the Orderbook API quote endpoints (V3). Quotes via mirror-node
`/api/v1/contracts/call` are free and need no key.
- HBAR uses 8 decimals (1 HBAR = 100,000,000 tinybar). Every token amount
is denominated in its smallest unit; token decimals vary per token
(SAUCE = 6). Never assume 18 decimals.
- Keep uint256 values (amounts, nonces, deadlines) as strings in JS.
Never cast to Number before signing or submitting.
- Hedera accounts must ASSOCIATE a token before receiving it, or the
transaction fails with TOKEN_NOT_ASSOCIATED_TO_ACCOUNT.
- HTS token inputs require a spender allowance to the router contract.
- Use the WHBAR token address wherever a swap path includes HBAR.
- V3 order book fees are expressed in pips (1 pip = 1e-6), NOT basis points.
- Never log Orderbook WebSocket URLs: they carry the JWT in the query string.
- Develop on testnet first with a dedicated integration account. Never put
a primary wallet private key in a bot process.
```
Agents should treat prices, fees, and rate limits as live data: fetch them from the APIs or contracts at run time rather than hard-coding values from documentation.
## Next steps
The first three calls, ready to paste into an agent session.
Every endpoint across both APIs with auth models.
Verify every ID in the rules file above.
A server-side pattern for V3 order book bots.
# Contract deployments
Source: https://docs.saucerswap.finance/developers/contracts
Canonical SaucerSwap contract and token IDs on Hedera mainnet and testnet, with HashScan and Mirror Node verification, the V3 signing domain, and Axelar ITS SAUCE on Base.
These are the canonical SaucerSwap deployments. Every ID links to HashScan. Audit coverage for the V1, V2, and V3 contracts is listed on the [audits page](/developers/security/audits).
HashScan is the human-readable explorer. For machine verification, query the public Mirror Node directly: [`/contracts/{id}`](https://mainnet-public.mirrornode.hedera.com/api/v1/contracts/0.0.1077627), [`/accounts/{id}`](https://mainnet-public.mirrornode.hedera.com/api/v1/accounts/0.0.1456985), or [`/tokens/{id}`](https://mainnet-public.mirrornode.hedera.com/api/v1/tokens/0.0.731861). Replace the example ID with the deployment you need to verify.
Contracts marked deprecated remain on-chain but should not be used for new integrations. Always verify the ID you are calling against this page.
## Hedera mainnet
### V1 (AMM)
| Contract | Hedera ID | Purpose |
| --------------------------------- | --------------------------------------------------------------- | -------------------------------------------- |
| SaucerSwapV1Factory | [0.0.1062784](https://hashscan.io/mainnet/contract/0.0.1062784) | Creates V1 pools; `getPair`, `pairCreateFee` |
| SaucerSwapV1RouterV3 | [0.0.3045981](https://hashscan.io/mainnet/contract/0.0.3045981) | Current V1 router for swaps and liquidity |
| SaucerSwapRouterWithFee | [0.0.6755814](https://hashscan.io/mainnet/contract/0.0.6755814) | Fee-enabled router variant |
| SaucerSwapV1RouterV2 (deprecated) | [0.0.1461860](https://hashscan.io/mainnet/contract/0.0.1461860) | Superseded by RouterV3 |
| SaucerSwapV1RouterV1 (deprecated) | [0.0.1062787](https://hashscan.io/mainnet/contract/0.0.1062787) | Superseded by RouterV3 |
| SaucerSwapV1FeeTo | [0.0.1062785](https://hashscan.io/mainnet/account/0.0.1062785) | Protocol fee collection account |
### V2 (CLMM)
| Contract | Hedera ID | Purpose |
| ----------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------- |
| SaucerSwapV2Factory | [0.0.3946833](https://hashscan.io/mainnet/contract/0.0.3946833) | Creates V2 pools; `getPool`, `mintFee` |
| SaucerSwapV2SwapRouter | [0.0.3949434](https://hashscan.io/mainnet/contract/0.0.3949434) | V2 swaps (`exactInput`, `exactOutput`) |
| SaucerSwapV2QuoterV2 | [0.0.3949424](https://hashscan.io/mainnet/contract/0.0.3949424) | Gas-free swap quotes |
| SaucerSwapV2NonfungiblePositionManagerV2 | [0.0.4053945](https://hashscan.io/mainnet/contract/0.0.4053945) | Liquidity position NFTs |
| — LP NFT token | [0.0.4054027](https://hashscan.io/mainnet/token/0.0.4054027) | NFT collection for V2 positions |
| SaucerSwapV2NonfungiblePositionManagerV1 (deprecated) | [0.0.3949448](https://hashscan.io/mainnet/contract/0.0.3949448) | Superseded by V2 manager |
| — LP NFT token (deprecated) | [0.0.3949456](https://hashscan.io/mainnet/token/0.0.3949456) | NFT collection for the deprecated manager |
| SaucerSwapV2TickLens | [0.0.3948950](https://hashscan.io/mainnet/contract/0.0.3948950) | Tick data lens |
| SaucerSwapV2TickMath | [0.0.3946804](https://hashscan.io/mainnet/contract/0.0.3946804) | Math library |
| SaucerSwapV2BitMath | [0.0.3946806](https://hashscan.io/mainnet/contract/0.0.3946806) | Math library |
| SaucerSwapV2SwapMath | [0.0.3946812](https://hashscan.io/mainnet/contract/0.0.3946812) | Math library |
| SaucerSwapV2Oracle | [0.0.3946808](https://hashscan.io/mainnet/contract/0.0.3946808) | Oracle library |
| SaucerSwapV2HbarConversion | [0.0.3946810](https://hashscan.io/mainnet/contract/0.0.3946810) | HBAR conversion helper |
### V3 (order book)
V3 order matching runs off-chain with on-chain settlement through a reactor contract. The reactor address is not a static list entry: fetch it per environment from the signing-domain endpoint, which returns the EIP-712 domain used for order signatures. Unauthenticated access to this endpoint is [rolling out network by network](/api-reference/orderbook/market-data) with the July 2026 deployment — if it returns `401`, call it with a [JWT](/api-reference/orderbook/authentication) instead.
```bash theme={null}
curl "https://testnet-orderbook-api.saucerswap.finance/signature/domain"
```
The response's `verifyingContract` is the reactor contract for that environment, and `chainId` identifies the Hedera network. Example response from the testnet environment, captured July 9, 2026:
```json Output theme={null}
{
"name": "PartialFillLimitOrderReactor",
"version": "1",
"chainId": 296,
"verifyingContract": "0xA09dB478fF54e5CB6925E19847d5c2d11Ef97cF0"
}
```
Advanced clients can submit cancellations directly to the reactor on-chain; see [Orders and signing](/api-reference/orderbook/orders).
### Staking and farming
| Contract | Hedera ID | Purpose |
| ------------- | --------------------------------------------------------------- | --------------------------------------------------- |
| Mothership | [0.0.1460199](https://hashscan.io/mainnet/contract/0.0.1460199) | SAUCE single-sided staking (`enter`, `leave`) |
| Masterchef | [0.0.1077627](https://hashscan.io/mainnet/contract/0.0.1077627) | Yield farms (`deposit`, `withdraw`, `pendingSauce`) |
| StakeToSetter | [0.0.1456973](https://hashscan.io/mainnet/contract/0.0.1456973) | Staking configuration |
### Fee routing and governance
| Contract | Hedera ID | Purpose |
| ------------------------- | --------------------------------------------------------------- | -------------------------------- |
| BrewsaucerV2 | [0.0.9575119](https://hashscan.io/mainnet/contract/0.0.9575119) | Protocol fee conversion to SAUCE |
| BrewsaucerV1 (deprecated) | [0.0.1485296](https://hashscan.io/mainnet/contract/0.0.1485296) | Superseded by BrewsaucerV2 |
| sauceSplitter | [0.0.1462981](https://hashscan.io/mainnet/contract/0.0.1462981) | Fee distribution splitter |
| hbarSplitter | [0.0.1462986](https://hashscan.io/mainnet/contract/0.0.1462986) | Fee distribution splitter |
Governance submissions do not use one permanent “proposal creator” account. Historical Labs submissions used:
* `0.0.7281411` for the 2024 Topic 103 record.
* `0.0.4543385` for later submissions.
* `0.0.10035210` for Topics 330–385.
Always verify the submitter on the live [governance app](https://www.saucerswap.finance/governance) for the specific proposal; do not treat a historical account as a current role.
### Vesting (genesis allocation)
| Contract | Hedera ID |
| ---------------------- | --------------------------------------------------------------- |
| CoreDevelopmentVesting | [0.0.1059453](https://hashscan.io/mainnet/contract/0.0.1059453) |
| AdvisorVesting | [0.0.1059259](https://hashscan.io/mainnet/contract/0.0.1059259) |
| MarketingVesting | [0.0.1059333](https://hashscan.io/mainnet/contract/0.0.1059333) |
| OperationsVesting | [0.0.1059313](https://hashscan.io/mainnet/contract/0.0.1059313) |
The vesting schedule ended July 16, 2025. Checked July 29, 2026: MarketingVesting retained 199,961.736852 SAUCE; the other three balances were zero. A residual balance is not an active vesting schedule.
### WHBAR and wrappers
| Contract | Hedera ID | Purpose |
| -------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| WHBAR | [0.0.1456985](https://hashscan.io/mainnet/contract/0.0.1456985) | Wrapped HBAR contract |
| — WHBAR token | [0.0.1456986](https://hashscan.io/mainnet/token/0.0.1456986) | The WHBAR HTS token |
| WhbarHelper | [0.0.5808826](https://hashscan.io/mainnet/contract/0.0.5808826) | Safe wrap and unwrap helper — see [WHBAR overview](/developers/whbar/overview) |
| WHBAR (deprecated) | [0.0.1062663](https://hashscan.io/mainnet/contract/0.0.1062663) | Legacy wrapped HBAR |
| — WHBAR token (deprecated) | [0.0.1062664](https://hashscan.io/mainnet/token/0.0.1062664) | Legacy WHBAR HTS token |
| ERC20Wrapper | [0.0.9675688](https://hashscan.io/mainnet/contract/0.0.9675688) | HTS to ERC20 wrapping |
### Tokens
| Token | Hedera ID |
| ------------------- | ------------------------------------------------------------ |
| SAUCE | [0.0.731861](https://hashscan.io/mainnet/token/0.0.731861) |
| xSAUCE | [0.0.1460200](https://hashscan.io/mainnet/token/0.0.1460200) |
| Electromagnetic PEC | [0.0.732556](https://hashscan.io/mainnet/token/0.0.732556) |
| Strong Nuclear PEC | [0.0.732555](https://hashscan.io/mainnet/token/0.0.732555) |
| Weak Nuclear PEC | [0.0.732554](https://hashscan.io/mainnet/token/0.0.732554) |
| Gravity PEC | [0.0.732553](https://hashscan.io/mainnet/token/0.0.732553) |
## Hedera testnet
| Contract | Hedera ID | Purpose |
| -------------------------------------- | --------------------------------------------------------------- | ------------------------------- |
| WHBAR | [0.0.15057](https://hashscan.io/testnet/contract/0.0.15057) | Wrapped HBAR contract |
| — WHBAR token | [0.0.15058](https://hashscan.io/testnet/token/0.0.15058) | The WHBAR HTS token |
| WhbarHelper | [0.0.5286055](https://hashscan.io/testnet/contract/0.0.5286055) | Safe wrap and unwrap helper |
| WHBAR (deprecated) | [0.0.2230358](https://hashscan.io/testnet/contract/0.0.2230358) | Legacy wrapped HBAR |
| — WHBAR token (deprecated) | [0.0.2230359](https://hashscan.io/testnet/token/0.0.2230359) | Legacy WHBAR HTS token |
| SaucerSwapV1Factory | [0.0.9959](https://hashscan.io/testnet/contract/0.0.9959) | Creates V1 pools |
| SaucerSwapV1RouterV3 | [0.0.19264](https://hashscan.io/testnet/contract/0.0.19264) | Current V1 router |
| SaucerSwapV1RouterWithFee | [0.0.4652955](https://hashscan.io/testnet/contract/0.0.4652955) | Fee-enabled router variant |
| SaucerSwapV1RouterV2 (deprecated) | [0.0.2230930](https://hashscan.io/testnet/contract/0.0.2230930) | Superseded by RouterV3 |
| FeeTo | [0.0.10060](https://hashscan.io/testnet/account/0.0.10060) | Protocol fee collection account |
| Masterchef | [0.0.1179171](https://hashscan.io/testnet/contract/0.0.1179171) | Yield farms |
| Mothership | [0.0.1418650](https://hashscan.io/testnet/contract/0.0.1418650) | SAUCE single-sided staking |
| SAUCE token | [0.0.1183558](https://hashscan.io/testnet/token/0.0.1183558) | Testnet SAUCE |
| xSAUCE token | [0.0.1418651](https://hashscan.io/testnet/token/0.0.1418651) | Testnet xSAUCE |
| SaucerSwapV2Factory | [0.0.1197038](https://hashscan.io/testnet/contract/0.0.1197038) | Creates V2 pools |
| SaucerSwapV2NonfungiblePositionManager | [0.0.1308184](https://hashscan.io/testnet/contract/0.0.1308184) | Liquidity position NFTs |
| — LP NFT token | [0.0.1310436](https://hashscan.io/testnet/token/0.0.1310436) | NFT collection for V2 positions |
| SaucerSwapV2SwapRouter | [0.0.1414040](https://hashscan.io/testnet/contract/0.0.1414040) | V2 swaps |
| SaucerSwapV2QuoterV2 | [0.0.1390002](https://hashscan.io/testnet/contract/0.0.1390002) | Gas-free swap quotes |
For the V3 testnet reactor, fetch `https://testnet-orderbook-api.saucerswap.finance/signature/domain` as shown above.
## Cross-chain SAUCE — Axelar ITS
| Network | Asset | Address |
| ------- | ---------------- | ------------------------------------------------------------------------------------------------------------------- |
| Hedera | Native SAUCE | [0.0.731861](https://hashscan.io/mainnet/token/0.0.731861) |
| Base | Axelar ITS SAUCE | [0xA4FF56eF7Ef4a2CaD03cFa130208C9BC1b45d293](https://basescan.org/token/0xA4FF56eF7Ef4a2CaD03cFa130208C9BC1b45d293) |
Axelar ITS SAUCE is the active cross-chain representation listed here. Do not use deprecated Hashport projections or addresses as substitutes for the native Hedera token or the Axelar ITS deployment.
## Next steps
Call these contracts through the public mirror node.
Audit reports covering the deployed contracts.
Quote and swap against the V2 contracts.
Trade the V3 order book programmatically.
# TypeScript bot client
Source: https://docs.saucerswap.finance/developers/orderbook/typescript-client
Reference TypeScript client pattern for server-side SaucerSwap V3 Orderbook API bots: authenticate, build, sign, save, stream, and cancel orders.
This page documents a TypeScript client pattern for server-side bots and market makers. It is meant to make the API flow concrete: authenticate, fetch market data, build orders, sign orders, save orders, subscribe to streams, and cancel orders.
This pattern is for backend services and dedicated bot accounts. Do not ship private-key signing code in a browser app, and do not use a primary wallet key for automated trading.
## Dependencies
```bash theme={null}
npm install ethers@5 ws @hiero-ledger/sdk
npm install --save-dev @types/ws
```
The example client uses:
| Package | Purpose |
| ------------------- | ------------------------------------------------ |
| `ethers@5` | EIP-712 signing and EVM account utilities |
| `ws` | Node.js WebSocket support |
| `@hiero-ledger/sdk` | Hedera account key handling for ED25519 accounts |
The example pins `ethers@5` intentionally for CommonJS-friendly bot projects. If your service already runs as ESM, you can adapt the signing helpers to `ethers@6+`, but do not upgrade the sample dependency without also reviewing the module format and API changes.
## Recommended client surface
If you build a small wrapper around the API, use a surface like this:
| Method | Purpose |
| -------------------------------------- | -------------------------------------------------------------------------------- |
| `authenticate(accountId, privateKey)` | Run challenge and verify flow; store the JWT |
| `getOrderbooks(query)` | Discover orderbook token IDs, EVM addresses, decimals, status, and routing flags |
| `getDepth(orderbookId)` | Fetch a depth snapshot |
| `getDomain()` | Fetch and cache the EIP-712 signing domain |
| `buildOrders(requests)` | Request nonce-assigned serialized orders |
| `signOrder(order, privateKey, domain)` | Produce a prefixed signature for a built order |
| `saveOrders(items)` | Submit signed orders |
| `cancel(orderIds)` | Request cancellation for specific order IDs |
| `cancelAll(nonceFloor)` | Emergency cancel by nonce floor |
| `connectDepthWs(books, handlers)` | Subscribe to live depth updates |
| `connectUserEventsWs(books, handlers)` | Subscribe to authenticated order events |
The examples below assume a wrapper with this shape. You can also call the REST and WebSocket endpoints directly.
`OrderbookApiClient` is not a published package. It is a wrapper shape you implement in your own codebase against the documented endpoints. The full signing rules — EIP-712 payloads, mode-byte prefixes, and ED25519 handling — are specified in the [order placement reference](/api-reference/orderbook/orders).
## Minimal limit order flow
```typescript theme={null}
const client = new OrderbookApiClient({ environment: 'testnet' })
async function placeLimitOrder() {
await client.authenticate('0.0.123456', process.env.PRIVATE_KEY!)
const domain = await client.getDomain()
const requests = [
{
orderbookId: '3',
type: 'LIMIT' as const,
deadline: String(Math.floor(Date.now() / 1000) + 3600),
inputToken: '0xbase-token-evm-address',
inputAmount: '1000000',
outputToken: '0xquote-token-evm-address',
outputAmount: '950000',
isAMMEnabled: true,
},
]
const builtOrders = await client.buildOrders(requests)
const items = []
for (let i = 0; i < builtOrders.length; i++) {
const signature = await client.signOrder(
builtOrders[i],
process.env.PRIVATE_KEY!,
domain,
)
items.push({
order: builtOrders[i],
signature,
orderbookId: requests[i].orderbookId,
type: requests[i].type,
})
}
const { orders: saved } = await client.saveOrders(items)
for (const order of saved) {
console.log(
`order ${order.meta?.id}: status=${order.meta?.status} nonce=${order.info.nonce}`,
)
}
}
placeLimitOrder().catch(console.error)
```
## Signing behavior
The bot client signs the serialized order returned by `buildOrders()`.
For `ECDSA_SECP256K1` accounts:
1. Build the EIP-712 order payload.
2. Sign with `wallet._signTypedData(domain, types, order)`.
3. Prefix the signature with `0x00`.
For `ED25519` Hedera accounts:
1. Build the same EIP-712 order payload.
2. Hash it with `ethers.utils._TypedDataEncoder.hash`.
3. Sign the raw hash bytes with the Hiero SDK private key.
4. Prefix the signature bytes with `0x00`.
Wallet integrations that use Hedera personal sign should instead use the `0x01` signing mode and submit a HIP-632 `SignatureMap` around the raw wallet signature.
## Implementation notes
* Cache the value returned by `getDomain()` for the current session.
* Reuse the same authenticated account for build, sign, save, and cancellation.
* Sign the order returned by `buildOrders()`, not the original request body.
* Preserve all integer fields as strings.
* Use `baseTokenDecimals` and `quoteTokenDecimals` from `getOrderbooks()` when converting between display amounts and raw token units.
* Keep the signature mode byte in the submitted signature.
* Re-authenticate before reconnecting WebSocket streams.
## WebSocket example
```typescript theme={null}
await client.authenticate('0.0.123456', process.env.PRIVATE_KEY!)
const ws = client.connectDepthWs(['3'], {
onOpen: () => console.log('depth stream connected'),
onMessage: (message) => {
const event = JSON.parse(message)
console.log(event)
},
onClose: (code, reason) => {
console.log(`depth stream closed: ${code} ${reason}`)
},
onError: (error) => {
console.error(error)
},
})
```
Production clients should re-authenticate before reconnecting and should not log full WebSocket URLs because the JWT is passed in the query string.
## Cancellation example
```typescript theme={null}
await client.cancel([1234, 1235])
```
Cancellation is asynchronous. Wait for the user-event stream or fetch order history before treating an order as canceled.
```typescript theme={null}
await client.cancelAll('100000000000000000000')
```
Use nonce-floor cancellation only for emergency recovery or deliberate session shutdown flows.
## Next steps
Integration flow, environments, and the endpoint summary.
The build, sign, and save flow this client wraps.
Depth diffs and user events for live reconciliation.
Limits coordination and contacts for high-volume flow.
# Developer overview
Source: https://docs.saucerswap.finance/developers/overview
Start here to build on SaucerSwap: choose between the REST data API, the V3 Orderbook API, and on-chain contracts, with auth models and testnet setup.
SaucerSwap exposes three integration surfaces. Most integrations use more than one: read market data from an API, then quote and execute on-chain or through the order book.
## The three surfaces
| Surface | What it gives you | Authentication | Reference |
| ------------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------- |
| REST data API | Tokens, prices, candles, V1/V2 pools, farms, positions, and protocol stats | `x-api-key` header, issued by the team | [API reference](/api-reference/overview) |
| Orderbook API (V3) | Order books, depth, trade tape, market quotes, order placement and cancellation, WebSocket streams | Public reads; wallet challenge + JWT for account data and order flow | [Orderbook API](/api-reference/orderbook/overview) |
| On-chain contracts | Swaps, quotes, liquidity, staking, and farming against the deployed V1 and V2 contracts | None — you pay Hedera gas | [Contract deployments](/developers/contracts) |
## Which surface for which job
| You want to | Use |
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| Show prices, charts, TVL, or portfolio data | [REST data API](/api-reference/overview) |
| Get a swap quote without executing | [QuoterV2 or router quote functions](/developers/v2/swap/swap-quote) — free via JSON-RPC or the mirror node |
| Execute swaps from your own app or bot | [V2 swap operations](/developers/v2/swap/swap-quote) (V1 available as [legacy](/developers/v1/swap/swap-quote)) |
| Run a market maker or trading bot on the V3 order book | [Orderbook API](/api-reference/orderbook/overview) and the [TypeScript bot client](/developers/orderbook/typescript-client) |
| Manage liquidity positions programmatically | [V2 liquidity operations](/developers/v2/liquidity/new-liquidity-position) |
| Stake SAUCE or farm LP tokens from code | [Staking operations](/developers/staking/single-sided-staking) |
| Monitor swaps and pools in near real time | [Track swap events](/developers/v2/swap/track-swap-events), or the [order book WebSockets](/api-reference/orderbook/websockets) for V3 |
V2 is recommended for new AMM integrations; V1 remains live but is legacy. The V3 order book is a separate matching system with its own [API](/api-reference/orderbook/overview) and [concepts page](/protocol/saucerswap-v3).
## Test before mainnet
Every surface has a testnet counterpart:
| Surface | Testnet endpoint |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| REST data API | `https://test-api.saucerswap.finance` |
| Orderbook API | `https://testnet-orderbook-api.saucerswap.finance` |
| Contracts | [Testnet deployments](/developers/contracts#hedera-testnet) via `https://testnet.mirrornode.hedera.com` and the testnet JSON-RPC relay |
Create a Hedera testnet account and fund it with test HBAR through the [Hedera developer portal](https://portal.hedera.com/). Use a dedicated integration account for bots — never a primary wallet key.
## Next steps
Make your first API calls in under five minutes.
Canonical contract and token IDs with HashScan links.
Both APIs, authentication models, and every endpoint.
llms.txt, the docs MCP server, and an agent rules file.
# Developer quickstart
Source: https://docs.saucerswap.finance/developers/quickstart
Make your first SaucerSwap API calls in minutes: fetch token data and pools from the REST API and get a live on-chain swap quote from QuoterV2.
This quickstart walks the shortest useful path: read token data, list pools, then fetch a real swap quote. The first two calls use the REST data API; the quote runs against the on-chain QuoterV2 contract through Hedera's public mirror node, which needs no key at all.
Prerequisites:
* A SaucerSwap [API key](/api-reference/authentication) for the REST calls (the quote step works without one)
* `curl`, or Node.js 18+, or Python 3 with `requests`
The REST data API authenticates with an `x-api-key` header. Request a key by emailing [support@saucerswap.finance](mailto:support@saucerswap.finance) — see [Authentication](/api-reference/authentication) for what to include and what to expect. Substitute your key for `YOUR_API_KEY` below.
Fetch the SAUCE token (`0.0.731861`) with all of its market metadata:
```bash cURL theme={null}
curl -H "x-api-key: YOUR_API_KEY" \
"https://api.saucerswap.finance/tokens/0.0.731861"
```
```javascript JavaScript theme={null}
const res = await fetch('https://api.saucerswap.finance/tokens/0.0.731861', {
headers: { 'x-api-key': process.env.SAUCERSWAP_API_KEY },
});
const token = await res.json();
console.log(token.symbol, token.priceUsd);
```
```python Python theme={null}
import os, requests
res = requests.get(
"https://api.saucerswap.finance/tokens/0.0.731861",
headers={"x-api-key": os.environ["SAUCERSWAP_API_KEY"]},
)
token = res.json()
print(token["symbol"], token["priceUsd"])
```
Representative response (field values from the [OpenAPI specification](/api-reference/overview); live prices will differ):
```json Output theme={null}
{
"id": "0.0.731861",
"name": "SAUCE",
"symbol": "SAUCE",
"icon": "/images/tokens/sauce.svg",
"decimals": 6,
"price": "36806544",
"priceUsd": 0.01763457,
"dueDiligenceComplete": true,
"isFeeOnTransferToken": false,
"description": "SaucerSwap is an open source and non-custodial AMM protocol native to Hedera.",
"website": "https://www.saucerswap.finance/",
"twitterHandle": "SaucerSwapLabs"
}
```
`price` is denominated in tinybar (1 HBAR = 100,000,000 tinybar), and amounts are strings in the token's smallest unit. See [Conventions](/api-reference/conventions).
List every V2 concentrated liquidity pool, including fee tier and current tick:
```bash cURL theme={null}
curl -H "x-api-key: YOUR_API_KEY" \
"https://api.saucerswap.finance/v2/pools"
```
```javascript JavaScript theme={null}
const res = await fetch('https://api.saucerswap.finance/v2/pools', {
headers: { 'x-api-key': process.env.SAUCERSWAP_API_KEY },
});
const pools = await res.json();
for (const p of pools) {
console.log(`${p.tokenA.symbol}/${p.tokenB.symbol} @ ${p.fee / 10_000}%`);
}
```
```python Python theme={null}
import os, requests
res = requests.get(
"https://api.saucerswap.finance/v2/pools",
headers={"x-api-key": os.environ["SAUCERSWAP_API_KEY"]},
)
for p in res.json():
print(f"{p['tokenA']['symbol']}/{p['tokenB']['symbol']} @ {p['fee'] / 10_000}%")
```
Representative response (one array element, from the OpenAPI specification):
```json Output theme={null}
[
{
"id": 1,
"contractId": "0.0.3948521",
"tokenA": { "id": "0.0.456858", "symbol": "USDC", "decimals": 6 },
"tokenB": { "id": "0.0.1055459", "symbol": "USDC[hts]", "decimals": 6 },
"amountA": "6313040",
"amountB": "6313042",
"fee": 500,
"sqrtRatioX96": "79228162514992909706099547250",
"tickCurrent": 0,
"liquidity": "10878982596"
}
]
```
Quotes come from the on-chain `QuoterV2` contract ([`0.0.3949424`](https://hashscan.io/mainnet/contract/0.0.3949424)) and cost nothing: Hedera's public mirror node simulates the call. This example quotes 100 HBAR into SAUCE through the WHBAR/SAUCE 0.30% pool. No API key is required.
```bash cURL theme={null}
# calldata = quoteExactInput(path, amountIn)
# path = WHBAR (0.0.1456986) + fee 0x000bb8 (0.30%) + SAUCE (0.0.731861)
# amountIn = 10000000000 tinybar (100 HBAR)
curl -X POST "https://mainnet.mirrornode.hedera.com/api/v1/contracts/call" \
-H "content-type: application/json" \
-d '{
"block": "latest",
"to": "0x00000000000000000000000000000000003c4370",
"data": "0xcdca1753000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000000000000000002b0000000000000000000000000000000000163b5a000bb800000000000000000000000000000000000b2ad5000000000000000000000000000000000000000000"
}'
```
```javascript JavaScript theme={null}
import * as ethers from 'ethers'; // v6
const iface = new ethers.Interface([
'function quoteExactInput(bytes path, uint256 amountIn) returns (uint256 amountOut, uint160[] sqrtPriceX96AfterList, uint32[] initializedTicksCrossedList, uint256 gasEstimate)',
]);
const WHBAR = '0x0000000000000000000000000000000000163b5a'; // 0.0.1456986
const SAUCE = '0x00000000000000000000000000000000000b2ad5'; // 0.0.731861
const path = WHBAR + '000bb8' + SAUCE.slice(2); // 0.30% fee tier
const data = iface.encodeFunctionData('quoteExactInput', [path, 10_000_000_000n]);
const res = await fetch('https://mainnet.mirrornode.hedera.com/api/v1/contracts/call', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
block: 'latest',
to: '0x00000000000000000000000000000000003c4370', // QuoterV2 0.0.3949424
data,
}),
});
const { result } = await res.json();
const [amountOut] = iface.decodeFunctionResult('quoteExactInput', result);
console.log(`100 HBAR -> ${Number(amountOut) / 1e6} SAUCE`);
```
```python Python theme={null}
import requests
# calldata for quoteExactInput(WHBAR -> 0.30% -> SAUCE, 100 HBAR)
CALLDATA = (
"0xcdca1753"
"0000000000000000000000000000000000000000000000000000000000000040"
"00000000000000000000000000000000000000000000000000000002540be400"
"000000000000000000000000000000000000000000000000000000000000002b"
"0000000000000000000000000000000000163b5a000bb80000000000000000"
"0000000000000000000b2ad5000000000000000000000000000000000000000000"
)
res = requests.post(
"https://mainnet.mirrornode.hedera.com/api/v1/contracts/call",
json={
"block": "latest",
"to": "0x00000000000000000000000000000000003c4370", # QuoterV2
"data": CALLDATA,
},
)
amount_out = int(res.json()["result"][2:66], 16)
print(f"100 HBAR -> {amount_out / 1e6} SAUCE")
```
Live response captured on July 9, 2026 (the first 32-byte word is `amountOut`):
```json Output theme={null}
{
"result": "0x000000000000000000000000000000000000000000000000000000001e4372b0..."
}
```
Decoded, `amountOut` is `507736752` — with 6 decimals, 100 HBAR quoted to ≈507.74 SAUCE at capture time. Your numbers will track the live pool price.
## Where to go from here
The quote you just fetched is the first half of a swap: pass it as the minimum output when you [execute the swap through the SwapRouter](/developers/v2/swap/swap-hbar-for-tokens). For V3 order book quotes, the [Orderbook API](/api-reference/orderbook/market-data) exposes public `quote/exact-input` and `quote/exact-output` endpoints per market.
## Next steps
Turn the quote into an executed swap.
Every REST and Orderbook API endpoint.
Trade the V3 order book programmatically.
All contract and token IDs used above.
# Security audits
Source: https://docs.saucerswap.finance/developers/security/audits
Independent security audits of SaucerSwap V1, V2, V3, and the mobile wallet by Hacken, Omniscia, Halborn, and Quantstamp, with links to every report.
The SaucerSwap protocol has been audited by independent security firms across every major release. Each report below is hosted by the auditing firm.
## SaucerSwap V1
| Scope | Auditor | Date | Report |
| -------------- | -------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Core | Hacken | July 12, 2022 | [View report](https://hacken.io/wp-content/uploads/2022/07/SaucerSwap_25052022_SCAudit_Report2-1.pdf) |
| Masterchef | Hacken | July 12, 2022 | [View report](https://hacken.io/wp-content/uploads/2022/07/Farm-repo-SaucerSwap_25052022_01012021_SCAudit_Report2.pdf) |
| Updated router | Omniscia | June 7, 2023 | [View report](https://omniscia.io/reports/saucerswap-labs-router-implementation-64660c885d5517001401256c) |
## SaucerSwap V2
| Scope | Auditor | Date | Report |
| --------- | -------- | ------------------ | ----------------------------------------------------------------------------------------- |
| Core | Omniscia | September 27, 2023 | [View report](https://omniscia.io/reports/saucerswap-core-64c64695c767620014d91ed0/) |
| Periphery | Omniscia | September 27, 2023 | [View report](https://omniscia.io/reports/saucerswap-periphery-64c65c6cc767620014d91f14/) |
## SaucerSwap V3
| Scope | Auditor | Date | Report |
| ----------------------- | ------- | ------------ | ---------------------------------------------------------------------------------------- |
| V3 order book contracts | Halborn | May 18, 2026 | [View report](https://www.halborn.com/audits/saucerswap-labs/saucerswap-labs-sca-82e775) |
## SaucerSwap Wallet
| Scope | Auditor | Date | Report |
| ------------- | ---------- | --------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Mobile wallet | Quantstamp | August 20, 2025 | [View report](https://certificate.quantstamp.com/full/saucer-swap-wallet/d30efab8-8abd-46b1-bba5-6360b87e3aa3/index.html) |
## Other
| Scope | Auditor | Date | Report |
| ------- | ------- | ----------------- | ---------------------------------------------------------------------------------------- |
| Vesting | Hacken | July 12, 2022 | [View report](https://hacken.io/audits/saucerswap/sca-saucerswap-erc20-vesting-jul2022/) |
| Staking | Hacken | November 25, 2022 | [View report](https://hacken.io/audits/saucerswap/sca-saucerswap-erc20-staking-jul2022/) |
## Next steps
Report vulnerabilities responsibly and earn rewards.
Verify audited contract IDs on HashScan.
Operational risk disclosures for the V3 order book.
# Bug bounty
Source: https://docs.saucerswap.finance/developers/security/bug-bounty
SaucerSwap bug bounty program: scope, severity-based rewards, disclosure process, and eligibility rules for responsibly reporting vulnerabilities.
Security is a top priority for SaucerSwap. To encourage responsible disclosure of vulnerabilities, we offer a bug bounty program with financial rewards based on the severity of the identified issues.
## Scope
* SaucerSwap [testnet contracts](/developers/contracts#hedera-testnet) and [GitHub repositories](https://github.com/saucerswaplabs)
* SaucerSwap [testnet interface](https://testnet.saucerswap.finance/)
* SaucerSwap Mobile App (iOS and Android)
The following are not within the scope of the program:
* SaucerSwap mainnet contracts and production environment (testing restricted to testnet, which mirrors mainnet)
* Third-party contracts not directly associated with SaucerSwap
* Known issues from previous audit and bug bounty reports
* Third-party applications using SaucerSwap contracts
* Any findings that rely on Denial of Service (DoS) or Distributed Denial of Service (DDoS)
* Phishing, social engineering, or attacks requiring collusion from SaucerSwap staff or third-party support
* Physical access, stolen/unlocked devices, SIM-swap, device-level malware, or OS/kernel exploits unrelated to the app
* Repackaged or modified app builds, emulator-only issues, or jailbreak-only read-only file access (unless chained to unauthorized signing, in which case it is evaluated under High)
* Vulnerabilities in third-party libraries without demonstrable impact on SaucerSwap Mobile
## Rewards
The program includes the following four-level severity scale, based on the [OWASP risk rating methodology](https://owasp.org/www-community/OWASP_Risk_Rating_Methodology).
| Severity | Definition |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Critical | Issues that could impact numerous users and have serious reputational, legal, or financial implications, such as locking contracts permanently or taking funds from all users. |
| High | Issues that impact individual users where exploitation would pose reputational, legal, or moderate financial risk to the user. |
| Medium | The risk is relatively small and does not pose a threat to user funds. |
| Informational | The issue does not pose an immediate risk but is relevant to security best practices. |
SaucerSwap Labs will determine rewards based on the bug's severity and its potential for exploitation. Rewards may be disbursed in U.S. dollars, cryptocurrency, or a mix of both.
## Disclosure
Report vulnerabilities to [dev@saucerswap.finance](mailto:dev@saucerswap.finance). An acknowledgment will be sent within two to three business days. Do not disclose the bug publicly until it is resolved and permitted by SaucerSwap Labs.
A detailed report of a vulnerability increases the likelihood of a reward and may increase the reward amount. Please provide as much information about the vulnerability as possible, including:
* Conditions required for reproducing the bug
* Step-by-step guide or proof of concept for reproduction
* Potential consequences if exploited
* Suggested remediation (optional)
Anyone who reports a unique, previously-unreported vulnerability that results in a change to the code or a configuration change and who keeps such vulnerability confidential until it has been resolved by our engineers will be financially rewarded.
## Eligibility
To be eligible for a reward under this program, you must meet the following conditions:
1. **Uniqueness:** Discover a previously unreported, non-public vulnerability that is not already known to our team and is within the scope of the program.
2. **First disclosure:** Be the first to disclose the unique vulnerability to [dev@saucerswap.finance](mailto:dev@saucerswap.finance), and adhere to the program's disclosure requirements.
3. **Detailed reporting:** Provide comprehensive information that enables our engineers to reproduce and remedy the vulnerability.
4. **Non-exploitation:** Do not exploit the vulnerability in any form, including publicizing it or seeking other forms of profit, except under this program.
5. **Non-publicization:** Do not disclose the vulnerability to the public or any third party without our explicit approval.
6. **Ethical conduct:** Make a good faith effort to prevent privacy violations, data destruction, service interruption, or any degradation of in-scope assets.
7. **Lawful behavior:** Do not engage in any unlawful conduct during the disclosure process, such as making threats or demands.
8. **Age requirement:** Must be at least 18 years of age. If younger, you may participate with the consent of a parent or guardian.
9. **Legal compliance:** Cannot be subject to U.S. sanctions or reside in a U.S.-embargoed country.
10. **Non-affiliation:** Cannot be a current or former employee, vendor, or contractor who contributed to the development of the affected code.
11. **Complete compliance:** Must comply with all other eligibility requirements specified in this program.
By meeting these criteria, you become eligible for a reward under the SaucerSwap bug bounty program.
## Other terms
By submitting a report, you grant SaucerSwap Labs the rights necessary to validate and resolve the vulnerability. All reward decisions are at our sole discretion. The program's terms may be changed at any time.
## History
A dedicated V3 testnet bug bounty ran from May 25 to June 1, 2026, ahead of the V3 order book mainnet launch; that program is now closed.
## Next steps
Independent audit reports for every protocol release.
Testnet contract IDs that fall within the program scope.
# Single-sided staking operations
Source: https://docs.saucerswap.finance/developers/staking/single-sided-staking
Contract operations for SAUCE single-sided staking: convert between SAUCE and xSAUCE amounts and stake or unstake through the Mothership contract.
Outlined below are the common operations associated with single-sided staking:
* [Get xSAUCE amount from SAUCE](#get-xsauce-amount-from-sauce)
* [Stake SAUCE tokens for xSAUCE](#stake-sauce-tokens-for-xsauce)
* [Get SAUCE amount from xSAUCE](#get-sauce-amount-from-xsauce)
* [Unstake xSAUCE tokens for SAUCE](#unstake-xsauce-tokens-for-sauce)
Contract ID: [Mothership](https://hashscan.io/mainnet/contract/0.0.1460199)
Refer to [Single-sided staking](/protocol/single-sided-staking) for concept-level documentation.
***
## Get xSAUCE amount from SAUCE
Get the calculated xSAUCE amount from a given SAUCE amount.
Function name: `sauceForxSauce`
*No gas cost — read-only call.*
| Parameter Name | Description |
| ----------------------- | --------------------------------- |
| *uint256 \_sauceAmount* | SAUCE amount in its smallest unit |
```solidity MotherShip.sol theme={null}
function sauceForxSauce(uint256 _sauceAmount) external view returns (uint256 xSauceAmount_) {
uint256 totalSauce = IERC20(sauce).balanceOf(address(this));
uint256 totalxSauce = IERC20(xSauce).totalSupply();
if (totalxSauce == 0 || totalSauce == 0) {
xSauceAmount_ = _sauceAmount;
}
else {
xSauceAmount_ = _sauceAmount * (totalxSauce) / (totalSauce);
}
}
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
const interfaces = new ethers.Interface([
'function sauceForxSauce(uint256 _sauceAmount) external view returns (uint256 xSauceAmount_)'
]);
const mothershipContract = new ethers.Contract(mothershipEvmAddress, interfaces.fragments, provider);
const result = await mothershipContract.sauceForxSauce(sauceAmountTiny);
const xSauceAmount = result[0]; //uint256 xSauceAmount_ - in token's smallest unit
```
***
## Stake SAUCE tokens for xSAUCE
Stake any amount of SAUCE tokens in exchange for xSAUCE tokens.
Function name: `enter`
Recommended gas limit: 100,000
| Parameter Name | Description |
| ------------------ | ------------------------------------------------- |
| *uint256 \_amount* | The amount of SAUCE to stake in its smallest unit |
```solidity Mothership.sol theme={null}
function enter(uint256 _amount) external {
uint256 totalSauce = IERC20(sauce).balanceOf(address(this));
uint256 totalShares = IERC20(xSauce).totalSupply();
safeTransferToken(sauce, msg.sender, address(this), _amount);
if (totalShares == 0 || totalSauce == 0) {
safeMintToken(xSauce, _amount, new bytes[](0));
safeTransferToken(xSauce, address(this), msg.sender, _amount);
}
// Calculate and mint the amount of xSAUCE the SAUCE is worth. The ratio will change overtime, as xSAUCE is burned/minted and SAUCE deposited + gained from fees / withdrawn.
else {
uint256 what = _amount * (totalShares) / (totalSauce);
safeMintToken(xSauce, what, new bytes[](0));
safeTransferToken(xSauce, address(this), msg.sender, what);
}
}
```
A spender allowance for the Mothership contract is required for the SAUCE token.
Ensure that the client has the [xSAUCE token ID](https://hashscan.io/mainnet/token/0.0.1460200) associated beforehand.
To calculate the amount of xSAUCE tokens a user will receive from a given SAUCE amount, use the [`sauceForxSauce()`](#get-xsauce-amount-from-sauce) Solidity function in MotherShip.sol. Alternatively calculate the amount using the current SAUCE/xSAUCE ratio value.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - xSAUCE token is associated
// - Mothership contract has spender allowance for the SAUCE token
const params = new ContractFunctionParameters();
params.addUint256(sauceAmountTiny); //uint _amount
await new ContractExecuteTransaction()
.setContractId(mothershipContractId)
.setGas(gasLim)
.setFunction('enter', params)
.execute(client);
```
***
## Get SAUCE amount from xSAUCE
Get the calculated SAUCE amount from a given xSAUCE amount.
Function name: `xSauceForSauce`
*No gas cost — read-only call.*
| Parameter Name | Description |
| ------------------------ | ---------------------------------- |
| *uint256 \_xSauceAmount* | xSAUCE amount in its smallest unit |
```solidity MotherShip.sol theme={null}
function xSauceForSauce(uint256 _xSauceAmount) external view returns (uint256 sauceAmount_) {
uint256 totalxSauce = IERC20(xSauce).totalSupply();
sauceAmount_ = _xSauceAmount * (IERC20(sauce).balanceOf(address(this))) / (totalxSauce);
}
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
const interfaces = new ethers.Interface([
'function xSauceForSauce(uint256 _xSauceAmount) external view returns (uint256 sauceAmount_)'
]);
const mothershipContract = new ethers.Contract(mothershipEvmAddress, interfaces.fragments, provider);
const result = await mothershipContract.xSauceForSauce(xSauceAmountTiny);
const sauceAmount = result[0]; //uint256 sauceAmount_ - in token's smallest unit
```
***
## Unstake xSAUCE tokens for SAUCE
Unstake any amount of xSAUCE tokens in exchange for SAUCE tokens.
Function name: `leave`
Recommended gas limit: 100,000
| Parameter Name | Description |
| ----------------- | ---------------------------------------------------- |
| *uint256 \_share* | The amount of xSAUCE to unstake in its smallest unit |
```solidity Mothership.sol theme={null}
function leave(uint256 _share) external {
uint256 totalShares = IERC20(xSauce).totalSupply();
uint256 what = _share * (IERC20(sauce).balanceOf(address(this))) / (totalShares);
safeTransferToken(xSauce, msg.sender, address(this), _share);
safeBurnToken(xSauce, address(this), _share, new int64[](0));
safeTransferToken(sauce, address(this), msg.sender, what);
}
```
To calculate the amount of SAUCE tokens a user will receive from a given xSAUCE amount, use the [`xSauceForSauce()`](#get-sauce-amount-from-xsauce) Solidity function in MotherShip.sol. Alternatively calculate the output amount using the current SAUCE/xSAUCE ratio value.
Ensure that the client has the [SAUCE token ID](https://hashscan.io/mainnet/token/0.0.731861) associated beforehand.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - SAUCE token is associated
// - Mothership contract has spender allowance for the xSAUCE token
const params = new ContractFunctionParameters();
params.addUint256(xSauceAmountTiny); //uint256 _share
await new ContractExecuteTransaction()
.setContractId(mothershipContractId)
.setGas(gasLim)
.setFunction('leave', params)
.execute(client);
```
## Next steps
How xSAUCE and the staking pool work.
Deposit LP tokens and read pending rewards.
Mothership and token IDs for mainnet and testnet.
# Yield farming operations
Source: https://docs.saucerswap.finance/developers/staking/yield-farming
Contract operations for SaucerSwap yield farms: deposit and withdraw LP tokens and read pending SAUCE and HBAR rewards from the Masterchef contract.
Outlined below are the common operations associated with yield farming:
* [Deposit LP tokens to a farm](#deposit-lp-tokens-to-a-farm)
* [Get pending farm rewards](#get-pending-farm-rewards)
* [Withdraw LP tokens from a farm](#withdraw-lp-tokens-from-a-farm)
Contract ID: [Masterchef](https://hashscan.io/mainnet/contract/0.0.1077627)
Query [https://api.saucerswap.finance/farms/](https://api.saucerswap.finance/farms/) for all eligible farm pool IDs.
Query [https://api.saucerswap.finance/pools/](https://api.saucerswap.finance/pools/) for all available pool IDs
## Deposit LP tokens to a farm
Deposit any amount of LP tokens to an existing farm to earn additional yield.
Function name: `deposit`
Recommended gas limit: 210,000
| Parameter Name | Description |
| ------------------ | ------------------------------------ |
| *uint256 \_pid* | Liquidity pool id |
| *uint256 \_amount* | LP token amount in its smallest unit |
```solidity MasterChef.sol theme={null}
function deposit(uint256 _pid, uint256 _amount) external payable nonReentrant {
require(msg.value >= tinycentsToTinybars(depositFee), 'msg.value < depositFee');
// send rent to rentPayer
(bool result, ) = rentPayer.call{value: msg.value}("");
if (!result) {
emit DidNotReceiveHbar(rentPayer, msg.value);
}
UserInfo storage user = userInfo[_pid][msg.sender];
PoolInfo storage pool = poolInfo[_pid];
updatePool(_pid);
uint256 pending = (user.amount * pool.accSaucePerShare / 1e12) - user.rewardDebt;
uint256 pendingHbar = (user.amount * pool.accHBARPerShare / 1e12) - user.rewardDebtHbar;
user.amount = user.amount + _amount;
user.rewardDebt = user.amount * pool.accSaucePerShare / 1e12;
user.rewardDebtHbar = user.amount * pool.accHBARPerShare / 1e12;
if(pending > 0) {
safeSauceTransfer(msg.sender, pending);
}
if (_amount > 0) {
safeTransferToken(pool.lpToken, msg.sender, address(this), _amount.toInt256().toInt64());
}
emit Deposit(msg.sender, _pid, _amount);
if (pendingHbar > 0) {
safeHBARTransfer(msg.sender, pendingHbar);
}
}
```
A spender allowance for the Farm contract is required for the LP token.
Depositing tokens into a farm costs \$0.25 (as of July 2026), payable in HBAR. To get the current deposit fee, call the `depositFee()` method on the Farm contract. It returns the current value expressed in tinycent. To accurately convert this value to Tinybar, query the exchange rate from /api/v1/network/exchangerate
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Farm contract has spender allowance for the LP token
const params = new ContractFunctionParameters();
params.addUint256(poolId); //uint _pid
params.addUint256(lpTokenAmount); //uint _amount
await new ContractExecuteTransaction()
.setPayableAmount(depositFeeInHbar)
.setContractId(farmContractId)
.setGas(gasLim)
.setFunction('deposit', params)
.execute(client);
```
## Get pending farm rewards
Get current HBAR and SAUCE yield reward values for a user.
Function name: `pendingSauce`
*No gas cost — read-only call.*
| Parameter Name | Description |
| ---------------- | ----------------------- |
| *uint256 \_pid* | Liquidity pool id |
| *address \_user* | User's solidity address |
```solidity MasterChef.sol theme={null}
function pendingSauce(uint256 _pid, address _user) external view returns (uint256, uint256) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 accSaucePerShare = pool.accSaucePerShare;
uint256 accHBARPerShare = pool.accHBARPerShare;
uint256 lpSupply = IERC20(pool.lpToken).balanceOf(address(this));
if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {
uint256 multiplier = getMultiplier(pool.lastRewardTime, block.timestamp);
uint256 sauceReward = multiplier * (saucePerSecond) * (pool.allocPoint) / (totalAllocPoint);
uint256 hbarReward = multiplier * (hbarPerSecond) * (pool.allocPoint) / (totalAllocPoint);
accSaucePerShare = accSaucePerShare + (sauceReward * (1e12) / (lpSupply));
accHBARPerShare = accHBARPerShare + (hbarReward * (1e12) / (lpSupply));
}
return (user.amount * (accSaucePerShare) / (1e12) - (user.rewardDebt), user.amount * (accHBARPerShare) / (1e12) - (user.rewardDebtHbar));
}
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
const interfaces = new ethers.Interface([
'function pendingSauce(uint256 _pid, address _user) external view returns (uint256, uint256)'
]);
const farmContract = new ethers.Contract(farmEvmAddress, interfaces.fragments, provider);
const result = await farmContract.pendingSauce(poolId, userEvmAddress);
const pendingSauceTiny = result[0]; //uint256
const pendingTinybar = result[1]; //uint256
```
## Withdraw LP tokens from a farm
Withdraw any amount of LP tokens from an existing farm.
Function name: `withdraw`
Recommended gas limit: 190,000
| Parameter Name | Description |
| ------------------ | ------------------------------------ |
| *uint256 \_pid* | Liquidity pool id |
| *uint256 \_amount* | LP token amount in its smallest unit |
```solidity MasterChef.sol theme={null}
function withdraw(uint256 _pid, uint256 _amount) external nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.amount >= _amount, "withdraw: not good");
updatePool(_pid);
uint256 pending = (user.amount * pool.accSaucePerShare / 1e12) - user.rewardDebt;
uint256 pendingHbar = (user.amount * pool.accHBARPerShare / 1e12) - user.rewardDebtHbar;
user.amount = user.amount - _amount;
user.rewardDebt = user.amount * pool.accSaucePerShare / 1e12;
user.rewardDebtHbar = user.amount * pool.accHBARPerShare / 1e12;
if(pending > 0) {
safeSauceTransfer(msg.sender, pending);
}
if(_amount > 0) {
safeTransferToken(address(pool.lpToken), address(this), msg.sender, _amount.toInt256().toInt64());
}
emit Withdraw(msg.sender, _pid, _amount);
if (pendingHbar > 0) {
safeHBARTransfer(msg.sender, pendingHbar);
}
}
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction
} from '@hashgraph/sdk';
const params = new ContractFunctionParameters();
params.addUint256(poolId); //uint _pid
params.addUint256(lpTokenAmount); //uint _amount
await new ContractExecuteTransaction()
.setContractId(farmContractId)
.setGas(gasLim)
.setFunction('withdraw', params)
.execute(client);
```
## Next steps
Stake SAUCE for xSAUCE through contracts.
Get the LP tokens a farm deposit requires.
Masterchef and token IDs for mainnet and testnet.
# Adding liquidity (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/adding-liquidity
Add liquidity to existing SaucerSwap V1 pools with the addLiquidityETH and addLiquidity functions, including allowance and LP token association setup.
Add liquidity to an existing HBAR/token liquidity pool.
Outlined below are two methods to add liquidity to an existing pool on SaucerSwap:
* [Adding HBAR-token liquidity](#adding-hbar-token-liquidity)
* [Adding token-token liquidity](#adding-token-token-liquidity)
Contract ID: [SaucerSwapV1RouterV3](https://hashscan.io/mainnet/contract/0.0.3045981)
To create a new liquidity pool, see [Creating a new liquidity pool](/developers/v1/liquidity/create-a-new-pool).
Ensure that the client has the LP token associated before adding liquidity.
A spender allowance for the Router contract is required for HTS tokens.
Both `addLiquidityETH` and `addLiquidity` support HTS tokens containing custom fees.
***
## Adding HBAR-token liquidity
Add more liquidity to an existing HBAR/token liquidity pool.
Function name: `addLiquidityETH`
Recommended gas limit: 240,000
| Parameter Name | Description |
| ------------------------- | --------------------------------------------- |
| *address token* | EVM address of the token to pool with HBAR |
| *uint amountTokenDesired* | The maximum token amount in its smallest unit |
| *uint amountTokenMin* | The minimum token amount in its smallest unit |
| *uint amountETHMin* | The minimum HBAR amount in its smallest unit |
| *address to* | EVM address to receive the liquidity tokens |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
```
```solidity UniswapV2Router02.sol theme={null}
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external virtual override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
(amountToken, amountETH) = _addLiquidity(
token,
whbar,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = IUniswapV2Factory(factory).getPair(token, whbar);
require(pair != address(0), "UniswapV2Router: PAIR DOES NOT EXIST");
safeTransferToken(
token, msg.sender, pair, amountToken
);
IWHBAR(WHBAR).deposit{value: amountETH}(msg.sender, pair);
liquidity = IUniswapV2Pair(pair).mint(to);
// refund dust eth, if any
if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
}
```
The `addLiquidityETH` function operates in HBAR but derives its name from Uniswap on Ethereum. This name was kept to simplify integration for developers versed in Uniswap tools.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output NFT token is associated
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addAddress(tokenAddress); //address token
params.addUint256(amountTokenDesired); //uint amountTokenDesired
params.addUint256(amountTokenMin); //uint amountTokenMin
params.addUint256(amountHBARMin); //uint amountETHMin
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setPayableAmount(inputHbar)
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('addLiquidityETH', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint','uint']);
const amountToken = values[0]; //uint amountToken
const amountHBAR = values[1]; //uint amountETH
const liquidity = values[2]; //uint liquidity
```
## Adding token-token liquidity
Add more liquidity to an existing token/token liquidity pool.
Function name: `addLiquidity`
Recommended gas limit: 240,000
| Parameter Name | Description |
| --------------------- | ------------------------------------------------------------ |
| *address tokenA* | EVM address of the first HTS token |
| *address tokenB* | EVM address of the second HTS token |
| *uint amountADesired* | The maximum amount for the first token in its smallest unit |
| *uint amountBDesired* | The maximum amount for the second token in its smallest unit |
| *uint amountAMin* | The minimum amount for the first token in its smallest unit |
| *uint amountBMin* | The minimum amount for the second token in its smallest unit |
| *address to* | EVM address to receive the liquidity tokens |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output NFT token is associated
// - Router contract has spender allowance for the input tokens
const params = new ContractFunctionParameters();
params.addAddress(tokenAAddress); //address tokenA
params.addAddress(tokenBAddress); //address tokenB
params.addUint256(amountADesired); //uint amountADesired
params.addUint256(amountBDesired); //uint amountBDesired
params.addUint256(amountAMin); //uint amountAMin
params.addUint256(amountBMin); //uint amountBMin
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('addLiquidity', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint','uint']);
const amountA = values[0]; //uint amountA
const amountB = values[1]; //uint amountB
const liquidity = values[2]; //uint liquidity
```
## Next steps
Withdraw your share of a V1 pool.
Create the pool first if it does not exist.
Read current reserves before sizing amounts.
# Check if a pool exists (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/check-if-a-pool-exists
Check whether a SaucerSwap V1 liquidity pool exists on-chain with the factory getPair function before creating a pool or adding liquidity on Hedera.
When adding a new or existing liquidity pool, the initial step is typically to verify if the liquidity pool already exists before determining the next course of action. The factory contract provides a method to retrieve the pool address, if it exists, as shown below.
Checking if the liquidity pool exists using SaucerSwap's REST API is also a suitable alternative. For more information, see [Get V1 liquidity pools](/developers/v1/liquidity/fetch-all-pools)
## Get the existing liquidity pool if it exists
*No gas cost — read-only call.*
Get the existing liquidity pool's CREATE2 EVM address if it exists. If the pool does not exist on-chain, a zero address will be returned.
Function name: `getPair`
| Parameter Name | Description |
| ---------------- | ------------------------------- |
| *address tokenA* | EVM address of the first token |
| *address tokenB* | EVM address of the second token |
```solidity IUniswapV2Factory.sol theme={null}
function getPair(
address tokenA,
address tokenB
) external view returns (address pair);
```
The ordering of tokens for tokenA and tokenB does not matter.
When working with HBAR, use the wrapped HBAR token ID ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)) for either tokenA or tokenB.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing the Factory's getPair function
const interfaces = new ethers.Interface(abi);
const factoryContract = new ethers.Contract(factoryEvmAddress, interfaces.fragments, provider);
const result = await factoryContract.getPair(tokenA, tokenB); //(tokenB, tokenA) will give same result
const poolEvmAddress = result; //address pool
```
## Next steps
Create the pool if it does not exist yet.
List every V1 pool from the REST API.
# Create a new pool (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/create-a-new-pool
Create new SaucerSwap V1 liquidity pools with addLiquidityETHNewPool and addLiquidityNewPool, including the pool creation fee and auto-association setup.
Create a new HBAR/token or token/token liquidity pool.
There are two methods to add a new liquidity pool:
* [Creating a new HBAR-token liquidity pool](#creating-a-new-hbar-token-liquidity-pool)
* [Creating a new token-token liquidity pool](#creating-a-new-token-token-liquidity-pool)
Contract ID: [SaucerSwapV1RouterV3](https://hashscan.io/mainnet/contract/0.0.3045981)
See [Pool creation fee](/developers/v1/liquidity/pool-creation-fee) to get the current pool creation fee.
Ensure that the liquidity pool does not exist on-chain prior to creation of the new pool. See [Check for an existing pool](/developers/v1/liquidity/check-if-a-pool-exists).
Increase the client's max token auto-association by one to receive the incoming LP token.
To add liquidity to an existing pool, see [Adding liquidity](/developers/v1/liquidity/adding-liquidity).
Both methods support HTS tokens with custom fees.
***
## Creating a new HBAR-token liquidity pool
Create a new HBAR/token liquidity pool and provide it with initial liquidity.
Function name: `addLiquidityETHNewPool`
Recommended gas limit: 3,200,000
| Parameter Name | Description |
| ------------------------- | ------------------------------------------------------ |
| *address token* | EVM address of the token to pair with HBAR |
| *uint amountTokenDesired* | The maximum token amount in its smallest unit |
| *uint amountTokenMin* | The minimum token amount in its smallest unit |
| *uint amountETHMin* | The minimum HBAR amount in its smallest unit (tinybar) |
| *address to* | EVM address to receive the new liquidity tokens |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function addLiquidityETHNewPool(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
```
```solidity UniswapV2Router02.sol theme={null}
function addLiquidityETHNewPool(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external virtual payable override ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
require (IUniswapV2Factory(factory).getPair(token, whbar) == address(0), "UniswapV2Router: POOL ALREADY EXISTS");
uint256 feeInTinybars = tinycentsToTinybars(IUniswapV2Factory(factory).pairCreateFee());
require(msg.value > feeInTinybars, 'UniswapV2Router: MSG.VALUE');
IUniswapV2Factory(factory).createPair{value: feeInTinybars}(token, whbar);
(amountToken, amountETH) = _addLiquidity(token, whbar, amountTokenDesired, msg.value - feeInTinybars, amountTokenMin, amountETHMin);
address pair = UniswapV2Library.pairFor(factory, token, whbar);
safeTransferToken(
token, msg.sender, pair, amountToken
);
IWHBAR(WHBAR).deposit{value: amountETH}(msg.sender, pair);
liquidity = IUniswapV2Pair(pair).mint(to);
if (msg.value - feeInTinybars > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - feeInTinybars - amountETH);
}
```
A spender allowance for the router is required for the HTS token.
The `addLiquidityETHNewPool` function operates in HBAR but derives its name from Uniswap on Ethereum. This name was kept to simplify integration for developers versed in Uniswap tools.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Token auto-association](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/update-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
AccountUpdateTransaction, //for token auto-association
} from '@hashgraph/sdk';
//Client pre-checks:
// - Max auto-association increased by one
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addAddress(tokenAddress); //address token
params.addUint256(amountTokenDesired); //uint amountTokenDesired
params.addUint256(amountTokenMin); //uint amountTokenMin
params.addUint256(amountHBARMin); //uint amountETHMin
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setPayableAmount(inputHbarAndPoolCreationFeeHbar) //input hbar + pool creation fee
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('addLiquidityETHNewPool', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint','uint']);
const amountToken = values[0]; //uint amountToken
const amountHBAR = values[1]; //uint amountETH
const liquidity = values[2]; //uint liquidity
```
***
## Creating a new token-token liquidity pool
Create a new token/token liquidity pool and provide it with initial liquidity.
Function name: `addLiquidityNewPool`
Recommended gas limit: 3,200,000
| Parameter Name | Description |
| --------------------- | ------------------------------------------------------------ |
| *address tokenA* | EVM address of the first HTS token |
| *address tokenB* | EVM address of the second HTS token |
| *uint amountADesired* | The maximum amount for the first token in its smallest unit |
| *uint amountBDesired* | The maximum amount for the second token in its smallest unit |
| *uint amountAMin* | The minimum amount for the first token in its smallest unit |
| *uint amountBMin* | The minimum amount for the second token in its smallest unit |
| *address to* | EVM address to receive the new liquidity tokens |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function addLiquidityNewPool(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external payable returns (uint amountA, uint amountB, uint liquidity);
```
```solidity UniswapV2Router02.sol theme={null}
function addLiquidityNewPool(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external virtual payable override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
require (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0), "UniswapV2Router: POOL ALREADY EXISTS");
address pair = IUniswapV2Factory(factory).createPair{value: msg.value}(tokenA, tokenB);
(amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
safeTransferToken(
tokenA, msg.sender, pair, amountA
);
safeTransferToken(
tokenB, msg.sender, pair, amountB
);
liquidity = IUniswapV2Pair(pair).mint(to);
}
```
A spender allowance for the router is required for both HTS tokens.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Token auto-association](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/update-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
AccountUpdateTransaction, //for token auto-association
} from '@hashgraph/sdk';
//Client pre-checks:
// - Max auto-association increased by one
// - Router contract has spender allowance for the input tokens
const params = new ContractFunctionParameters();
params.addAddress(tokenAEvmAddress); //address tokenA
params.addAddress(tokenBEvmAddress); //address tokenB
params.addUint256(amountADesired); //uint amountADesired
params.addUint256(amountBDesired); //uint amountBDesired
params.addUint256(amountAMin); //uint amountAMin
params.addUint256(amountBMin); //uint amountBMin
params.addAddress(toEvmAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setPayableAmount(poolCreationFeeHbar)
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('addLiquidityNewPool', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint','uint']);
const amountA = values[0]; //uint amountA - in its smallest unit
const amountB = values[1]; //uint amountB - in its smallest unit
const liquidity = values[2]; //uint liquidity
```
## Next steps
Fetch the current fee before creating a pool.
Verify the pool is not already on-chain.
Add to the pool once it exists.
# Fetch all pools (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/fetch-all-pools
Retrieve every SaucerSwap V1 liquidity pool with reserves and token metadata from the SaucerSwap REST API, including the response schema and an example.
SaucerSwap offers a public REST API endpoint to retrieve all liquidity pools, accompanied by useful metadata for each pool, including liquidity pool reserves, and their associated tokens. Use the following URL options to access the data.
The endpoint is `GET /pools` on `https://api.saucerswap.finance` (mainnet) or `https://test-api.saucerswap.finance` (testnet). Requests require an API key; see [Authentication](/api-reference/authentication).
For SaucerSwap V2 liquidity pools, refer to [Get V2 liquidity pools](/developers/v2/liquidity/fetch-all-pools).
## Data JSON schema
```typescript theme={null}
interface ApiLiquidityPool {
id: number;
contractId: string;
lpToken: ApiLPToken;
lpTokenReserve: string; //in smallest unit
tokenA: ApiToken;
tokenReserveA: string; //in smallest unit
tokenB: ApiToken;
tokenReserveB: string; //in smallest unit
}
interface ApiLPToken {
decimals: number;
id: string;
name: string;
symbol: string;
priceUsd: string;
}
interface ApiToken {
decimals: number;
icon: string | null;
id: string;
name: string;
price: string;
priceUsd: number;
symbol: string;
dueDiligenceComplete: boolean;
isFeeOnTransferToken: boolean;
description: string | null;
website: string | null;
sentinelReport: string | null;
twitterHandle: string | null;
timestampSecondsLastListingChange: number;
}
```
## Code overview
*No gas cost — read-only call.*
```typescript theme={null}
const url = 'https://api.saucerswap.finance/pools/';
const response = await axios.get(url);
const pools = response.data;
for (const pool of pools as ApiLiquidityPool[] ) {
const symbolA = pool.tokenA.symbol;
const symbolB = pool.tokenB.symbol;
let output = '';
output += `Pool id: ${pool.id}`;
output += ` - ${pool.contractId} (${symbolA}/${symbolB})`;
console.log(output);
}
```
## Next steps
Read reserves for a single pool on-chain.
The V2 equivalent with fee tiers and ticks.
Get an API key for the REST API.
# Get pool reserves (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/get-pool-reserves
Read current SaucerSwap V1 pool reserves through the Hedera mirror node REST API or the getReserves contract function over the public JSON-RPC relay.
Below are the common methods to get the current liquidity reserves:
* [Get pool reserves via REST API](#get-pool-reserves-via-rest-api)
* [Get pool reserves via JSON RPC](#get-pool-reserves-via-json-rpc)
Getting the reserves data for a liquidity pool using SaucerSwap's REST API is also a suitable alternative. For more information, see [Fetch all pools (V1)](/developers/v1/liquidity/fetch-all-pools). The pool metadata includes the reserve data.
To track updates to liquidity pool reserves in near real-time, see [Track LP updates (V1)](/developers/v1/liquidity/track-pool-updates).
## Get pool reserves via REST API
Fetch all HTS token balances for a pool via Mirror Node's REST API.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
const apiUrl = `/api/v1/accounts/${poolContractId}/tokens`;
const response = await axios.get(`${mirrorNodeBaseUrl}${apiUrl}`);
const tokens = response.data.tokens;
for (const token of tokens ) {
console.log(`Token id: ${token.token_id}, Reserve: ${token.balance}`);
}
```
***
## Get pool reserves via JSON RPC
Fetch all HTS token balances for a pool using the getReserves() solidity function via Mirror Node's JSON RPC Relay.
Function name: `getReserves`
*No gas cost — read-only call.*
```solidity IUniswapV2Pair.sol theme={null}
function getReserves() external view returns (
uint112 reserve0,
uint112 reserve1,
uint32 blockTimestampLast
);
```
```solidity UniswapV2Pair.sol theme={null}
function getReserves()
public
view
returns (
uint112 _reserve0,
uint112 _reserve1,
uint32 _blockTimestampLast
)
{
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load abi data containing Pair's getReserves() function
const interfaces = new ethers.Interface(abi);
const poolContract = new ethers.Contract(poolAddress, interfaces.fragments, provider);
const result = await poolContract.getReserves();
const reserve0 = result.reserve0; //in token's smallest unit
const reserve1 = result.reserve1; //in token's smallest unit
const block = result.blockTimestampLast;
```
## Next steps
Follow reserve changes in near real time.
List every V1 pool with reserves included.
# V1 liquidity operations
Source: https://docs.saucerswap.finance/developers/v1/liquidity/overview
Developer guide to SaucerSwap V1 liquidity operations: fetch pools, check pool existence, read reserves, create pools, and add or remove liquidity.
These guides cover every contract and REST operation for working with SaucerSwap V1 liquidity pools on Hedera: discovering pools, reading their state, creating new pools, and managing liquidity positions.
V2 is recommended for new liquidity integrations; V1 is legacy. See the [V2 liquidity guides](/developers/v2/liquidity/new-liquidity-position) for concentrated liquidity positions.
List every V1 pool with reserves and token metadata from the REST API.
Query the factory for an existing pool before creating one.
Fetch the current pool creation fee and convert it to HBAR.
Create an HBAR-token or token-token pool with initial liquidity.
Read current reserves through the mirror node or JSON-RPC.
Poll Sync events to follow reserve changes in near real time.
Add liquidity to an existing pool and receive LP tokens.
Withdraw your share of a pool, including fee-on-transfer tokens.
# Pool creation fee (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/pool-creation-fee
Fetch the current SaucerSwap V1 pool creation fee from the factory contract in tinycent and convert it to HBAR with the mirror node exchange rate API.
The following code demonstrates how to accurately fetch the current pool creation fee in HBAR using a combination of JSON RPC and REST API. The pool creation fee is used when [creating a new liquidity pool](/developers/v1/liquidity/create-a-new-pool).
The fee for creating V1 liquidity pools is \$50 (as of July 2026), paid in HBAR. Always fetch the current value on-chain. The exchange rate information is used to accurately determine the equivalent value in HBAR.
The `pairCreateFee()` function will return the current fee expressed in **Tinycent** (US).
*No gas cost — read-only call.*
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing Factory's pairCreateFee function
const interfaces = new ethers.Interface(abi);
//get pool creation fee in tinycent
const factoryContract = new ethers.Contract(factoryEvmAddress, interfaces.fragments, provider);
const result = await factoryContract.pairCreateFee();
const tinycent = Number(result); //amount in tinycent (US)
//get the current exchange rate via REST API
const url = `${mirrorNodeBaseUrl}/api/v1/network/exchangerate`;
const response = await axios.get(url);
const currentRate = response.data.current_rate;
const centEquivalent = Number(currentRate.cent_equivalent);
const hbarEquivalent = Number(currentRate.hbar_equivalent);
const centToHbarRatio = centEquivalent/hbarEquivalent;
//calculate the fee in terms of HBAR
const tinybar = BigNumber(tinycent / centToHbarRatio).decimalPlaces(0);
const poolCreateFeeInHbar = Hbar.from(tinybar, HbarUnit.Tinybar);
console.log(`Pool creation fee: ${poolCreateFeeInHbar.toString(HbarUnit.Hbar)}`);
```
## Next steps
Use the fee when creating a new pool.
Factory and router IDs for mainnet and testnet.
# Removing liquidity (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/removing-liquidity
Remove liquidity from SaucerSwap V1 pools with the removeLiquidityETH, removeLiquidity, and fee-on-transfer functions, including allowance requirements.
Outlined below are three methods to remove liquidity from an existing pool:
* [Removing HBAR-token liquidity](#removing-hbar-token-liquidity)
* [Removing token-token liquidity](#removing-token-token-liquidity)
* [Removing HBAR-token liquidity for tokens with custom fees](#removing-hbar-token-liquidity-supporting-tokens-with-custom-fees)
Contract ID: [SaucerSwapV1RouterV3](https://hashscan.io/mainnet/contract/0.0.3045981)
A spender allowance for the router is required for the LP token.
removeLiquidity supports HTS tokens with custom fees.
## Removing HBAR-token liquidity
Remove liquidity from an existing HBAR/token liquidity pool.
Function name: `removeLiquidityETH`
Recommended gas limit: 2,800,000
| Parameter Name | Description |
| --------------------- | -------------------------------------------------------- |
| *address token* | EVM address of the token paired with HBAR |
| *uint liquidity* | LP liquidity amount to remove |
| *uint amountTokenMin* | The minimum token amount to receive in its smallest unit |
| *uint amountETHMin* | The minimum HBAR amount to receive in its smallest unit |
| *address to* | EVM address to receive the tokens |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
```
```solidity UniswapV2Router02.sol theme={null}
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) public virtual override ensure(deadline) returns (uint amountToken, uint amountETH) {
safeAssociateToken(address(this), token);
(amountToken, amountETH) = removeLiquidity(
token,
whbar,
liquidity,
amountTokenMin,
amountETHMin,
address(this), // used to be msg.sender
deadline
);
safeTransferToken(token, address(this), to, amountToken);
safeApproveToken(whbar, WHBAR, amountETH);
IWHBAR(WHBAR).withdraw(address(this), to, amountETH);
safeDissociateToken(address(this), token);
}
```
The `removeLiquidityETH` function operates in HBAR but derives its name from Uniswap on Ethereum. This name was kept to simplify integration for developers versed in Uniswap tools.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Router contract has spender allowance for the LP token
const params = new ContractFunctionParameters();
params.addAddress(tokenAddress); //address token
params.addUint256(lpTokenAmountToRemove); //uint liquidity
params.addUint256(amountTokenMin); //uint amountTokenMin
params.addUint256(amountETHMin); //uint amountETHMin
params.addAddress(toSoli); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('removeLiquidityETH', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint']);
const amountToken = values[0]; //uint amountToken
const amountHBAR = values[1]; //uint amountETH
```
***
## Removing token-token liquidity
Remove liquidity from an existing token/token liquidity pool.
Function name: `removeLiquidity`
Recommended gas limit: 1,600,000
| Parameter Name | Description |
| ----------------- | ------------------------------------------------------------ |
| *address tokenA* | EVM address of the first HTS token |
| *address tokenB* | EVM address of the second HTS token |
| *uint liquidity* | LP liquidity amount to remove in its smallest unit |
| *uint amountAMin* | The minimum amount for the first token in its smallest unit |
| *uint amountBMin* | The minimum amount for the second token in its smallest unit |
| *address to* | EVM address to receive the tokens |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Router contract has spender allowance for the LP token
const params = new ContractFunctionParameters();
params.addAddress(tokenAAddress); //address tokenA
params.addAddress(tokenBAddress); //address tokenB
params.addUint256(lpTokenAmountToRemove); //uint liquidity
params.addUint256(amountAMin); //uint amountAMin
params.addUint256(amountBMin); //uint amountBMin
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('removeLiquidity', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint','uint']);
const amountA = values[0]; //uint amountA
const amountB = values[1]; //uint amountB
```
***
## Removing HBAR-token liquidity supporting tokens with custom fees
Remove liquidity from an existing HBAR/token liquidity pool supporting HTS tokens with custom fees on transfer.
Function name: `removeLiquidityETHSupportingFeeOnTransferTokens`
Recommended gas limit: 3,000,000
| Parameter Name | Description |
| --------------------- | -------------------------------------------------------- |
| *address token* | EVM address of the token paired with HBAR |
| *uint liquidity* | LP liquidity amount to remove in its smallest unit |
| *uint amountTokenMin* | The minimum token amount to receive in its smallest unit |
| *uint amountETHMin* | The minimum HBAR amount to receive in its smallest unit |
| *address to* | EVM address to receive the tokens |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
```
```solidity UniswapV2Router02.sol theme={null}
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) public virtual override ensure(deadline) returns (uint amountETH) {
safeAssociateToken(address(this), token);
(, amountETH) = removeLiquidity(
token,
whbar,
liquidity,
amountTokenMin,
amountETHMin,
address(this),
deadline
);
uint256 amountToSend = IERC20(token).balanceOf(address(this));
require(amountToSend >= amountTokenMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT_FOT'); // second slippage check
safeTransferToken(token, address(this), to, amountToSend);
safeApproveToken(whbar, WHBAR, amountETH);
IWHBAR(WHBAR).withdraw(address(this), to, amountETH);
safeDissociateToken(address(this), token);
}
```
The `removeLiquidityETHSupportingFeeOnTransferTokens` function operates in HBAR but derives its name from Uniswap on Ethereum. This name was kept to simplify integration for developers versed in Uniswap tools.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Router contract has spender allowance for the LP token
const params = new ContractFunctionParameters();
params.addAddress(tokenAddress); //address token
params.addUint256(lpTokenAmountToRemove); //uint liquidity
params.addUint256(amountTokenMin); //uint amountTokenMin
params.addUint256(amountETHMin); //uint amountETHMin
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('removeLiquidityETHSupportingFeeOnTransferTokens', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint']);
const amountHBAR = values[0]; //uint amountETH
```
## Next steps
Provide liquidity to an existing V1 pool.
Read current reserves for a pool.
Router, factory, and token IDs for mainnet and testnet.
# Track pool updates (V1)
Source: https://docs.saucerswap.finance/developers/v1/liquidity/track-pool-updates
Track SaucerSwap V1 liquidity reserve changes in near real time by polling Sync events for one pool or all pools via the mirror node REST or JSON-RPC.
Below are the common methods to track updates in liquidity reserve balances:
* [Polling Sync events for all pools](#polling-sync-events-for-all-pools)
* [Polling Sync events for a pool](#polling-sync-events-for-a-pool)
* Subscription using eth\_subscribe (coming later - [HIP-694](https://github.com/hiero-ledger/hiero-improvement-proposals/blob/main/HIP/hip-694.md))
For production environments, it's highly recommended to use a paid Mirror Node provider for commercial and high-traffic purposes. While Hedera's public mirror node offers free REST API and JSON API endpoints, they have global rate limits. These are best suited for development or low rate usage scenarios.
## Polling Sync events for all pools
*No gas cost — read-only call.*
Whenever the reserve values for a pool contract are updated, either due to liquidity changes or a swap, a Sync event is emitted from the contract, containing the updated reserve values for the token pair. The following code demonstrates how to listen for Sync events for **all pools** using REST API or JSON RPC.
Listening to 'Sync' events without specifying an address in the filter data will return logs for all pools on SaucerSwap, as well as other DEXs on Hedera that share the same 'topic0' hash signature for the 'Sync' event. To identify and filter specific pools, extract the pool's EVM address from the log.
***
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing the Sync event
const abiInterfaces = new ethers.Interface(abi);
const filter = {
topics: [abiInterfaces.getEvent('Sync')!.topicHash], //topic0 filter
fromBlock: fromBlock,
toBlock: toBlock,
};
const logs = await provider.getLogs(filter);
for (const log of logs) {
const parsedLog = abiInterfaces.parseLog({ topics: log.topics.slice(), data: log.data });
const {reserve0, reserve1} = parsedLog!.args; //reserve values in smallest unit
const poolAddress = log.address;
console.log(`Pool: ${poolAddress}, reserve0: ${reserve0}, reserve1: ${reserve1}`);
}
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//load ABI data containing the Sync event
const abiInterfaces = new ethers.Interface(abi);
let params = `timestamp=gte:${unixFrom}×tamp=lte:${unixTo}`;
params += `&topic0=${abiInterfaces.getEvent('Sync')!.topicHash}`;
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/results/logs?${params}`;
const response = await axios.get(url);
const logs = response.data.logs;
for (const log of logs) {
const {reserve0, reserve1} = abiInterfaces.decodeEventLog('Sync', log.data);
console.log(`Pair: ${log.address}, reserve0: ${reserve0}, reserve1: ${reserve1}`);
}
```
## Polling Sync events for a pool
*No gas cost — read-only call.*
Whenever the reserve values for a pool contract are updated, either due to liquidity changes or a swap, a Sync event is emitted from the contract, containing the updated reserve values for the token pair. The following code demonstrates how to listen for Sync events for **a specific pool** using REST API or JSON RPC.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing the Sync event
const abiInterfaces = new ethers.Interface(abi);
const filter = {
topics: [abiInterfaces.getEvent('Sync')!.topicHash], //topic0 filter
fromBlock: fromBlock,
toBlock: toBlock,
address: poolEvmAddress, //pool address starting with 0x
};
const logs = await provider.getLogs(filter);
for (const log of logs) {
const parsedLog = abiInterfaces.parseLog({ topics: log.topics.slice(), data: log.data });
const {reserve0, reserve1} = parsedLog!.args; //reserve values in smallest unit
const poolAddress = log.address;
console.log(`reserve0: ${reserve0}, reserve1: ${reserve1}`);
}
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//load ABI data containing the Sync event
const abiInterfaces = new ethers.Interface(abi);
let params = `timestamp=gte:${unixFrom}×tamp=lte:${unixTo}`;
params += `&topic0=${abiInterfaces.getEvent('Sync')!.topicHash}`;
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/${contractIdEvm}/results/logs?${params}`;
const response = await axios.get(url);
const logs = response.data.logs;
for (const log of logs) {
const {reserve0, reserve1} = abiInterfaces.decodeEventLog('Sync', log.data);
console.log(`reserve0: ${reserve0}, reserve1: ${reserve1}`);
}
```
## Next steps
Read a reserve snapshot for one pool.
Monitor executed swaps the same way.
# Swap HBAR for tokens (V1)
Source: https://docs.saucerswap.finance/developers/v1/swap/swap-hbar-for-tokens
Swap HBAR for HTS tokens through the SaucerSwap V1 router: exact-input, exact-output, and fee-on-transfer variants with Hedera SDK TypeScript examples.
Below are three methods available to swap HBAR for HTS tokens:
* [Swap exact HBAR for tokens](/developers/v1/swap/swap-hbar-for-tokens#swap-exact-hbar-for-tokens)
* [Swap HBAR for exact tokens](/developers/v1/swap/swap-hbar-for-tokens#swap-hbar-for-exact-tokens)
* [Swap exact HBAR for tokens supporting custom fees](/developers/v1/swap/swap-hbar-for-tokens#swap-exact-hbar-for-tokens-supporting-custom-fees)
Contract ID: [SaucerSwapV1RouterV3](https://hashscan.io/mainnet/contract/0.0.3045981)
The `swapExactETHForTokens` and `swapETHForExactTokens` function trades in HBAR but derives its name from Uniswap on Ethereum. This name was kept to simplify integration for developers versed in Uniswap tools.
Consider the token's decimal places when determining the output amount.
The output values should be in the token's smallest unit. For the SAUCE token, which has 6 decimal places, an input of 123.45 SAUCE should be entered as 123450000 (123.45 multiplied by 10^6).
Ensure that the "**to**" account has the output token id associated prior to executing the swap. Failure to do so will result in a `TOKEN_NOT_ASSOCIATED_TO_ACCOUNT` error.
When providing HBAR in the path array, use the wrapped HBAR token ID ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)).
## Swap exact HBAR for tokens
Swap an exact amount of HBAR for a minimum token amount.
Solidity function name: `swapExactETHForTokens`
| Parameter name | Description |
| -------------------------- | -------------------------------------------------------- |
| *uint amountOutMin* | The minimum token amount to receive in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
virtual
override
payable
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[0] == whbar, 'UniswapV2Router: INVALID_PATH');
amounts = UniswapV2Library.getAmountsOut(factory, msg.value, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
IWHBAR(WHBAR).deposit{value: amounts[0]}(msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]));
_swap(amounts, path, to);
}
```
Set the minimum output token amount (`amountOutMin`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
const params = new ContractFunctionParameters();
params.addUint256(amountOutMin); //uint amountOutMin
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setPayableAmount(inputHbar)
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapExactETHForTokens', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint[]']);
const amounts = values[0]; //uint[] amounts
const finalOutputAmount = amounts[amounts.length - 1];
```
## Swap HBAR for exact tokens
Swap a maximum amount of HBAR to receive an exact tokens amount
Solidity function name: `swapETHForExactTokens`
| Parameter Name | Description |
| -------------------------- | ------------------------------------------------------- |
| *uint amountOut* | The exact output amount to receive in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function swapETHForExactTokens(
uint amountOut,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
virtual
override
payable
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[0] == whbar, 'UniswapV2Router: INVALID_PATH');
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= msg.value, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
IWHBAR(WHBAR).deposit{value: amounts[0]}(msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]));
_swap(amounts, path, to);
// refund dust eth, if any
if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
}
```
Set the maximum HBAR amount (**payable**) with caution.
A low maximum might lead to a swap failure if the required liquidity surpasses this limit or due to rapid price movements. Conversely, setting it too high can expose you to significant slippage, potentially leading to a financial loss as you might spend far more HBAR than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
const params = new ContractFunctionParameters();
params.addUint256(amountOut); //uint amountOut
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setPayableAmount(inputHbar)
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapETHForExactTokens', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint[]']);
const amounts = values[0]; //uint[] amounts
const finalInputAmount = amounts[0];
```
## Swap exact HBAR for tokens supporting custom fees
Swap an exact amount of HBAR for a minimum token amount, supporting HTS tokens with custom fees on token transfer.
Solidity function name: `swapExactETHForTokensSupportingFeeOnTransferTokens`
| Parameter name | Description |
| -------------------------- | -------------------------------------------------------- |
| *uint amountOutMin* | The minimum token amount to receive in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router02.sol theme={null}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
```
```solidity UniswapV2Router02.sol theme={null}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
)
external
virtual
override
payable
ensure(deadline)
{
require(path[0] == whbar, 'UniswapV2Router: INVALID_PATH');
uint amountIn = msg.value;
IWHBAR(WHBAR).deposit{value: amountIn}(msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]));
uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'
);
}
```
Set the minimum output token amount (`amountOutMin`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
const params = new ContractFunctionParameters();
params.addUint256(amountOutMin); //uint amountOutMin
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
await new ContractExecuteTransaction()
.setPayableAmount(inputHbar)
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapExactETHForTokensSupportingFeeOnTransferTokens', params)
.execute(client);
```
## Next steps
Fetch expected amounts before you execute the swap.
Run the same flow in the opposite direction.
Monitor executed swaps in near real time.
# Swap quote (V1)
Source: https://docs.saucerswap.finance/developers/v1/swap/swap-quote
Get SaucerSwap V1 swap quotes with the getAmountsOut and getAmountsIn functions through the Hedera JSON-RPC relay or mirror node, at no gas cost.
Below are the two methods to get a quote for a swap from a given route using JSON-RPC or REST-API:
* [Get output quote from exact input amount](/developers/v1/swap/swap-quote#get-output-quote-from-input-amount)
* [Get input quote from exact output amount](/developers/v1/swap/swap-quote#get-input-quote-from-output-amount)
Contract ID: [SaucerSwapV1RouterV3](https://hashscan.io/mainnet/contract/0.0.3045981)
When providing HBAR in the path array, use the wrapped HBAR token ID ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)).
## Get output quote from input amount
*No gas cost — read-only call.*
Get the output amounts from a given input amount and a swap route.
Function name: `getAmountsOut`
| Parameter Name | Description |
| ----------------- | ------------------------------------------- |
| *uint amountIn* | The input token amount in its smallest unit |
| *address\[] path* | An ordered list of token EVM addresses |
```solidity IUniswapV2Router01.sol theme={null}
function getAmountsOut(
uint amountIn,
address[] calldata path
) external view returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function getAmountsOut(uint amountIn, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return UniswapV2Library.getAmountsOut(factory, amountIn, path);
}
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//ABI data for the getAmountsOut
const abi = ['function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)'];
//Load the ABI
const abiInterfaces = new ethers.Interface(abi);
//Example route
const tokenIn = '0x' + TokenId.fromString(whbarTokenId).toSolidityAddress();
const tokenOut = '0x' + TokenId.fromString(sauceTokenId).toSolidityAddress();
const route = [tokenIn, tokenOut];
const routerContract = new ethers.Contract(routerEvmAddress, abiInterfaces.fragments, provider);
const result = await routerContract.getAmountsOut(inputAmountInSmallestUnit, route);
const amounts = result; //uint[] amounts
const finalOutputAmount = amounts[amounts.length - 1]; //in token's smallest unit
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//ABI data for the getAmountsOut
const abi = ['function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)'];
//Load the ABI
const abiInterfaces = new ethers.Interface(abi);
//Example route (WHBAR > SAUCE)
const tokenIn = '0x' + TokenId.fromString(whbarTokenId).toSolidityAddress();
const tokenOut = '0x' + TokenId.fromString(sauceTokenId).toSolidityAddress();
const route = [tokenIn, tokenOut];
const routerContract = ContractId.fromString(routerContractId);
const params = [inputAmountInSmallestUnit, route];
const encodedData = abiInterfaces.encodeFunctionData(abiInterfaces.getFunction('getAmountsOut')!, params);
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/call`;
const data = {
'block': 'latest',
'data': encodedData,
'to': routerContract.toSolidityAddress(),
};
const response = await axios.post(url, data, { headers: {'content-type': 'application/json'} });
const amounts = abiInterfaces.decodeFunctionResult('getAmountsOut', response.data.result)[0]; //uint[] amounts
const finalOutputAmount = amounts[amounts.length - 1]; //in token's smallest unit
```
***
## Get input quote from output amount
*No gas cost — read-only call.*
Get the input amounts from a given output amount and a swap route.
Function name: `getAmountsIn`
| Parameter Name | Description |
| ----------------- | -------------------------------------------- |
| *uint amountOut* | The output token amount in its smallest unit |
| *address\[] path* | An ordered list of token EVM addresses |
```solidity IUniswapV2Router01.sol theme={null}
function getAmountsIn(
uint amountOut,
address[] calldata path
) external view returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function getAmountsIn(uint amountOut, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return UniswapV2Library.getAmountsIn(factory, amountOut, path);
}
```
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
const networkId = 'testnet';
const provider = new ethers.JsonRpcProvider(`https://${networkId}.hashio.io/api`, '', {
batchMaxCount: 1,
});
//ABI data for the getAmountsIn
const abi = ['function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts)'];
//Load the ABI
const abiInterfaces = new ethers.Interface(abi);
//Example route (WHBAR > SAUCE)
const tokenIn = '0x' + TokenId.fromString(whbarTokenId).toSolidityAddress();
const tokenOut = '0x' + TokenId.fromString(sauceTokenId).toSolidityAddress();
const route = [tokenIn, tokenOut];
const routerContract = new ethers.Contract(routerEvmAddress, abiInterfaces.fragments, provider);
const result = await routerContract.getAmountsIn(outputAmountInSmallestUnit, route);
const amounts = result; //uint[] amounts
const finalInputAmount = amounts[0]; //in token's smallest unit
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//ABI data for the getAmountsIn
const abi = ['function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts)'];
//Load the ABI
const abiInterfaces = new ethers.Interface(abi);
//Example route (WHBAR > SAUCE)
const tokenIn = '0x' + TokenId.fromString(whbarTokenId).toSolidityAddress();
const tokenOut = '0x' + TokenId.fromString(sauceTokenId).toSolidityAddress();
const route = [tokenIn, tokenOut];
const routerContract = ContractId.fromString(routerContractId);
const params = [outputAmountInSmallestUnit, route];
const encodedData = abiInterfaces.encodeFunctionData(abiInterfaces.getFunction('getAmountsIn')!, params);
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/call`;
const data = {
'block': 'latest',
'data': encodedData,
'to': routerContract.toSolidityAddress(),
};
const response = await axios.post(url, data, { headers: {'content-type': 'application/json'} });
const amounts = abiInterfaces.decodeFunctionResult('getAmountsIn', response.data.result)[0]; //uint[] amounts
const finalInputAmount = amounts[0]; //in token's smallest unit
```
## Next steps
Execute the swap you just quoted with the V1 router.
Quote against V2 concentrated liquidity with QuoterV2.
Router, factory, and token IDs for mainnet and testnet.
# Swap tokens for HBAR (V1)
Source: https://docs.saucerswap.finance/developers/v1/swap/swap-tokens-for-hbar
Swap HTS tokens for HBAR through the SaucerSwap V1 router: exact-input, exact-output, and fee-on-transfer variants with allowance and association checks.
Below are three methods available to swap tokens for HBAR:
* [Swap exact tokens for HBAR](/developers/v1/swap/swap-tokens-for-hbar#swap-exact-tokens-for-hbar)
* [Swap tokens for exact HBAR](/developers/v1/swap/swap-tokens-for-hbar#swap-tokens-for-exact-hbar)
* [Swap exact tokens supporting custom fees for HBAR](/developers/v1/swap/swap-tokens-for-hbar#swap-exact-tokens-supporting-custom-fees-for-hbar)
Contract ID: [SaucerSwapV1RouterV3](https://hashscan.io/mainnet/contract/0.0.3045981)
The `swapExactTokensForETH` and `swapTokensForExactETH` function trades in HBAR but derives its name from Uniswap on Ethereum. This name was kept to simplify integration for developers versed in Uniswap tools.
Granting a spender allowance to the router contract **is required** when the input token is not native HBAR for security reasons enforced at the native code layer. Ensure that the allowance amount is in token's smallest unit.
Consider the token's decimal places when determining input amounts.
The input values should be in the token's smallest unit. For the SAUCE token, which has 6 decimal places, an input of 123.45 SAUCE should be entered as 123450000 (123.45 multiplied by 10^6).
When providing HBAR in the path array, use the wrapped HBAR token ID ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)).
## Swap exact tokens for HBAR
Swap an exact amount of tokens for a minimum HBAR amount.
Solidity function name: `swapExactTokensForETH`
| Parameter Name | Description |
| -------------------------- | -------------------------------------------------------- |
| *uint amountIn* | The input token amount in its smallest unit |
| *uint amountOutMin* | The minimum token amount to receive in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
virtual
override
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[path.length - 1] == whbar, 'UniswapV2Router: INVALID_PATH');
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
safeTransferToken(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
);
_swap(amounts, path, address(this));
safeApproveToken(whbar, WHBAR, amounts[amounts.length - 1]);
IWHBAR(WHBAR).withdraw(address(this), to, amounts[amounts.length - 1]);
}
```
Set the minimum output token amount (`amountOutMin`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addUint256(amountIn); //uint amountIn
params.addUint256(amountOutMin); //uint amountOutMin
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapExactTokensForETH', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint[]']);
const amounts = values[0]; //uint[] amounts
const finalOutputAmount = amounts[amounts.length - 1];
```
***
## Swap tokens for exact HBAR
Swap a maximum amount of tokens to receive an exact HBAR amount.
```solidity IUniswapV2Router01.sol theme={null}
function swapTokensForExactETH(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
virtual
override
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[path.length - 1] == whbar, 'UniswapV2Router: INVALID_PATH');
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
safeTransferToken(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
);
_swap(amounts, path, address(this));
safeApproveToken(whbar, WHBAR, amounts[amounts.length - 1]);
IWHBAR(WHBAR).withdraw(address(this), to, amounts[amounts.length - 1]);
}
```
Function name: `swapTokensForExactETH`
| Parameter Name | Description |
| -------------------------- | ------------------------------------------------------------ |
| *uint amountOut* | The exact output HBAR amount to receive in its smallest unit |
| *uint amountInMax* | The maximum allowed input amount in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
Set the maximum input token amount (`amountInMax`) with caution.
A low maximum might lead to a swap failure if the required liquidity surpasses this limit or due to rapid price movements. Conversely, setting it too high can expose you to significant slippage, potentially leading to a financial loss as you might spend far more tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addUint256(amountOut); //uint amountOut
params.addUint256(amountInMax); //uint amountInMax
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapTokensForExactETH', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint[]']);
const amounts = values[0]; //uint[] amounts
const finalInputAmount = amounts[0];
```
***
## Swap exact tokens supporting custom fees for HBAR
Swap an exact amount of tokens, supporting HTS tokens with custom fees on token transfer, for a minimum HBAR amount.
Solidity function name: `swapExactTokensForETHSupportingFeeOnTransferTokens`
| Parameter Name | Description |
| -------------------------- | -------------------------------------------------------- |
| *uint amountIn* | The input token amount in its smallest unit |
| *uint amountOutMin* | The minimum token amount to receive in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router02.sol theme={null}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
```
```solidity UniswapV2Router02.sol theme={null}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
)
external
virtual
override
ensure(deadline)
{
require(path[path.length - 1] == whbar, 'UniswapV2Router: INVALID_PATH');
uint startAmount = IERC20(whbar).balanceOf(address(this));
safeTransferToken(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn
);
_swapSupportingFeeOnTransferTokens(path, address(this));
uint endAmount = IERC20(whbar).balanceOf(address(this));
uint amountOut = endAmount.sub(startAmount);
require(amountOut >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
safeApproveToken(whbar, WHBAR, amountOut);
IWHBAR(WHBAR).withdraw(address(this), to, amountOut);
}
```
Set the minimum output token amount (`amountOutMin`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addUint256(amountIn); //uint amountIn
params.addUint256(amountOutMin); //uint amountOutMin
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapExactTokensForETHSupportingFeeOnTransferTokens', params)
.execute(client);
```
## Next steps
Fetch expected amounts before you execute the swap.
Swap between two HTS tokens with the same router.
Router, factory, and token IDs for mainnet and testnet.
# Swap tokens for tokens (V1)
Source: https://docs.saucerswap.finance/developers/v1/swap/swap-tokens-for-tokens
Swap HTS tokens for other HTS tokens through the SaucerSwap V1 router, covering exact-input, exact-output, and fee-on-transfer variants with examples.
Below are three methods available to swap tokens for tokens:
* [Swap exact tokens for tokens](/developers/v1/swap/swap-tokens-for-tokens#swap-exact-tokens-for-tokens)
* [Swap tokens for exact tokens](/developers/v1/swap/swap-tokens-for-tokens#swap-tokens-for-exact-tokens)
* [Swap exact tokens for tokens supporting custom fees](/developers/v1/swap/swap-tokens-for-tokens#swap-exact-tokens-for-tokens-supporting-custom-fees)
Contract ID: [SaucerSwapV1RouterV3](https://hashscan.io/mainnet/contract/0.0.3045981)
Consider the token's decimal places when determining input and output values.
Input and output amounts passed to the solidity function should all be in the token's smallest unit. For the SAUCE token, which has 6 decimal places, an input of 123.45 SAUCE should be entered as 123450000 (123.45 multiplied by 10^6).
Granting a spender allowance to the router contract **is required** when the input token is not native HBAR for security reasons enforced at the native code layer. Ensure that the allowance amount is in token's smallest unit.
Ensure that the "to" account has the output token id associated prior to executing the swap. Failure to do so will result in a `TOKEN_NOT_ASSOCIATED_TO_ACCOUNT` error.
***
## Swap exact tokens for tokens
Swap an exact amount of tokens for a minimum token amount.
Solidity function name: `swapExactTokensForTokens`
| Parameter Name | Description |
| -------------------------- | -------------------------------------------------------- |
| *uint amountIn* | The exact input token amount in its smallest unit |
| *uint amountOutMin* | The minimum token amount to receive in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
safeTransferTokenRouter(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
);
_swap(amounts, path, to);
}
```
Set the minimum output token amount (`amountOutMin`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addUint256(amountIn); //uint amountIn
params.addUint256(amountOutMin); //uint amountOutMin
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapExactTokensForTokens', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint[]']);
const amounts = values[0]; //uint[] amounts
const finalOutputAmount = amounts[amounts.length - 1];
```
***
## Swap tokens for exact tokens
Swap a maximum amount of tokens to receive an exact tokens amount.
Solidity function name: `swapTokensForExactTokens`
| Parameter name | Description |
| -------------------------- | ------------------------------------------------------- |
| *uint amountOut* | The exact output amount to receive in its smallest unit |
| *uint amountInMax* | The maximum allowed input amount in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router01.sol theme={null}
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
```
```solidity UniswapV2Router02.sol theme={null}
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT');
safeTransferToken(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
);
_swap(amounts, path, to);
}
```
Set the maximum input token amount (`amountInMax`) with caution.
A low maximum might lead to a swap failure if the required liquidity surpasses this limit or due to rapid price movements. Conversely, setting it too high can expose you to significant slippage, potentially leading to a financial loss as you might spend far more tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addUint256(amountOut); //uint amountOut
params.addUint256(amountInMax); //uint amountInMax
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
const response = await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapTokensForExactTokens', params)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint[]']);
const amounts = values[0]; //uint[] amounts
const finalInputAmount = amounts[0];
```
***
## Swap exact tokens for tokens supporting custom fees
Swap an exact amount of tokens for a minimum token amount, supporting HTS tokens with custom fees on token transfer.
Solidity function name: `swapExactTokensForTokensSupportingFeeOnTransferTokens`
| Parameter Name | Description |
| -------------------------- | -------------------------------------------------------- |
| *uint amountIn* | The input token amount in its smallest unit |
| *uint amountOutMin* | The minimum token amount to receive in its smallest unit |
| *address\[] calldata path* | An ordered list of token EVM addresses |
| *address to* | EVM address for the token recipient |
| *uint deadline* | Deadline in Unix seconds |
```solidity IUniswapV2Router02.sol theme={null}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
```
```solidity UniswapV2Router02.sol theme={null}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) {
safeTransferToken(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn
);
uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin,
'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'
);
}
```
Set the minimum output token amount (`amountOutMin`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
// - Router contract has spender allowance for the input token
const params = new ContractFunctionParameters();
params.addUint256(amountIn); //uint amountIn
params.addUint256(amountOutMin); //uint amountOutMin
params.addAddressArray(tokenPath); //address[] calldata path
params.addAddress(toAddress); //address to
params.addUint256(deadline); //uint deadline
await new ContractExecuteTransaction()
.setContractId(routerContractId)
.setGas(gasLim)
.setFunction('swapExactTokensForTokensSupportingFeeOnTransferTokens', params)
.execute(client);
```
## Next steps
Fetch expected amounts before you execute the swap.
Monitor executed swaps in near real time.
Use V2 concentrated liquidity for the same operation.
# Track swap events (V1)
Source: https://docs.saucerswap.finance/developers/v1/swap/track-swap-events
Monitor SaucerSwap V1 Swap events in near real time by polling the Hedera mirror node REST API or the JSON-RPC relay, with log grouping by transaction.
Below are the common methods to monitor swap events:
* [Polling Swap events for all pairs](/developers/v1/swap/track-swap-events#polling-swap-events-for-all-pairs)
* Subscription using eth\_subscribe (coming later - [HIP-694](https://github.com/hiero-ledger/hiero-improvement-proposals/blob/main/HIP/hip-694.md))
For production environments, it's highly recommended to use a paid Mirror Node provider for commercial and high-traffic purposes. While Hedera's public mirror node offers free REST API and JSON API endpoints, they have global rate limits. These are best suited for development or low rate usage scenarios.
## Polling Swap events for all pairs
*No gas cost — read-only call.*
Every time a user executes a swap, the contract emits a 'Swap' event with the updated reserve values for the token pair. The following code demonstrates how to listen to these 'Swap' events for all pairs using either the REST API or JSON RPC.
Listening to 'Swap' events without specifying an address in the filter data will return logs for all pairs on SaucerSwap, as well as other DEXs on Hedera that share the same 'topic0' hash signature for the 'Swap' event. To identify and filter specific pairs, extract the pair's EVM address from the log.
When a swap involves multiple liquidity pairs, a successful smart contract call will emit multiple 'Swap' events. To determine the route used, as well as the initial input amount and the final output amount, aggregate all the 'Swap' event logs.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
const networkId = 'testnet';
const provider = new ethers.JsonRpcProvider(`https://${networkId}.hashio.io/api`, '', {
batchMaxCount: 1, //workaround for ethers V6
});
//load ABI data containing the Swap event
const abiInterfaces = new ethers.Interface(abi);
const filter = {
topics: [abiInterfaces.getEvent('Swap')!.topicHash], //topic0 filter
fromBlock: fromBlock,
toBlock: toBlock,
};
//group logs on transaction hash
const groupedLogs:any = {};
const logs = await provider.getLogs(filter);
for (const log of logs) {
const tnxHash = log.transactionHash;
if (!groupedLogs[tnxHash]) {
groupedLogs[tnxHash] = [];
}
groupedLogs[tnxHash].push(log);
}
Object.keys(groupedLogs).forEach(tnxHash => {
console.log(`\nTransaction hash: ${tnxHash}`);
//group logs by log index
groupedLogs[tnxHash].sort((a: any, b: any) => a.index - b.index);
for (const log of groupedLogs[tnxHash]) {
const pairEvmAddress = log.address; //use this to get token0 and token1 data
const parsedLog = abiInterfaces.parseLog({ topics: log.topics.slice(), data: log.data });
const result = parsedLog!.args;
//amount0In / amount0Out is token0
//amount1In / amount1Out is token1
const amountIn = result.amount0In == 0 ? result.amount1In : result.amount0In;
const amountOut = result.amount0Out == 0 ? result.amount1Out : result.amount0Out;
console.log(`Pair: ${pairEvmAddress}, amountIn: ${amountIn}, amountOut: ${amountOut}`);
}
});
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
const abiInterfaces = new ethers.Interface(abi);
let params = `timestamp=gte:${unixFrom}×tamp=lte:${unixTo}`;
params += `&topic0=${abiInterfaces.getEvent('Swap')!.topicHash}`;
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/results/logs?${params}`;
const response = await axios.get(url);
const logs = response.data.logs;
//group logs on transaction hash
const groupedLogs:any = {};
for (const log of logs) {
const tnxHash = log.transaction_hash;
if (!groupedLogs[tnxHash]) {
groupedLogs[tnxHash] = [];
}
groupedLogs[tnxHash].push(log);
}
Object.keys(groupedLogs).forEach(tnxHash => {
console.log(`\nTransaction hash: ${tnxHash}`);
//group logs by log index
groupedLogs[tnxHash].sort((a: any, b: any) => a.index - b.index);
for (const log of groupedLogs[tnxHash]) {
const pairEvmAddress = log.address; //use this to get token0 and token1 data
const parsedLog = abiInterfaces.parseLog({ topics: log.topics.slice(), data: log.data });
const result = parsedLog!.args;
//amount0In / amount0Out is token0
//amount1In / amount1Out is token1
const amountIn = result.amount0In == 0 ? result.amount1In : result.amount0In;
const amountOut = result.amount0Out == 0 ? result.amount1Out : result.amount0Out;
console.log(`Pair: ${pairEvmAddress}, amountIn: ${amountIn}, amountOut: ${amountOut}`);
}
});
```
## Next steps
Follow reserve changes through Sync events.
The V2 equivalent with price and liquidity fields.
Router, factory, and token IDs for mainnet and testnet.
# Check if a pool exists (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/check-if-a-pool-exists
Check whether a SaucerSwap V2 pool exists for a token pair and fee tier with the factory getPool function before minting a new liquidity position.
Checking if the liquidity pool with the matching fee tier exists using SaucerSwap's REST API is also a suitable alternative. For more information, see [Get all Liquidity Pools (V2)](/developers/v2/liquidity/fetch-all-pools).
***
Function name: `getPool`
*No gas cost — read-only call.*
| Parameter Name | Description |
| ---------------- | --------------------------------------------------------------------------------- |
| *address token0* | The contract address of either token0 or token1 |
| *address token1* | The contract address of the other token |
| *uint24 fee* | The fee collected upon every swap in the pool, denominated in hundredths of a bip |
```solidity IUniswapV3Factory.sol theme={null}
/// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
/// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
/// @param tokenA The contract address of either token0 or token1
/// @param tokenB The contract address of the other token
/// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
/// @return pool The pool address
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
```
When working with HBAR, use the WHBAR (Wrapped HBAR) token address for either tokenA or tokenB.
The ordering of tokens for token0 and token1 does not matter.
If the pool does not exist, a zero address will be returned.
## Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing the Factory's getPool function
const interfaces = new ethers.Interface(abi);
const factoryContract = new ethers.Contract(factoryEvmAddress, interfaces.fragments, provider);
const result = await factoryContract.getPool(token0, token1, fee); //(token1, token0, fee) will give same result
const poolEvmAddress = result; //address pool
```
## Next steps
Mint a position once the pool is confirmed.
List every V2 pool from the REST API.
# Claiming fees (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/claiming-fees
Claim accrued swap fees from a SaucerSwap V2 liquidity position with the collect function, adding an unwrapWHBAR multicall for pools that include HBAR.
Contract ID: [SaucerSwapV2NonfungiblePositionManager](https://hashscan.io/mainnet/contract/0.0.4053945)
See [Get user positions](/developers/v2/liquidity/get-user-positions) for details how to retrieve all positions of a user including fees earned if any.
***
Function name: `collect`
Recommended gas limit: 300,000
| Struct Parameter Name | Description |
| --------------------- | ------------------------------------------------------------ |
| *uint256 tokenSN* | The serial number of the position NFT to collect fees for |
| *address recipient* | EVM address to receive the claimed swap fees |
| *uint256 amount0Max* | The maximum amount for the first token in its smallest unit |
| *uint256 amount1Max* | The maximum amount for the second token in its smallest unit |
```solidity INonfungiblePositionManager.sol theme={null}
struct CollectParams {
uint256 tokenSN;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
/// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient
/// @param params tokenSN The serial number of the NFT for which tokens are being collected,
/// recipient The account that should receive the tokens,
/// amount0Max The maximum amount of token0 to collect,
/// amount1Max The maximum amount of token1 to collect
/// @return amount0 The amount of fees collected in token0
/// @return amount1 The amount of fees collected in token1
function collect(CollectParams calldata params) external payable
returns (uint256 amount0, uint256 amount1);
```
```solidity NonfungiblePositionManager.sol theme={null}
/// @inheritdoc INonfungiblePositionManager
function collect(CollectParams calldata params)
external
payable
override
isAuthorizedForToken(params.tokenSN)
returns (uint256 amount0, uint256 amount1)
{
require(params.amount0Max > 0 || params.amount1Max > 0);
// allow collecting to the nft position manager address with address 0
address recipient = params.recipient == address(0) ? address(this) : params.recipient;
Position storage position = _positions[params.tokenSN];
PoolAddress.PoolKey memory poolKey = _poolIdToPoolKey[position.poolId];
IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
(uint128 tokensOwed0, uint128 tokensOwed1) = (position.tokensOwed0, position.tokensOwed1);
// trigger an update of the position fees owed and fee growth snapshots if it has any liquidity
if (position.liquidity > 0) {
pool.burn(position.tickLower, position.tickUpper, 0);
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(
PositionKey.compute(address(this), position.tickLower, position.tickUpper)
);
tokensOwed0 += uint128(
FullMath.mulDiv(
feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
tokensOwed1 += uint128(
FullMath.mulDiv(
feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
}
// compute the arguments to give to the pool#collect method
(uint128 amount0Collect, uint128 amount1Collect) = (
params.amount0Max > tokensOwed0 ? tokensOwed0 : params.amount0Max,
params.amount1Max > tokensOwed1 ? tokensOwed1 : params.amount1Max
);
// the actual amounts collected are returned
(amount0, amount1) = pool.collect(
recipient,
position.tickLower,
position.tickUpper,
amount0Collect,
amount1Collect
);
// sometimes there will be a few less wei than expected due to rounding down in core, but we just subtract the full amount expected
// instead of the actual amount so we can burn the token
(position.tokensOwed0, position.tokensOwed1) = (tokensOwed0 - amount0Collect, tokensOwed1 - amount1Collect);
emit Collect(params.tokenSN, recipient, amount0Collect, amount1Collect);
}
```
## Code overview
The following code demonstrates how to claim all swap fees from a pool.
When claiming fees from a pool that involves HBAR, include `unwrapWHBAR` in your multicall to convert the Wrapped HBAR (WHBAR) output token back into the native HBAR cryptocurrency.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Uniswap V3 SDK](https://docs.uniswap.org/sdk/v3/overview)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import { Pool, Position, nearestUsableTick, priceToClosestTick } from '@uniswap/v3-sdk';
import { Fraction, Percent, Token, Price } from '@uniswap/sdk-core';
import { ContractExecuteTransaction } from '@hashgraph/sdk';
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//Load the ABI data for NonfungiblePositionManager
const nftManagerInterfaces = new ethers.Interface(nftManagerAbi);
//get max possible value for amount0Max and amount1Max
const MAX_UINT128 = new BigNumber(2).pow(128).minus(1).toFixed(0);
//CollectParams struct
const params = {
tokenSN: tokenSN,
recipient: recipientAddress,
amount0Max: MAX_UINT128, //collect max fees
amount1Max: MAX_UINT128, //collect max fees
};
//Construct encoded data for each function
const collectEncoded = nftManagerInterfaces.encodeFunctionData('collect', [params]);
//Not needed if HBAR isn't included in the pool
const unwrapWHBAREncoded = nftManagerInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipientAddress]);
//Build encoded data for the multicall
const encodedData = nftManagerInterfaces.encodeFunctionData('multicall',
[[collectEncoded, unwrapWHBAREncoded]]);
const encodedDataAsUint8Array = hexToUint8Array(encodedData.substring(2));
//Execute the paid contract call
const response = await new ContractExecuteTransaction()
.setContractId(nftManagerContractId)
.setGas(gasGwei)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
//Fetch the result
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const results = nftManagerInterfaces.decodeFunctionResult('multicall', result.bytes)[0];
const collectResult = nftManagerInterfaces.decodeFunctionResult('collect', results[0]);
//Retrieve the collected amounts for informative purposes
const amount0 = BigNumber(collectResult.amount0);
const amount1 = BigNumber(collectResult.amount1);
```
## Next steps
See fees earned across all positions.
Collect fees while exiting a position.
# Decreasing liquidity (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/decreasing-liquidity
Decrease or fully exit a SaucerSwap V2 liquidity position with the decreaseLiquidity, collect, unwrapWHBAR, and optional burn calls in one multicall.
Contract ID: [SaucerSwapV2NonfungiblePositionManager](https://hashscan.io/mainnet/contract/0.0.4053945)
***
## Decrease liquidity
Function name: `decreaseLiquidity`
Recommended gas limit: 300,000
| Struct Parameter Name | Description |
| --------------------- | --------------------------------------------------------------------- |
| *uint256 tokenSN* | The serial number of the token for which liquidity is being decreased |
| *uint128 liquidity* | Liquidity amount to remove |
| *uint256 amount0Min* | The minimum amount for the first token in its smallest unit |
| *uint256 amount1Min* | The minimum amount for the second token in its smallest unit |
| *uint256 deadline* | Deadline in Unix seconds |
```solidity INonfungiblePositionManager.sol theme={null}
struct DecreaseLiquidityParams {
uint256 tokenSN;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Decreases the amount of liquidity in a position and accounts it to the position
/// @param params tokenSN The serial number of the token for which liquidity is being decreased,
/// amount The amount by which liquidity will be decreased,
/// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity,
/// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity,
/// deadline The time by which the transaction must be included to effect the change
/// @return amount0 The amount of token0 accounted to the position's tokens owed
/// @return amount1 The amount of token1 accounted to the position's tokens owed
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
```
```solidity NonfungiblePositionManager.sol theme={null}
/// @inheritdoc INonfungiblePositionManager
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
external
payable
override
isAuthorizedForToken(params.tokenSN)
checkDeadline(params.deadline)
returns (uint256 amount0, uint256 amount1)
{
require(params.liquidity > 0);
Position storage position = _positions[params.tokenSN];
uint128 positionLiquidity = position.liquidity;
require(positionLiquidity >= params.liquidity);
PoolAddress.PoolKey memory poolKey = _poolIdToPoolKey[position.poolId];
IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
(amount0, amount1) = pool.burn(position.tickLower, position.tickUpper, params.liquidity);
require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, 'Price slippage check');
bytes32 positionKey = PositionKey.compute(address(this), position.tickLower, position.tickUpper);
// this is now updated to the current transaction
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(positionKey);
position.tokensOwed0 +=
uint128(amount0) +
uint128(
FullMath.mulDiv(
feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128,
positionLiquidity,
FixedPoint128.Q128
)
);
position.tokensOwed1 +=
uint128(amount1) +
uint128(
FullMath.mulDiv(
feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
positionLiquidity,
FixedPoint128.Q128
)
);
position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
// subtraction is safe because we checked positionLiquidity is gte params.liquidity
position.liquidity = positionLiquidity - params.liquidity;
emit DecreaseLiquidity(params.tokenSN, params.liquidity, amount0, amount1);
}
```
### Code overview
The following code demonstrates how to remove all liquidity from an existing position, collect the swap fees, and return the deposit amounts.
When removing liquidity from a pool that involves HBAR, include `unwrapWHBAR` in your call to convert the Wrapped HBAR (WHBAR) output token back into the native HBAR cryptocurrency.
Call the `collect` function after removing the liquidity to withdraw the amounts to the recipient address. It will also collect any swap fees earned in the position.
To burn the NFT after completely exiting the position, include `burn` in the multi-call. See [Burning the NFT](#burning-the-nft).
Hedera's EVM chain ID can be retrieved from [https://chainlist.org](https://chainlist.org/?testnets=true\&search=Hedera).
The following code is intended for guidance purposes and does not include checks and safeguards.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Uniswap V3 SDK](https://docs.uniswap.org/sdk/v3/overview)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import { Pool, Position, nearestUsableTick, priceToClosestTick } from '@uniswap/v3-sdk';
import { Fraction, Percent, Token, Price } from '@uniswap/sdk-core';
import { ContractExecuteTransaction } from '@hashgraph/sdk';
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//Load the ABI data for UniswapV3Pool
const poolInterfaces = new ethers.Interface(poolAbi);
//Load the ABI data for NonfungiblePositionManager
const nftManagerInterfaces = new ethers.Interface(nftManagerAbi);
//Construct the pool contract
const poolContract = new ethers.Contract(poolEvmAddress,
poolInterfaces.fragments, provider);
//Construct the NFT Manager contract
const nftManagerContract = new ethers.Contract(nftManagerEvmAddress,
nftManagerInterfaces.fragments, provider);
//Get current position data for the given NFT token serial number
const lp = await nftManagerContract.positions(tokenSN);
const token0Address = lp.token0;
const token1Address = lp.token1;
const feeTier = Number(lp.fee);
const tickLower = Number(lp.tickLower);
const tickUpper = Number(lp.tickUpper);
const liquidity = lp.liquidity.toString();
//Get current slot0 and liquidity data from the pool
const [slot0, poolLiquidity] = await Promise.all([
poolContract.slot0(),
poolContract.liquidity()
]);
//Construct the tokens
//For Hedera chain id, see https://chainlist.org/?testnets=true&search=Hedera
const token0 = new Token(hederaChainId, token0Address, token0Decimals);
const token1 = new Token(hederaChainId, token1Address, token1Decimals);
//Construct the pool using the latest data
const pool = new Pool(
token0, token1,
feeTier, slot0.sqrtPriceX96.toString(),
poolLiquidity.toString(), Number(slot0.tick)
);
//Construct a position from liquidity and range
const position = new Position({
pool: pool,
tickUpper: tickUpper,
tickLower: tickLower,
liquidity: liquidity
});
//Calculate the maximum amounts factoring in the price slippage % and range
const priceSlippagePercent = new Percent(1, 100); //1% price slippage
const burnAmounts = position.burnAmountsWithSlippage(priceSlippagePercent);
const amount0Min = burnAmounts.amount0.toString();
const amount1Min = burnAmounts.amount1.toString();
//DecreaseLiquidityParams struct
const params = {
tokenSN: tokenSN,
liquidity: liquidity, //liquidity amount to remove
amount0Min: amount0Min, //in smallest unit
amount1Min: amount1Min, //in smallest unit
deadline: deadline, //Unix seconds
};
//get max possible value for amount0Max and amount1Max
const MAX_UINT128 = new BigNumber(2).pow(128).minus(1).toFixed(0);
//CollectParams struct
const collectParams = {
tokenSN: tokenSN,
recipient: recipientAddress, //0x..
amount0Max: MAX_UINT128, //collect max fees and amount
amount1Max: MAX_UINT128, //collect max fees and amount
};
//Construct encoded data for each function
//The unwrapWHBAR is needed when collecting the HBAR swap fees
//Optionally include 'collect' here to collect fees.
//Optionally include 'burn' to burn the NFT if all liquidity is removed.
const decreaseEncoded = nftManagerInterfaces.encodeFunctionData('decreaseLiquidity', [params]);
const collectEncoded = nftManagerInterfaces.encodeFunctionData('collect', [collectParams]);
//The unwrapWHBAR is only needed when removing liquidity that includes HBAR
const unwrapWHBAREncoded = nftManagerInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipientAddress]);
//Build encoded data for the multicall
const encodedData = nftManagerInterfaces.encodeFunctionData('multicall',
[[decreaseEncoded, collectEncoded, unwrapWHBAREncoded]]);
const encodedDataAsUint8Array = hexToUint8Array(encodedData.substring(2));
//Execute the contract call
const response = await new ContractExecuteTransaction()
.setContractId(nftManagerContractId)
.setGas(gasGwei)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
//Fetch the result
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const results = nftManagerInterfaces.decodeFunctionResult('multicall', result.bytes)[0];
const collectResult = nftManagerInterfaces.decodeFunctionResult('collect', results[1]);
//Retrieve the amounts removed for informative purposes
const removedAmount0 = BigNumber(collectResult.amount0);
const removedAmount1 = BigNumber(collectResult.amount1);
```
***
## Burning the NFT
After completely exiting a position, you may burn the NFT position if it is no longer needed. The following code demonstrates how to set a spender allowance for the NFT and include the burn function in the multicall.
An NFT allowance for the NFT Manager contract must be approved by the token holder to enable the contract to retrieve the NFT to burn it.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
```typescript theme={null}
//Updated code to include burning of the NFT token
//Construct encoded data for each function
//The unwrapWHBAR is needed when collecting the HBAR swap fees
//Optionally include 'collect' here to collect fees.
//Optionally include 'burn' to burn the NFT if all liquidity is removed.
const decreaseEncoded = nftManagerInterfaces.encodeFunctionData('decreaseLiquidity', [params]);
const collectEncoded = nftManagerInterfaces.encodeFunctionData('collect', [collectParams]);
const burnEncoded = nftManagerInterfaces.encodeFunctionData('burn', [tokenSN]);
//The unwrapWHBAR is only needed when removing liquidity that includes HBAR
const unwrapWHBAREncoded = nftManagerInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipientAddress]);
//Build encoded data for the multicall
const encodedData = nftManagerInterfaces.encodeFunctionData('multicall',
[[decreaseEncoded, collectEncoded, unwrapWHBAREncoded, burnEncoded]]);
const encodedDataAsUint8Array = hexToUint8Array(encodedData.substring(2));
//Give NFT spender allowance to NFT Manager contract
const nftId = new NftId(lpTokenId, tokenSN);
const approveResult = await new AccountAllowanceApproveTransaction()
.approveTokenNftAllowance(nftId, ownerId, nftManagerContractId)
.execute(client);
const allowanceReceipt = await approveResult.getReceipt(client);
console.log(`NFT allowance status: ${allowanceReceipt.status}`);
//Execute the contract call
const response = await new ContractExecuteTransaction()
.setContractId(nftManagerContractId)
.setGas(gasGwei)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
```
## Next steps
Collect swap fees without removing liquidity.
Add liquidity back to the position.
List positions and fees for an account.
# Fetch all pools (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/fetch-all-pools
Retrieve every SaucerSwap V2 concentrated liquidity pool with fee tier, tick, and liquidity data from the SaucerSwap REST API, with response schemas.
SaucerSwap offers a public [REST API](/api-reference/overview) endpoint to retrieve all liquidity pools, accompanied by useful metadata for each pool, including liquidity pool reserves, and their associated tokens. Use the following URL options to access the data.
The endpoint is `GET /v2/pools` on `https://api.saucerswap.finance` (mainnet) or `https://test-api.saucerswap.finance` (testnet). Requests require an API key; see [Authentication](/api-reference/authentication).
For SaucerSwap V1 liquidity pools, see [Fetch all pools (V1)](/developers/v1/liquidity/fetch-all-pools).
## Data JSON schema
```typescript theme={null}
type ApiLiquidityPoolV2 = {
id: number;
contractId: string;
tokenA: ApiToken;
amountA: string; //total amount for tokenA, in smallest unit
tokenB: ApiToken;
amountB: string; //total amount for tokenB, in smallest unit
fee: number;
sqrtRatioX96: string;
tickCurrent: number;
liquidity: string;
}
type ApiToken = {
decimals: number
icon?: string
id: string
name: string
price: string
priceUsd: number
symbol: string
dueDiligenceComplete: boolean
isFeeOnTransferToken: boolean
timestampSecondsLastListingChange: number
description: string | null
website: string | null
twitterHandle: string | null
sentinelReport: string | null
}
```
## Code overview
*No gas cost — read-only call.*
```typescript theme={null}
const url = 'https://api.saucerswap.finance/v2/pools/';
const response = await axios.get(url);
const pools = response.data;
for (const pool of pools as ApiLiquidityPoolV2[] ) {
const symbolA = pool.tokenA.symbol;
const symbolB = pool.tokenB.symbol;
const feeTier = pool.fee / 10_000.0;
const currTick = pool.tickCurrent;
const liquidity = pool.liquidity;
let output = '';
output += `Pool id: ${pool.id}`;
output += ` - ${symbolA}/${symbolB} @ ${feeTier}%`;
output += ` - Current tick: ${currTick}`;
output += `, Liquidity: ${liquidity}`;
console.log(output);
}
```
## Next steps
Read the live price ratio for one pool.
The V1 equivalent with reserve amounts.
Get an API key for the REST API.
# Fetch pool token ratio (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/fetch-pool-token-ratio
Read the current token price ratio of a SaucerSwap V2 pool with slot0 and the Uniswap V3 SDK to size both token amounts of a new liquidity position.
## Code overview
The code below demonstrates one of the methods for retrieving the current price ratio of two tokens of an existing liquidity pool, which is needed to calculate the precise amounts required for each token when establishing a new liquidity position. The token ratio allows you to calculate the amount needed for the other token.
*No gas cost — read-only call.*
Hedera's EVM chain ID can be retrieved from [https://chainlist.org](https://chainlist.org/?testnets=true\&search=Hedera).
The pool address, token addresses, token decimal places, and the fee tier can be retrieved from SaucerSwap's REST API. Refer to [Fetch all pools (V2)](/developers/v2/liquidity/fetch-all-pools) for details.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Uniswap V3 SDK](https://docs.uniswap.org/sdk/v3/overview)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as uniswap_sdk from '@uniswap/v3-sdk';
import * as uniswap_core from '@uniswap/sdk-core';
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load the ABI data containing Pool's liquidity() and slot0()
const abiInterfaces = new ethers.Interface(abi);
//construct the pool contract
const poolContract = new ethers.Contract(poolEvmAddress, abiInterfaces.fragments, provider);
//construct the tokens
const token0 = new uniswap_core.Token(hederaChainId, token0Address, token0Decimals);
const token1 = new uniswap_core.Token(hederaChainId, token1Address, token1Decimals);
//get current slot0 and liquidity data from JSON-RPC
const [slot0, liquidity] = await Promise.all([
poolContract.slot0(),
poolContract.liquidity()
]);
//construct the pool using the latest on-chain data
const pool = new uniswap_sdk.Pool(
token0, token1,
feeTierBip, slot0.sqrtPriceX96.toString(),
liquidity.toString(), Number(slot0.tick)
);
// Get the price of token0 in terms of token1:
const priceOfToken0InToken1 = pool.token0Price.toFixed(token1Decimals);
// Get the price of token1 in terms of token0:
const priceOfToken1InToken0 = pool.token1Price.toFixed(token0Decimals);
console.log(`Current price: ${priceOfToken1InToken0} Token0 per Token1`);
console.log(`Current price: ${priceOfToken0InToken1} Token1 per Token0`);
```
## Next steps
Mint a position using the computed amounts.
Get pool addresses, tokens, and fee tiers.
# Get user positions (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/get-user-positions
List all SaucerSwap V2 liquidity positions for a Hedera account from the SaucerSwap REST API, including liquidity, tick range, and fees earned data.
SaucerSwap offers a public [REST API](/api-reference/overview) endpoint to retrieve all positions for a user, accompanied by useful metadata for each position, including liquidity and fees earned, and their associated tokens. Use the following URL options to access the data.
The endpoint is `GET /v2/nfts/{accountId}/positions` on `https://api.saucerswap.finance` (mainnet) or `https://test-api.saucerswap.finance` (testnet). Requests require an API key; see [Authentication](/api-reference/authentication).
## Data JSON schema
```typescript theme={null}
type ApiNftPositionV2 = {
tokenSN: number
accountId: string
token0: ApiToken | undefined
token1: ApiToken | undefined
fee: number
tickLower: number
tickUpper: number
liquidity: number
feeGrowthInside0LastX128: number
feeGrowthInside1LastX128: number
tokensOwed0: number
tokensOwed1: number
createdAt: number
updatedAt: number
lastSyncedAt: number
deleted: boolean
}
type ApiToken = {
decimals: number
icon?: string
id: string
name: string
price: string
priceUsd: number
symbol: string
dueDiligenceComplete: boolean
isFeeOnTransferToken: boolean
timestampSecondsLastListingChange: number
description: string | null
website: string | null
twitterHandle: string | null
sentinelReport: string | null
}
```
## Code overview
*No gas cost — read-only call.*
```typescript theme={null}
const accountId = '0.0.1234';
const url = `https://api.saucerswap.finance/v2/nfts/${accountId}/positions`;
const response = await axios.get(url);
const positions = response.data;
for (const position of positions as ApiNftPositionV2[] ) {
const symbol0 = position.token0?.symbol;
const symbol1 = position.token1?.symbol;
const feeTier = position.fee / 10_000.0;
const tickLower = position.tickLower;
const tickUpper = position.tickUpper;
let output = '';
output += `NFT SN: ${position.tokenSN}`;
output += ` - ${symbol0}/${symbol1} @ ${feeTier}%`;
output += ` - Tick range: ${tickLower} to ${tickUpper}`;
console.log(output);
}
```
## Next steps
Collect the fees a position has earned.
Get an API key for the REST API.
# Increasing liquidity (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/increasing-liquidity
Add more liquidity to an existing SaucerSwap V2 position with increaseLiquidity, including slippage-safe amounts computed with the Uniswap V3 SDK.
Contract ID: [SaucerSwapV2NonfungiblePositionManager](https://hashscan.io/mainnet/contract/0.0.4053945)
See [Liquidity position fee](/developers/v2/liquidity/liquidity-position-fee) for an example of how to obtain the current fee, payable in HBAR, for minting a new liquidity position or adding more liquidity to an existing one.
See [New liquidity position](/developers/v2/liquidity/new-liquidity-position) for creating a new liquidity position.
When working with HBAR, use the [Wrapped HBAR token ID](https://hashscan.io/mainnet/token/0.0.1456986) and include the HBAR amount in the setPayableAmount() method for the ContractExecuteTransaction call.
***
Function name: `increaseLiquidity`
Recommended gas limit: 330,000
| Struct Parameter Name | Description |
| ------------------------ | --------------------------------------------------------------------- |
| *uint256 tokenSN* | The serial number of the token for which liquidity is being increased |
| *uint256 amount0Desired* | The maximum amount for the first token in its smallest unit |
| *uint256 amount1Desired* | The maximum amount for the second token in its smallest unit |
| *uint256 amount0Min* | The minimum amount for the first token in its smallest unit |
| *uint256 amount1Min* | The minimum amount for the second token in its smallest unit |
| *uint deadline* | Deadline in Unix seconds |
```solidity INonfungiblePositionManager.sol theme={null}
struct IncreaseLiquidityParams {
uint256 tokenSN;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender`
/// @param params tokenSN The serial number of the token for which liquidity is being increased,
/// amount0Desired The desired amount of token0 to be spent,
/// amount1Desired The desired amount of token1 to be spent,
/// amount0Min The minimum amount of token0 to spend, which serves as a slippage check,
/// amount1Min The minimum amount of token1 to spend, which serves as a slippage check,
/// deadline The time by which the transaction must be included to effect the change
/// @return liquidity The new liquidity amount as a result of the increase
/// @return amount0 The amount of token0 to acheive resulting liquidity
/// @return amount1 The amount of token1 to acheive resulting liquidity
function increaseLiquidity(IncreaseLiquidityParams calldata params)
external
payable
returns (
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
```
```solidity NonfungiblePositionManager.sol theme={null}
/// @inheritdoc INonfungiblePositionManager
function increaseLiquidity(IncreaseLiquidityParams calldata params)
external
payable
override
checkDeadline(params.deadline)
returns (
uint128 liquidity,
uint256 amount0,
uint256 amount1
)
{
Position storage position = _positions[params.tokenSN];
PoolAddress.PoolKey memory poolKey = _poolIdToPoolKey[position.poolId];
IUniswapV3Pool pool;
(liquidity, amount0, amount1, pool) = addLiquidity(
AddLiquidityParams({
token0: poolKey.token0,
token1: poolKey.token1,
fee: poolKey.fee,
tickLower: position.tickLower,
tickUpper: position.tickUpper,
amount0Desired: params.amount0Desired,
amount1Desired: params.amount1Desired,
amount0Min: params.amount0Min,
amount1Min: params.amount1Min,
recipient: address(this)
})
);
bytes32 positionKey = PositionKey.compute(address(this), position.tickLower, position.tickUpper);
// this is now updated to the current transaction
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(positionKey);
position.tokensOwed0 += uint128(
FullMath.mulDiv(
feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
position.tokensOwed1 += uint128(
FullMath.mulDiv(
feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
position.liquidity += liquidity;
emit IncreaseLiquidity(params.tokenSN, liquidity, amount0, amount1);
}
```
## Code overview
The following code demonstrates how to add more liquidity to an existing position.
See [Fetch pool token ratio](/developers/v2/liquidity/fetch-pool-token-ratio) for an example of how to retrieve the latest data and construct the Pool object using the Uniswap SDK library.
See [Fetch all pools](/developers/v2/liquidity/fetch-all-pools) to retrieve the pool address, token pairs, fee tier, token IDs and decimal places for the target pool of interest.
The `refundETH` function uses HBAR, but its name is derived from Uniswap on Ethereum. The name was retained to simplify integration for developers familiar with Uniswap tools. It is used to refund any excess HBAR when setting up a new liquidity position.
Hedera's EVM chain ID can be retrieved from [https://chainlist.org](https://chainlist.org/?testnets=true\&search=Hedera).
The following code is intended for guidance purposes and does not include checks and safeguards.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Uniswap V3 SDK](https://docs.uniswap.org/sdk/v3/overview)
* [Fetch all pools](/developers/v2/liquidity/fetch-all-pools)
* [Fetch pool token ratio](/developers/v2/liquidity/fetch-pool-token-ratio)
* [Liquidity position fee](/developers/v2/liquidity/liquidity-position-fee)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import { Pool, Position, nearestUsableTick, priceToClosestTick } from '@uniswap/v3-sdk';
import { Fraction, Percent, Token, Price } from '@uniswap/sdk-core';
import { ContractExecuteTransaction } from '@hashgraph/sdk';
//Client pre-checks:
// - Router contract has spender allowance for the input HTS tokens
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//Load the ABI data for UniswapV3Pool
const poolInterfaces = new ethers.Interface(poolAbi);
//Load the ABI data for NonfungiblePositionManager
const nftManagerInterfaces = new ethers.Interface(nftManagerAbi);
//Construct the pool contract
const poolContract = new ethers.Contract(poolEvmAddress,
poolInterfaces.fragments, provider);
//Construct the NFT Manager contract
const nftManagerContract = new ethers.Contract(nftManagerEvmAddress,
nftManagerInterfaces.fragments, provider);
//Get current position data for the given NFT token serial number
const lp = await nftManagerContract.positions(tokenSN);
const feeTier = Number(lp.fee);
const tickLower = Number(lp.tickLower);
const tickUpper = Number(lp.tickUpper);
//Construct the tokens
//For Hedera chain id, see https://chainlist.org/?testnets=true&search=Hedera
const token0 = new Token(hederaChainId, token0Address, token0Decimals);
const token1 = new Token(hederaChainId, token1Address, token1Decimals);
//Get current slot0 and liquidity data from the pool
const [slot0, poolLiquidity] = await Promise.all([
poolContract.slot0(),
poolContract.liquidity()
]);
//Construct the pool using the latest data
const pool = new Pool(
token0, token1,
feeTier, slot0.sqrtPriceX96.toString(),
poolLiquidity.toString(), Number(slot0.tick)
);
//Get amount0 in token's smallest unit from user's input (input0)
const amount0 = BigNumber(input0).times(Math.pow(10, token0Decimals)).toFixed(0);
//Construct a position using the SDK
// - use fromAmount0() if amount0 needs to be exact
// - use fromAmount1() if amount1 needs to be exact
// - use fromAmounts() if amount0 and amount1 do not need to be exact
const position = Position.fromAmount0({
pool: pool,
tickUpper: tickUpper,
tickLower: tickLower,
amount0: amount0,
useFullPrecision: true
});
//Get the mint amounts based on what the router will give us
const amount0Mint = position.mintAmounts.amount0.toString();
const amount1Mint = position.mintAmounts.amount1.toString();
//Calculate the minimum amounts factoring in the price slippage % and range
const priceSlippagePercent = new Percent(1, 100); //1% price slippage
const minAmounts = position.mintAmountsWithSlippage(priceSlippagePercent);
const amount0Min = minAmounts.amount0.toString();
const amount1Min = minAmounts.amount1.toString();
//IncreaseLiquidityParams struct
const params = {
tokenSN: tokenSN,
amount0Desired: amount0Mint, //in smallest unit
amount1Desired: amount1Mint, //in smallest unit
amount0Min: amount0Min, //in smallest unit
amount1Min: amount1Min, //in smallest unit
deadline: deadline, //Unix seconds
};
//Construct encoded data for each function
const increaseLiquidityEncoded = nftManagerInterfaces.encodeFunctionData('increaseLiquidity', [params]);
const refundEthEncoded = nftManagerInterfaces.encodeFunctionData('refundETH');
//Build encoded data for multicall
const encodedData = nftManagerInterfaces.encodeFunctionData('multicall',
[[increaseLiquidityEncoded, refundEthEncoded]]);
const encodedDataAsUint8Array = hexToUint8Array(encodedData.substring(2));
//Give spender allowance for both tokens to the NFT Manager contract if needed.
//To avoid having to ask for allowance each time, request max allowance.
//If the token is HBAR, no spender allowance is required.
//Use Hedera's REST API to get current allowances for an account.
await yourGrantSpenderAllowanceFunc(/* ... */);
//Execute the contract call
const response = await new ContractExecuteTransaction()
.setPayableAmount(inputHbar) //mint fee + HBAR token amount if used
.setContractId(nftManagerContractId)
.setGas(gasGwei)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
//Fetch the result
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const results = nftManagerInterfaces.decodeFunctionResult('multicall', result.bytes)[0];
const mintResult = nftManagerInterfaces.decodeFunctionResult('increaseLiquidity', results[0]);
//Retrieve the newly minted liquidity and amounts for informative purposes
const liquidity = BigNumber(mintResult.liquidity);
const amount0 = BigNumber(mintResult.amount0);
const amount1 = BigNumber(mintResult.amount1);
```
## Next steps
Remove liquidity or exit the position.
Collect swap fees earned by the position.
List positions and fees for an account.
# Liquidity position fee (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/liquidity-position-fee
Fetch the current SaucerSwap V2 mint fee from the factory contract in tinycent and convert it to HBAR using the mirror node network exchange rate API.
The following code demonstrates how to retrieve the fee for minting a new liquidity position or adding to an existing position, with the fees expressed in HBAR, using a combination of JSON-RPC and REST API calls.
The `mintFee()` function will return the current fee expressed in **Tinycent** (US).
*No gas cost — read-only call.*
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing Factory's mintFee() function
const interfaces = new ethers.Interface(abi);
//get pool creation fee in tinycent
const factoryContract = new ethers.Contract(factoryV2EvmAddress, interfaces.fragments, provider);
const result = await factoryContract.mintFee();
const tinycent = Number(result); //amount in tinycent (US)
//get the current exchange rate via REST API
const url = `${mirrorNodeBaseUrl}/api/v1/network/exchangerate`;
const response = await axios.get(url);
const currentRate = response.data.current_rate;
const centEquivalent = Number(currentRate.cent_equivalent);
const hbarEquivalent = Number(currentRate.hbar_equivalent);
const centToHbarRatio = centEquivalent/hbarEquivalent;
//calculate the fee in terms of HBAR
const tinybar = BigNumber(tinycent / centToHbarRatio).decimalPlaces(0);
const mintFeeInHbar = Hbar.from(tinybar, HbarUnit.Tinybar);
console.log(`New liquidity position fee: ${mintFeeInHbar.toString(HbarUnit.Hbar)}`);
```
## Next steps
Use the fee when minting a position.
Factory and position manager IDs for mainnet and testnet.
# New liquidity position (V2)
Source: https://docs.saucerswap.finance/developers/v2/liquidity/new-liquidity-position
Mint a new SaucerSwap V2 concentrated liquidity position NFT with the mint multicall, including tick range selection built with the Uniswap V3 SDK.
Contract ID: [SaucerSwapV2NonfungiblePositionManager](https://hashscan.io/mainnet/contract/0.0.4053945)
See [Liquidity position fee](/developers/v2/liquidity/liquidity-position-fee) for an example of how to obtain the current fee, payable in HBAR, for minting a new liquidity position or adding more liquidity to an existing one.
Ensure the recipient has associated the [SaucerSwapV2 LP NFT ID](https://hashscan.io/mainnet/token/0.0.4054027) representing the liquidity positions before minting a new position.
When working with HBAR, use the [Wrapped HBAR token ID](https://hashscan.io/mainnet/token/0.0.1456986) and include the HBAR amount in the setPayableAmount() method for the ContractExecuteTransaction call.
***
Function name: `mint`
Recommended gas limit: 900,000
| Struct Parameter Name | Description |
| ------------------------ | ---------------------------------------------------------------- |
| *address token0* | EVM address of the first token |
| *address token1* | EVM address of the second token |
| *uint24 fee* | Pool fee tier in hundredths of a bip (500, 1500, 3000, or 10000) |
| *int24 tickLower* | The lower end of the tick range for the position |
| *int24 tickUpper* | The upper end of the tick range for the position |
| *uint256 amount0Desired* | The maximum amount for the first token in its smallest unit |
| *uint256 amount1Desired* | The maximum amount for the second token in its smallest unit |
| *uint256 amount0Min* | The minimum amount for the first token in its smallest unit |
| *uint256 amount1Min* | The minimum amount for the second token in its smallest unit |
| *address recipient* | EVM address to receive the new liquidity position. |
| *uint deadline* | Deadline in Unix seconds |
```solidity INonfungiblePositionManager.sol theme={null}
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
/// @notice Creates a new position wrapped in a NFT
/// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized
/// a method does not exist, i.e. the pool is assumed to be initialized.
/// @param params The params necessary to mint a position, encoded as `MintParams` in calldata
/// @return tokenSN The token serial number of the new position
/// @return liquidity The amount of liquidity for this position
/// @return amount0 The amount of token0
/// @return amount1 The amount of token1
function mint(MintParams calldata params)
external
payable
returns (
uint256 tokenSN,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
```
```solidity NonfungiblePositionManager.sol theme={null}
/// @inheritdoc INonfungiblePositionManager
function mint(MintParams calldata params)
external
payable
override
checkDeadline(params.deadline)
returns (
uint256 tokenSN,
uint128 liquidity,
uint256 amount0,
uint256 amount1
)
{
IUniswapV3Pool pool;
(liquidity, amount0, amount1, pool) = addLiquidity(
AddLiquidityParams({
token0: params.token0,
token1: params.token1,
fee: params.fee,
recipient: address(this),
tickLower: params.tickLower,
tickUpper: params.tickUpper,
amount0Desired: params.amount0Desired,
amount1Desired: params.amount1Desired,
amount0Min: params.amount0Min,
amount1Min: params.amount1Min
})
);
tokenSN = _nextSN++;
{ // stack too deep
bytes memory metadataBytes = abi.encodePacked(baseUrl, HexStrings.toHexStringNoPrefix(tokenSN, 7)); // 14 digits in the url
require(metadataBytes.length <= 100, 'metadata too long');
bytes[] memory array = new bytes[](1);
array[0] = metadataBytes;
NFTHelper.safeMintTokens(nft, 0, array);
IERC721(nft).transferFrom(address(this), params.recipient, tokenSN);
}
bytes32 positionKey = PositionKey.compute(address(this), params.tickLower, params.tickUpper);
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(positionKey);
// idempotent set
uint80 poolId = cachePoolKey(
address(pool),
PoolAddress.PoolKey({token0: params.token0, token1: params.token1, fee: params.fee})
);
_positions[tokenSN] = Position({
poolId: poolId,
tickLower: params.tickLower,
tickUpper: params.tickUpper,
liquidity: liquidity,
feeGrowthInside0LastX128: feeGrowthInside0LastX128,
feeGrowthInside1LastX128: feeGrowthInside1LastX128,
tokensOwed0: 0,
tokensOwed1: 0
});
emit IncreaseLiquidity(tokenSN, liquidity, amount0, amount1);
}
```
***
## Code overview
The following code demonstrates how to create a new liquidity position with a price range being +/- 5% from the current token price, and receive an NFT representing the position.
See [Fetch pool token ratio](/developers/v2/liquidity/fetch-pool-token-ratio) for an example of how to retrieve the latest data and construct the Pool object using the Uniswap SDK library.
See [Fetch all pools](/developers/v2/liquidity/fetch-all-pools) to retrieve the pool address, token pairs, fee tier, token IDs and decimal places for the target pool of interest.
The `refundETH` function operates in HBAR, but its name is derived from Uniswap on Ethereum. The name was retained to simplify integration for developers familiar with Uniswap tools. It is used to refund any excess HBAR when setting up a new liquidity position.
Hedera's EVM chain ID can be retrieved from [https://chainlist.org](https://chainlist.org/?testnets=true\&search=Hedera).
The following code is intended for guidance purposes, and does not include checks and safeguards.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Uniswap V3 SDK](https://docs.uniswap.org/sdk/v3/overview)
* [Fetch all pools](/developers/v2/liquidity/fetch-all-pools)
* [Fetch pool token ratio](/developers/v2/liquidity/fetch-pool-token-ratio)
* [Liquidity position fee](/developers/v2/liquidity/liquidity-position-fee)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import { Pool, Position, nearestUsableTick, priceToClosestTick } from '@uniswap/v3-sdk';
import { Fraction, Percent, Token, Price } from '@uniswap/sdk-core';
import { ContractExecuteTransaction } from '@hashgraph/sdk';
//Client pre-checks:
// - NFT token id is associated
// - Router contract has spender allowance for the input HTS tokens
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load the ABI data containing liquidity() and slot0()
const abiInterfaces = new ethers.Interface(abi);
//construct the pool contract
const poolContract = new ethers.Contract(poolEvmAddress,
abiInterfaces.fragments, provider);
//construct the tokens
//For Hedera chain id, see https://chainlist.org/?testnets=true&search=Hedera
const token0 = new Token(hederaChainId, token0Address, token0Decimals);
const token1 = new Token(hederaChainId, token1Address, token1Decimals);
//get current slot0 and liquidity data from JSON-RPC Relay
const [slot0, poolLiquidity] = await Promise.all([
poolContract.slot0(),
poolContract.liquidity()
]);
//construct the pool using the latest data
const pool = new Pool(
token0, token1,
feeTier, slot0.sqrtPriceX96.toString(),
poolLiquidity.toString(), Number(slot0.tick)
);
//Get current token0 price in terms of token1
const currentPrice = pool.token0Price;
//Get amount0 in token's smallest unit
const amount0 = BigNumber(input0).times(Math.pow(10, token0Decimals)).toFixed(0);
//get the upper price (+5% from current in this example)
const multiplier = new Fraction(105, 100); //1.05 (105%)
const priceFraction = currentPrice.asFraction.multiply(multiplier);
const upperPrice = new Price(
currentPrice.baseCurrency,
currentPrice.quoteCurrency,
priceFraction.denominator,
priceFraction.numerator
);
//get the upper tick based on the target upper price
const tickUpperApprox = priceToClosestTick(upperPrice);
//calculate the delta between the current tick and the upper
const tickDelta = tickUpperApprox - pool.tickCurrent;
//get the lower tick based on the delta from current tick
const tickLowerApprox = pool.tickCurrent - tickDelta;
//get the nearest valid tick values
const tickUpper = nearestUsableTick(tickUpperApprox, pool.tickSpacing);
const tickLower = nearestUsableTick(tickLowerApprox, pool.tickSpacing);
//construct a position using the SDK
// - use fromAmount0() if amount0 needs to be exact
// - use fromAmount1() if amount1 needs to be exact
// - use fromAmounts() if amount0 and amount1 do not need to be exact
const position = Position.fromAmount0({
pool: pool,
tickUpper: tickUpper,
tickLower: tickLower,
amount0: amount0,
useFullPrecision: true
});
//get the mint amounts based on what the router will give us
const amount0Mint = position.mintAmounts.amount0.toString();
const amount1Mint = position.mintAmounts.amount1.toString();
//calculate the minimum amounts factoring in the price slippage % and range
const priceSlippagePercent = new Percent(1, 100); //1% price slippage
const minAmounts = position.mintAmountsWithSlippage(priceSlippagePercent);
const amount0Min = minAmounts.amount0.toString();
const amount1Min = minAmounts.amount1.toString();
//MintParams struct
const params = {
token0: token0Address, //0x..
token1: token1Address, //0x..
fee: feeTier, //500, 1500, 3000 or 10000
tickLower: tickLower, //lower tick of the range
tickUpper: tickUpper, //upper tick of the range
amount0Desired: amount0Mint, //in smallest unit
amount1Desired: amount1Mint, //in smallest unit
amount0Min: amount0Min, //in smallest unit
amount1Min: amount1Min, //in smallest unit
recipient: recipientAddress, //0x..
deadline: deadline, //Unix seconds
};
//construct encoded data for each function
const mintEncoded = abiInterfaces.encodeFunctionData('mint', [params]);
const refundEthEncoded = abiInterfaces.encodeFunctionData('refundETH');
//build encoded data for multicall
const encodedData = abiInterfaces.encodeFunctionData('multicall', [[mintEncoded, refundEthEncoded]]);
const encodedDataAsUint8Array = hexToUint8Array(encodedData.substring(2));
//Give spender allowance for both tokens to the NFT Manager contract if needed.
//To avoid having to ask for allowance each time, request max allowance.
//If the token is HBAR, no spender allowance is required.
//Use Hedera's REST API to get current allowances for an account.
await yourGrantSpenderAllowanceFunc(/* ... */);
//Execute the paid contract call
const response = await new ContractExecuteTransaction()
.setPayableAmount(inputHbar) //mint fee + HBAR token amount if used
.setContractId(nftManagerContractId)
.setGas(gasGwei)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
//Fetch the result
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const results = abiInterfaces.decodeFunctionResult('multicall', result.bytes)[0];
const mintResult = abiInterfaces.decodeFunctionResult('mint', results[0]);
//Retrieve the NFT token SN, liquidity and amounts for informative purposes
const tokenSN = Number(mintResult.tokenSN);
const liquidity = BigNumber(mintResult.liquidity);
const amount0 = BigNumber(mintResult.amount0);
const amount1 = BigNumber(mintResult.amount1);
```
## Next steps
Add more liquidity to the position later.
Size both token amounts from the current price.
Fetch the HBAR mint fee before calling mint.
# Swap HBAR for tokens (V2)
Source: https://docs.saucerswap.finance/developers/v2/swap/swap-hbar-for-tokens
Swap HBAR for HTS tokens through the SaucerSwap V2 SwapRouter using exactInput and exactOutput multicalls with refundETH, with TypeScript code examples.
Below are two methods available to swap HBAR for tokens:
* [Swap exact HBAR for tokens](/developers/v2/swap/swap-hbar-for-tokens#swap-exact-hbar-for-tokens)
* [Swap HBAR for exact tokens](/developers/v2/swap/swap-hbar-for-tokens#swap-hbar-for-exact-tokens)
Contract ID: [SaucerSwapV2SwapRouter](https://hashscan.io/mainnet/contract/0.0.3949434)
Consider the token's decimal places when determining the output amount.
The output values should be in the token's smallest unit. For the SAUCE token, which has 6 decimal places, an input of 123.45 SAUCE should be entered as 123450000 (123.45 multiplied by 10^6).
Ensure that the "**to**" account has the output token id associated prior to executing the swap. Failure to do so will result in a `TOKEN_NOT_ASSOCIATED_TO_ACCOUNT` error.
When providing HBAR in the path array, use the Wrapped HBAR token id ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)).
## Swap exact HBAR for tokens
Swap an exact amount of HBAR for a minimum token amount
Solidity function name: `exactInput`
| Struct Parameter Name | Description |
| --------------------- | ----------------------------------------------------------- |
| *bytes path* | A bytes array representing a route path including fees data |
| *recipient* | EVM address of the token recipient |
| *deadline* | Deadline in Unix seconds |
| *amountIn* | The exact input token amount in its smallest unit |
| *amountOutMinimum* | The minimum token amount to receive in its smallest unit |
```solidity ISwapRouter.sol theme={null}
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
```
```solidity SwapRouter.sol theme={null}
/// @inheritdoc ISwapRouter
function exactInput(ExactInputParams memory params)
external
payable
override
checkDeadline(params.deadline)
returns (uint256 amountOut)
{
address payer = msg.sender; // msg.sender pays for the first hop
while (true) {
bool hasMultiplePools = params.path.hasMultiplePools();
// the outputs of prior swaps become the inputs to subsequent ones
params.amountIn = exactInputInternal(
params.amountIn,
hasMultiplePools ? address(this) : params.recipient, // for intermediate swaps, this contract custodies
0,
SwapCallbackData({
path: params.path.getFirstPool(), // only the first pool in the path is necessary
payer: payer
})
);
// decide whether to continue or terminate
if (hasMultiplePools) {
payer = address(this); // at this point, the caller has paid
params.path = params.path.skipToken();
} else {
amountOut = params.amountIn;
break;
}
}
require(amountOut >= params.amountOutMinimum, 'Too little received');
}
```
Set the minimum output token amount (`amountOutMinimum`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
It is recommended to include `refundETH` in the multicall in case excess HBAR was sent to the contract.
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, 0x0001F4 (500) for a 0.05% fee.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
*Note: The Hedera JavaScript SDK currently does not support passing complex contract function parameters. Instead, use Ethers.js or Web3.js to obtain the encoded function data and pass that data as a function parameter.*
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import {
ContractExecuteTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
//load ABI data containing SwapRouter, PeripheryPayments and Multicall functions
const abiInterfaces = new ethers.Interface(abi);
//ExactInputParams
const params = {
path: routeDataWithFee, //'0x...'
recipient: recipientAddress, //'0x...' - user's recipient address
deadline: deadline, //Unix seconds
amountIn: inputTinybar, //in Tinybar
amountOutMinimum: outputAmountMin//in token's smallest unit
};
//encode each function individually
const swapEncoded = abiInterfaces.encodeFunctionData('exactInput', [params]);
const refundHBAREncoded = abiInterfaces.encodeFunctionData('refundETH');
//multi-call parameter: bytes[]
const multiCallParam = [swapEncoded, refundHBAREncoded];
//get encoded data for the multicall involving both functions
const encodedData = abiInterfaces.encodeFunctionData('multicall', [multiCallParam]);
//get encoded data as Uint8Array
const encodedDataAsUint8Array = hexToUint8Array(encodedData);
const response = await new ContractExecuteTransaction()
.setPayableAmount(Hbar.from(inputTinybar, HbarUnit.Tinybar))
.setContractId(swapRouterContractId)
.setGas(gasLim)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint256']);
const amountOut = values[0]; //uint256 amountOut
```
***
## Swap HBAR for exact tokens
Swap a maximum amount of HBAR to receive an exact tokens amount.
Solidity function name: `exactOutput`
| Struct Parameter Name | Description |
| --------------------- | ------------------------------------------------------------- |
| *bytes path* | A bytes array representing a route path including fees data |
| *recipient* | EVM address of the token recipient |
| *deadline* | Deadline in Unix seconds |
| *amountOut* | The exact output token amount to receive in its smallest unit |
| *amountInMaximum* | The maximum HBAR amount to spend, in tinybar |
```solidity ISwapRouter.sol theme={null}
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
```
```solidity SwapRouter.sol theme={null}
/// @inheritdoc ISwapRouter
function exactOutput(ExactOutputParams calldata params)
external
payable
override
checkDeadline(params.deadline)
returns (uint256 amountIn)
{
// it's okay that the payer is fixed to msg.sender here, as they're only paying for the "final" exact output
// swap, which happens first, and subsequent swaps are paid for within nested callback frames
exactOutputInternal(
params.amountOut,
params.recipient,
0,
SwapCallbackData({path: params.path, payer: msg.sender})
);
amountIn = amountInCached;
require(amountIn <= params.amountInMaximum, 'Too much requested');
amountInCached = DEFAULT_AMOUNT_IN_CACHED;
}
```
Ensure that the `refundETH` is included in the multicall so that any excess payable HBAR amount, up to the maximum amount, is refunded to the sender.
Set the maximum input token amount (`amountInMaximum`) with caution.
A low maximum might lead to a swap failure if the required liquidity surpasses this limit or due to rapid price movements. Conversely, setting it too high can expose you to significant slippage, potentially leading to a financial loss as you might spend far more tokens than expected.
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], but **reversed** (i.e. the first token in the array should be output token), with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, 0x000BB8 (3000) for a 0.30% fee.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import {
ContractExecuteTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
//load ABI data containing SwapRouter, PeripheryPayments and Multicall functions
const abiInterfaces = new ethers.Interface(abi);
//ExactOutputParams
const params = {
path: routeDataWithFee, //'0x...' (reversed route path)
recipient: recipientAddress, //'0x...' - user's recipient address
deadline: deadline, //Unix seconds
amountOut: outputAmount, //in token's smallest unit
amountInMaximum: inputTinybarMax //in Tinybar
};
//encode each function individually
const swapEncoded = abiInterfaces.encodeFunctionData('exactOutput', [params]);
const refundHBAREncoded = abiInterfaces.encodeFunctionData('refundETH');
//multi-call parameter: bytes[]
const multiCallParam = [swapEncoded, refundHBAREncoded];
//get encoded data for the multicall involving both functions
const encodedData = abiInterfaces.encodeFunctionData('multicall', [multiCallParam]);
//get encoded data as Uint8Array
const encodedDataAsUint8Array = hexToUint8Array(encodedData);
const response = await new ContractExecuteTransaction()
.setPayableAmount(Hbar.from(inputTinybarMax, HbarUnit.Tinybar))
.setContractId(swapRouterContractId)
.setGas(gasLim)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint256']);
const amountIn = values[0]; //uint256 amountIn
```
## Next steps
Fetch expected amounts from QuoterV2 first.
Run the same flow in the opposite direction.
Monitor executed swaps in near real time.
# Swap quote (V2)
Source: https://docs.saucerswap.finance/developers/v2/swap/swap-quote
Get SaucerSwap V2 swap quotes from the QuoterV2 contract with quoteExactInput and quoteExactOutput over JSON-RPC or the mirror node, at no gas cost.
Below are the two methods to get a quote for a swap from a given route:
* [Get output quote from exact input amount](/developers/v2/swap/swap-quote#get-output-quote-from-exact-input-amount)
* [Get input quote from exact output amount](/developers/v2/swap/swap-quote#get-input-quote-from-exact-output-amount)
Contract ID: [SaucerSwapV2QuoterV2](https://hashscan.io/mainnet/contract/0.0.3949424)
When providing HBAR in the path array, use the wrapped HBAR token ID ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)).
For production environments, it's highly recommended to use a paid Mirror Node provider for commercial and high-traffic purposes. While Hedera's public mirror node offers free REST API and JSON API endpoints, they have global rate limits. These are best suited for development or low rate usage scenarios.
## Get output quote from exact input amount
Get the output amount from a given exact input amount and a swap route.
Function name: `quoteExactInput`
No gas cost — read-only call.
| Parameter Name | Description |
| ------------------ | ------------------------------------------- |
| *bytes path* | Route path containing pair swap fees |
| *uint256 amountIn* | Exact input amount in token's smallest unit |
```solidity IQuoterV2.sol theme={null}
/// @notice Returns the amount out received for a given exact input swap without executing the swap
/// @param path The path of the swap, i.e. each token pair and the pool fee
/// @param amountIn The amount of the first token to swap
/// @return amountOut The amount of the last token that would be received
/// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
/// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactInput(bytes memory path, uint256 amountIn)
external
returns (
uint256 amountOut,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
```
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, `0x0001F4` for a 0.05% fee.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterEvmAddress = `0x${ContractId.fromString(quoterContractId).toSolidityAddress()}`;
//swap path
const pathData:string[] = [];
pathData.push(inputToken.toSolidityAddress());
pathData.push(feeHexStr);
pathData.push(outputToken.toSolidityAddress());
const encodedPathData = hexToUint8Array(pathData.join(''));
const data = abiInterfaces.encodeFunctionData('quoteExactInput', [
encodedPathData,
inputAmountInSmallestUnit.toString()
]);
//Send a call to the JSON-RPC provider directly
const result = await provider.call({
to: quoterEvmAddress,
data: data,
});
const decoded = abiInterfaces.decodeFunctionResult('quoteExactInput', result);
const finalOutputAmount = decoded.amountOut; //in token's smallest unit
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterContract = ContractId.fromString(quoterContractId);
//swap path
const path:string[] = [];
path.push(inputToken.toSolidityAddress());
path.push(feeHexStr);
path.push(outputToken.toSolidityAddress());
//get encoded Uint8Array data for path hex
const encodedPathData = hexToUint8Array(path.join(''));
//quoteExactInput params
const params = [encodedPathData, inputAmountInSmallestUnit];
//Get encoded function data
const encodedData = abiInterfaces.encodeFunctionData(abiInterfaces.getFunction('quoteExactInput')!, params);
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/call`;
const data = {
'block': 'latest',
'data': encodedData,
'to': quoterContract.toSolidityAddress(),
};
const response = await axios.post(url, data, { headers: {'content-type': 'application/json'} });
const result = abiInterfaces.decodeFunctionResult('quoteExactInput', response.data.result);
const finalAmountOut = result.amountOut; //in token's smallest unit
```
***
## Get input quote from exact output amount
Get the input amount from a given exact output amount and a swap route.
Function name: `quoteExactOutput`
No gas cost — read-only call.
| Parameter Name | Description |
| ------------------- | ---------------------------------------------- |
| *bytes path* | Route path containing pair swap fees, reversed |
| *uint256 amountOut* | Exact output amount in token's smallest unit |
```solidity IQuoterV2.sol theme={null}
/// @notice Returns the amount in required for a given exact output swap without executing the swap
/// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order
/// @param amountOut The amount of the last token to receive
/// @return amountIn The amount of first token required to be paid
/// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
/// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactOutput(bytes memory path, uint256 amountOut)
external
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
struct QuoteExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint256 amount;
uint24 fee;
uint160 sqrtPriceLimitX96;
}
```
```solidity QuoterV2.sol theme={null}
function quoteExactOutput(bytes memory path, uint256 amountOut)
public
override
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
)
{
sqrtPriceX96AfterList = new uint160[](path.numPools());
initializedTicksCrossedList = new uint32[](path.numPools());
uint256 i = 0;
while (true) {
(address tokenOut, address tokenIn, uint24 fee) = path.decodeFirstPool();
// the inputs of prior swaps become the outputs of subsequent ones
(
uint256 _amountIn,
uint160 _sqrtPriceX96After,
uint32 _initializedTicksCrossed,
uint256 _gasEstimate
) = quoteExactOutputSingle(
QuoteExactOutputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
amount: amountOut,
fee: fee,
sqrtPriceLimitX96: 0
})
);
sqrtPriceX96AfterList[i] = _sqrtPriceX96After;
initializedTicksCrossedList[i] = _initializedTicksCrossed;
amountOut = _amountIn;
gasEstimate += _gasEstimate;
i++;
// decide whether to continue or terminate
if (path.hasMultiplePools()) {
path = path.skipToken();
} else {
return (amountOut, sqrtPriceX96AfterList, initializedTicksCrossedList, gasEstimate);
}
}
}
```
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], but **reversed** (i.e. the first token in the array should be output token), with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, `0x000BB8` for a 0.30% fee.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterEvmAddress = `0x${ContractId.fromString(quoterContractId).toSolidityAddress()}`;
//swap path
const pathData:string[] = [];
pathData.push(inputToken.toSolidityAddress());
pathData.push(feeHexStr);
pathData.push(outputToken.toSolidityAddress());
//reverse the path
pathData.reverse();
//get encoded Uint8Array data for path hex
const encodedPathData = hexToUint8Array(pathData.join(''));
const data = abiInterfaces.encodeFunctionData('quoteExactOutput', [
encodedPathData,
outputAmountInSmallestUnit
]);
//Send a call to the JSON-RPC provider directly
const result = await provider.call({
to: quoterEvmAddress,
data: data,
});
const decoded = abiInterfaces.decodeFunctionResult('quoteExactOutput', result);
const finalAmountIn = decoded.amountIn; //in token's smallest unit
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterContract = ContractId.fromString(quoterContractId);
const path:string[] = [];
path.push(inputToken.toSolidityAddress());
path.push(feeHexStr);
path.push(outputToken.toSolidityAddress());
//reverse the path
path.reverse();
//get encoded Uint8Array data for path hex
const encodedPathData = hexToUint8Array(path.join(''));
//quoteExactOutput params
const params = [encodedPathData, outputAmountInSmallestUnit];
//Get encoded function data
const encodedData = abiInterfaces.encodeFunctionData(abiInterfaces.getFunction('quoteExactOutput')!, params);
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/call`;
const data = {
'block': 'latest',
'data': encodedData,
'to': quoterContract.toSolidityAddress(),
};
const response = await axios.post(url, data, { headers: {'content-type': 'application/json'} });
const result = abiInterfaces.decodeFunctionResult('quoteExactOutput', response.data.result);
const finalAmountIn = result.amountIn; //in token's smallest unit
```
## Next steps
Execute the swap you just quoted.
Find pool fee tiers to build the quote path.
QuoterV2 and SwapRouter IDs for mainnet and testnet.
# Swap tokens for HBAR (V2)
Source: https://docs.saucerswap.finance/developers/v2/swap/swap-tokens-for-hbar
Swap HTS tokens for HBAR through the SaucerSwap V2 SwapRouter using exactInput and exactOutput with unwrapWHBAR multicalls and allowance pre-checks.
Below are two methods available to swap tokens for HBAR:
* [Swap exact tokens for HBAR](/developers/v2/swap/swap-tokens-for-hbar#swap-exact-tokens-for-hbar)
* [Swap tokens for exact HBAR](/developers/v2/swap/swap-tokens-for-hbar#swap-tokens-for-exact-hbar)
Contract ID: [SaucerSwapV2SwapRouter](https://hashscan.io/mainnet/contract/0.0.3949434)
Consider the token's decimal places when determining input and output values.
Input and output amounts passed to the solidity function should all be in the token's smallest unit. For the SAUCE token, which has 6 decimal places, an input of 123.45 SAUCE should be entered as 123450000 (123.45 multiplied by 10^6).
Granting a spender allowance to the router contract **is required** when the input token is not native HBAR for security reasons enforced at the native code layer. Ensure that the allowance amount is in token's smallest unit.
When providing HBAR in the path array, use the Wrapped HBAR token ID ([WHBAR](https://hashscan.io/mainnet/token/0.0.1456986)).
***
## Swap exact tokens for HBAR
Swap an exact amount of tokens for a minimum HBAR amount.
Solidity function name: `exactInput`
| Struct Parameter Name | Description |
| -------------------------- | ----------------------------------------------------------- |
| *bytes path* | A bytes array representing a route path including fees data |
| *address recipient* | EVM address of the token recipient |
| *uint256 deadline* | Deadline in Unix seconds |
| *uint256 amountIn* | The exact input token amount in its smallest unit |
| *uint256 amountOutMinimum* | The minimum token amount to receive in its smallest unit |
```solidity ISwapRouter.sol theme={null}
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
```
```solidity SwapRouter.sol theme={null}
/// @inheritdoc ISwapRouter
function exactInput(ExactInputParams memory params)
external
payable
override
checkDeadline(params.deadline)
returns (uint256 amountOut)
{
address payer = msg.sender; // msg.sender pays for the first hop
while (true) {
bool hasMultiplePools = params.path.hasMultiplePools();
// the outputs of prior swaps become the inputs to subsequent ones
params.amountIn = exactInputInternal(
params.amountIn,
hasMultiplePools ? address(this) : params.recipient, // for intermediate swaps, this contract custodies
0,
SwapCallbackData({
path: params.path.getFirstPool(), // only the first pool in the path is necessary
payer: payer
})
);
// decide whether to continue or terminate
if (hasMultiplePools) {
payer = address(this); // at this point, the caller has paid
params.path = params.path.skipToken();
} else {
amountOut = params.amountIn;
break;
}
}
require(amountOut >= params.amountOutMinimum, 'Too little received');
}
```
Set the minimum output token amount (`amountOutMinimum`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, 0x0001F4 for a 0.05% fee.
Include `unwrapWHBAR` function in your call to convert the Wrapped HBAR (WHBAR) output token back into the native HBAR cryptocurrency following the swap.
For the ExactInputParams **recipient**, use the SwapRouter contract address. This is required for unwrapWHBAR to function correctly. The unwrapped HBAR will then be sent to the user's recipient address.
When the output token is not HBAR, use the user's address as the **recipient** instead.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
*Note: The Hedera JavaScript SDK currently does not support passing complex contract function parameters. Instead, use Ethers.js or Web3.js to obtain the encoded function data and pass that data as a function parameter.*
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//import {..} from @hashgraph/sdk
//Client pre-checks:
// - Router contract has spender allowance for the input token
//load ABI data containing SwapRouter, PeripheryPayments and Multicall functions
const abiInterfaces = new ethers.Interface(abi);
//ExactInputParams
const params = {
path: routeDataWithFee, //'0x...'
recipient: swapRouterAddress, //'0x...' - use the SwapRouter id here for unwrapWHBAR to work
deadline: deadline, //Unix seconds
amountIn: inputAmount, //in token's smallest unit
amountOutMinimum: outputTinybarMin //in Tinybar
};
//encode each function individually
const swapEncoded = abiInterfaces.encodeFunctionData('exactInput', [params]);
//Provide the user's address to receive the unwrapped HBAR
const unwrapEncoded = abiInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipient]);
//multi-call parameter: bytes[]
const multiCallParam = [swapEncoded, unwrapEncoded];
//get encoded data for the multicall involving both functions
const encodedData = abiInterfaces.encodeFunctionData('multicall', [multiCallParam]);
//get encoded data as Uint8Array
const encodedDataAsUint8Array = hexToUint8Array(encodedData);
const response = await new ContractExecuteTransaction()
.setContractId(swapRouterContractId)
.setGas(gasLim)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint256']);
const amountOut = values[0]; //uint256 amountOut - Tinybar
```
***
## Swap tokens for exact HBAR
Swap a maximum amount of tokens to receive an exact HBAR amount.
Solidity function name: `exactOutput`
| Schema Parameter Name | Description |
| ------------------------- | ----------------------------------------------------------- |
| *bytes path* | A bytes array representing a route path including fees data |
| *address recipient* | EVM address for the token recipient |
| *uint256 deadline* | Deadline in Unix seconds |
| *uint256 amountOut* | The exact output amount to receive in its smallest unit |
| *uint256 amountInMaximum* | The maximum allowed input amount in its smallest unit |
```solidity ISwapRouter.sol theme={null}
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
```
```solidity SwapRouter.sol theme={null}
/// @inheritdoc ISwapRouter
function exactOutput(ExactOutputParams calldata params)
external
payable
override
checkDeadline(params.deadline)
returns (uint256 amountIn)
{
// it's okay that the payer is fixed to msg.sender here, as they're only paying for the "final" exact output
// swap, which happens first, and subsequent swaps are paid for within nested callback frames
exactOutputInternal(
params.amountOut,
params.recipient,
0,
SwapCallbackData({path: params.path, payer: msg.sender})
);
amountIn = amountInCached;
require(amountIn <= params.amountInMaximum, 'Too much requested');
amountInCached = DEFAULT_AMOUNT_IN_CACHED;
}
```
Set the maximum input token amount (`amountInMaximum`) with caution.
A low maximum might lead to a swap failure if the required liquidity surpasses this limit or due to rapid price movements. Conversely, setting it too high can expose you to significant slippage, potentially leading to a financial loss as you might spend far more tokens than expected.
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], but **reversed** (i.e. the first token in the array should be output token), with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, `0x000BB8 (3000)` for a 0.30% fee.
Include `unwrapWHBAR` function in your call to convert the Wrapped HBAR output token back into the native HBAR cryptocurrency following the swap.
For the ExactInputParams **recipient**, use the SwapRouter contract address. This is required for unwrapWHBAR to function correctly. The unwrapped HBAR will then be sent to the user's recipient address.
When the output token is not HBAR, use the user's address as the **recipient** instead.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
*Note: The Hedera JavaScript SDK currently does not support passing complex contract function parameters. Instead, use Ethers.js or Web3.js to obtain the encoded function data and pass that data as a function parameter.*
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//import {..} from @hashgraph/sdk
//Client pre-checks:
// - Router contract has spender allowance for the input token
//load ABI data containing SwapRouter, PeripheryPayments and Multicall functions
const abiInterfaces= new ethers.Interface(abi);
//ExactOutputParams
const params = {
path: routeDataWithFee, //'0x...' (reversed route path)
recipient: swapRouterAddress, //'0x...' - use the SwapRouter id here for unwrapWHBAR to work
deadline: deadline, //Unix seconds
amountOut: outputTinybar, //in Tinybar
amountInMaximum: inputAmountMax //in token's smallest unit
};
//encode each function individually
const swapEncoded = abiInterfaces.encodeFunctionData('exactOutput', [params]);
//Provide the user's address to receive the unwrapped HBAR
const unwrapEncoded = abiInterfaces.encodeFunctionData('unwrapWHBAR', [0, recipient]);
//multi-call parameter: bytes[]
const multiCallParam = [swapEncoded, unwrapEncoded];
//get encoded data for the multicall involving both functions
const encodedData = abiInterfaces.encodeFunctionData('multicall', [multiCallParam]);
//get encoded data as Uint8Array
const encodedDataAsUint8Array = hexToUint8Array(encodedData);
const response = await new ContractExecuteTransaction()
.setContractId(swapRouterContractId)
.setGas(gasLim)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint256']);
const amountIn = values[0]; //uint256 amountIn
```
## Next steps
Fetch expected amounts from QuoterV2 first.
Swap between two HTS tokens with the same router.
SwapRouter and WHBAR IDs for mainnet and testnet.
# Swap tokens for tokens (V2)
Source: https://docs.saucerswap.finance/developers/v2/swap/swap-tokens-for-tokens
Swap HTS tokens for other HTS tokens through the SaucerSwap V2 SwapRouter with exactInput and exactOutput, including path encoding with pool fee tiers.
Below are two methods available to swap tokens for tokens:
* [Swap exact tokens for tokens](/developers/v2/swap/swap-tokens-for-tokens#swap-exact-tokens-for-tokens)
* [Swap tokens for exact tokens](/developers/v2/swap/swap-tokens-for-tokens#swap-tokens-for-exact-tokens)
Contract ID: [SaucerSwapV2SwapRouter](https://hashscan.io/mainnet/contract/0.0.3949434)
Consider the token's decimal places when determining input and output values.
Input and output amounts passed to the solidity function should all be in the token's smallest unit. For the SAUCE token, which has 6 decimal places, an input of 123.45 SAUCE should be entered as 123450000 (123.45 multiplied by 10^6).
Granting a spender allowance to the router contract **is required** when the input token is not native HBAR for security reasons enforced at the native code layer. Ensure that the allowance amount is in token's smallest unit.
Ensure that the "**to**" account has the output token id associated prior to executing the swap. Failure to do so will result in a `TOKEN_NOT_ASSOCIATED_TO_ACCOUNT` error.
***
## Swap exact tokens for tokens
Swap an exact amount of tokens for a minimum token amount.
Solidity function name: `exactInput`
| Struct Parameter Name | Description |
| -------------------------- | ----------------------------------------------------------- |
| *bytes path* | A bytes array representing a route path including fees data |
| *address recipient* | EVM address of the token recipient |
| *uint256 deadline* | Deadline in Unix seconds |
| *uint256 amountIn* | The exact input token amount in its smallest unit |
| *uint256 amountOutMinimum* | The minimum token amount to receive in its smallest unit |
```solidity ISwapRouter.sol theme={null}
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
```
```solidity SwapRouter.sol theme={null}
/// @inheritdoc ISwapRouter
function exactInput(ExactInputParams memory params)
external
payable
override
checkDeadline(params.deadline)
returns (uint256 amountOut)
{
address payer = msg.sender; // msg.sender pays for the first hop
while (true) {
bool hasMultiplePools = params.path.hasMultiplePools();
// the outputs of prior swaps become the inputs to subsequent ones
params.amountIn = exactInputInternal(
params.amountIn,
hasMultiplePools ? address(this) : params.recipient, // for intermediate swaps, this contract custodies
0,
SwapCallbackData({
path: params.path.getFirstPool(), // only the first pool in the path is necessary
payer: payer
})
);
// decide whether to continue or terminate
if (hasMultiplePools) {
payer = address(this); // at this point, the caller has paid
params.path = params.path.skipToken();
} else {
amountOut = params.amountIn;
break;
}
}
require(amountOut >= params.amountOutMinimum, 'Too little received');
}
```
Set the minimum output token amount (`amountOutMinimum`) with caution.
A high minimum might lead to a swap failure due to insufficient liquidity or rapid price movements. Conversely, setting the minimum too low can expose you to significant slippage, potentially resulting in a financial loss as you might receive far fewer tokens than expected.
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, 0x0001F4 (500) for a 0.05% fee.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
*Note: The Hedera JavaScript SDK currently does not support passing complex contract function parameters. Instead, use Ethers.js or Web3.js to obtain the encoded function data and pass that data as a function parameter.*
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import {
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
// - Router contract has spender allowance for the input token
//load ABI data containing SwapRouter functions
const abiInterfaces = new ethers.Interface(abi);
//ExactInputParams
const params = {
path: routeDataWithFee, //'0x...'
recipient: recipientAddress, //'0x...' - user's recipient address
deadline: deadline, //Unix seconds
amountIn: inputAmount, //in token's smallest unit
amountOutMinimum: outputAmountMin //in token's smallest unit
};
//get encoded hexdecimal string data ('0x...')
const encodedData = abiInterfaces.encodeFunctionData('exactInput', [params]);
//get encoded data as Uint8Array
const encodedDataAsUint8Array = hexToUint8Array(encodedData);
const response = await new ContractExecuteTransaction()
.setContractId(swapRouterContractId)
.setGas(gasLim)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint256']);
const amountOut = values[0]; //uint256 amountOut - in token's smallest unit
```
***
## Swap tokens for exact tokens
Swap a maximum amount of tokens to receive an exact tokens amount
Solidity function name: `exactOutput`
| Schema parameter name | Description |
| ------------------------- | ----------------------------------------------------------- |
| *bytes path* | A bytes array representing a route path including fees data |
| *address recipient* | EVM address for the token recipient |
| *uint256 deadline* | Deadline in Unix seconds |
| *uint256 amountOut* | The exact output amount to receive in its smallest unit |
| *uint256 amountInMaximum* | The maximum allowed input amount in its smallest unit |
```solidity ISwapRouter.sol theme={null}
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
```
```solidity SwapRouter.sol theme={null}
/// @inheritdoc ISwapRouter
function exactOutput(ExactOutputParams calldata params)
external
payable
override
checkDeadline(params.deadline)
returns (uint256 amountIn)
{
// it's okay that the payer is fixed to msg.sender here, as they're only paying for the "final" exact output
// swap, which happens first, and subsequent swaps are paid for within nested callback frames
exactOutputInternal(
params.amountOut,
params.recipient,
0,
SwapCallbackData({path: params.path, payer: msg.sender})
);
amountIn = amountInCached;
require(amountIn <= params.amountInMaximum, 'Too much requested');
amountInCached = DEFAULT_AMOUNT_IN_CACHED;
}
```
Set the maximum input token amount (`amountInMaximum`) with caution.
A low maximum might lead to a swap failure if the required liquidity surpasses this limit or due to rapid price movements. Conversely, setting it too high can expose you to significant slippage, potentially leading to a financial loss as you might spend far more tokens than expected.
The data passed to the 'path' parameter follows this format: \[token, fee, token, fee, token, ...], but **reversed** (i.e. the first token in the array should be output token), with each 'token' in the route being 20 bytes long and each 'fee' being 3 bytes long. Example, 0x000BB8 (3000) for a 0.30% fee.
### Code overview
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Token approve allowance](https://docs.hedera.com/hedera/sdks-and-apis/sdks/cryptocurrency/approve-an-allowance)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
*Note: The Hedera JavaScript SDK currently does not support passing complex contract function parameters. Instead, use Ethers.js or Web3.js to obtain the encoded function data and pass that data as a function parameter.*
```typescript theme={null}
import * as ethers from 'ethers'; //V6
import {
ContractExecuteTransaction,
AccountAllowanceApproveTransaction,
TokenAssociateTransaction
} from '@hashgraph/sdk';
//Client pre-checks:
// - Output token is associated
// - Router contract has spender allowance for the input token
//load ABI data containing SwapRouter functions
const abiInterfaces = new ethers.Interface(abi);
//ExactOutputParams
const params = {
path: routeDataWithFee, //'0x...' (reversed route path)
recipient: recipientAddress, //'0x...' - user's recipient address
deadline: deadline, //Unix seconds
amountOut: outputAmount, //in token's smallest unit
amountInMaximum: inputAmountMax //in token's smallest unit
};
//get encoded hexdecimal string data ('0x...')
const encodedData = abiInterfaces.encodeFunctionData('exactOutput', [params]);
//get encoded data as Uint8Array
const encodedDataAsUint8Array = hexToUint8Array(encodedData);
const response = await new ContractExecuteTransaction()
.setContractId(swapRouterContractId)
.setGas(gasLim)
.setFunctionParameters(encodedDataAsUint8Array)
.execute(client);
const record = await response.getRecord(client);
const result = record.contractFunctionResult!;
const values = result.getResult(['uint256']);
const amountIn = values[0]; //uint256 amountIn - in token's smallest unit
```
## Next steps
Fetch expected amounts from QuoterV2 first.
Monitor executed swaps in near real time.
SwapRouter and QuoterV2 IDs for mainnet and testnet.
# Track swap events (V2)
Source: https://docs.saucerswap.finance/developers/v2/swap/track-swap-events
Monitor SaucerSwap V2 Swap events in near real time by polling the Hedera mirror node REST API or JSON-RPC relay, including price and liquidity fields.
Below are the common methods to monitor swap events:
* [Polling Swap events for all pairs](#polling-swap-events-for-all-pairs)
* Subscription using eth\_subscribe (coming later - [HIP-694](https://github.com/hiero-ledger/hiero-improvement-proposals/blob/main/HIP/hip-694.md))
For production environments, it's highly recommended to use a paid Mirror Node provider for commercial and high-traffic purposes. While Hedera's public mirror node offers free REST API and JSON API endpoints, they have global rate limits. These are best suited for development or low rate usage scenarios.
***
## Polling Swap events for all pairs
*No gas cost — read-only call.*
Every time a user executes a swap, the contract emits a 'Swap' event with the updated reserve values for the token pair. The following code demonstrates how to listen to these 'Swap' events for all pairs using either the REST API or JSON RPC.
Listening to 'Swap' events without specifying an address in the filter data will return logs for all pairs on SaucerSwap, as well as other DEXs on Hedera that share the same 'topic0' hash signature for the 'Swap' event. To identify and filter specific pairs, extract the pair's EVM address from the log.
When a swap involves multiple liquidity pairs, a successful smart contract call will emit multiple 'Swap' events. To determine the route used, as well as the initial input amount and the final output amount, aggregate all the 'Swap' event logs.
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera JSON RPC Relay](https://docs.hedera.com/evm/tutorials/intermediate/json-rpc-connections)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
const latestBlock = await provider.getBlockNumber();
const fromBlock = latestBlock - 1000;
//load ABI data containing the Swap event
const abiInterfaces = new ethers.Interface(abi);
const filter = {
topics: [abiInterfaces.getEvent('Swap')!.topicHash], //topic0 filter
fromBlock: fromBlock,
toBlock: latestBlock,
};
//group logs on transaction hash
const groupedLogs:any = {};
const logs = await provider.getLogs(filter);
for (const log of logs) {
const tnxHash = log.transactionHash;
if (!groupedLogs[tnxHash]) {
groupedLogs[tnxHash] = [];
}
groupedLogs[tnxHash].push(log);
}
Object.keys(groupedLogs).forEach(tnxHash => {
console.log(`\nTransaction hash: ${tnxHash}`);
for (const log of groupedLogs[tnxHash]) {
const pairEvmAddress = log.address; //use this to get token0 and token1 data
const parsedLog = abiInterfaces.parseLog({ topics: log.topics.slice(), data: log.data });
const result = parsedLog!.args;
let output = '';
output += `Pair: ${pairEvmAddress}`;
output += `, amountIn: ${result.amount0}`;
output += `, amountOut: ${result.amount1}`;
output += `, sqrtPriceX96: ${result.sqrtPriceX96}`;
output += `, liquidity: ${result.liquidity}`;
output += `, tick: ${result.tick}`;
console.log(output);
}
});
```
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Ethers.js docs (v6)](https://docs.ethers.org/v6/)
* [Hedera REST API](https://docs.hedera.com/hedera/sdks-and-apis/rest-api)
```typescript theme={null}
import * as ethers from 'ethers'; //V6
//load ABI data containing the Swap event
const abiInterfaces = new ethers.Interface(abi);
let params = `timestamp=gte:${unixFrom}×tamp=lte:${unixTo}`;
params += `&topic0=${abiInterfaces.getEvent('Swap')!.topicHash}`;
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/results/logs?${params}`;
const response = await axios.get(url);
const logs = response.data.logs;
//group logs on transaction hash
const groupedLogs:any = {};
for (const log of logs) {
const tnxHash = log.transaction_hash;
if (!groupedLogs[tnxHash]) {
groupedLogs[tnxHash] = [];
}
groupedLogs[tnxHash].push(log);
}
Object.keys(groupedLogs).forEach(tnxHash => {
console.log(`\nTransaction hash: ${tnxHash}`);
for (const log of groupedLogs[tnxHash]) {
const pairEvmAddress = log.address; //use this to get token0 and token1 data
const parsedLog = abiInterfaces.parseLog({ topics: log.topics.slice(), data: log.data });
const result = parsedLog!.args;
let output = '';
output += `Pair: ${pairEvmAddress}`;
output += `, timestamp: ${log.timestamp}`;
output += `, amountIn: ${result.amount0}`;
output += `, amountOut: ${result.amount1}`;
output += `, sqrtPriceX96: ${result.sqrtPriceX96}`;
output += `, liquidity: ${result.liquidity}`;
output += `, tick: ${result.tick}`;
console.log(output);
}
});
```
## Next steps
The V1 equivalent with reserve-style amounts.
Map pair addresses back to pools and tokens.
# WHBAR overview
Source: https://docs.saucerswap.finance/developers/whbar/overview
How the WHBAR and WhbarHelper contracts wrap HBAR for smart contract use on SaucerSwap, plus the WHBAR allowance security advisory for integrators.
The [WHBAR contract](/developers/contracts) is a key component of the SaucerSwap protocol, enabling the conversion of native HBAR into wrapped HBAR, and vice versa, thereby inheriting the HTS functionality needed to interact with smart contracts on Hedera.
It is specifically designed to be called by the SaucerSwap V1 and V2 core and periphery contracts, as well as the WhbarHelper contract (described in this section). WHBAR is not intended for direct use by developers in other applications due to its specialized nature.
## WHBAR contract security advisory
Accounts that use the WHBAR contract directly and meet the following risk conditions expose themselves to loss of funds. The vulnerability described in this notice has existed since a 2023 network update.
For funds to be at risk, specific conditions must exist:
* An account has an open WHBAR allowance granted outside of an atomic transaction.
* The account is actively holding WHBAR tokens.
* No protective mechanisms (like those used by SaucerSwap or [WhbarHelper contracts](/developers/whbar/overview)) are in place.
For more information, see the [WHBAR contract security advisory](https://www.saucerswap.finance/blog/whbar-contract-securityadvisory) blog post.
## Next steps
Deposit HBAR and receive WHBAR at 1:1.
Withdraw WHBAR back to native HBAR.
WHBAR and WhbarHelper IDs for mainnet and testnet.
# Unwrap WHBAR for HBAR
Source: https://docs.saucerswap.finance/developers/whbar/unwrap-whbar-for-hbar
Unwrap WHBAR tokens back into native HBAR at a 1:1 ratio through the WhbarHelper unwrapWhbar function, including the required spender allowance setup.
Contract ID: [WhbarHelper](https://hashscan.io/mainnet/contract/0.0.5808826)
Granting a spender allowance to the **WhbarHelper** contract **is required** for the contract to transfer the [**WHBAR**](https://hashscan.io/mainnet/token/0.0.1456986) token from the user's wallet to the contract.
***
Function name: `unwrapWhbar`
| Parameter Name | Description |
| -------------- | --------------------------------------- |
| *uint256 wad* | WHBAR token amount in its smallest unit |
```solidity WhbarHelper.sol theme={null}
/// @notice Safely unwrap whbar to msg.sender
/// @dev This contract needs an allowance from msg.sender to transfer the whbar token
/// @param wad The amount to unwrap
function unwrapWhbar(uint wad) public {
require(wad > 0, "WhbarHelper: wad cannot be lt zero");
// transfer the whbar to this contract
HederaTokenHelper.safeTransferFrom(whbarToken, msg.sender, address(this), wad);
// approve sending the whbar to the whbar contract
HederaTokenHelper.safeApprove(whbarToken, whbarContract, wad);
// use withdraw(address src, address dst, uint wad) and use this contract and msg.sender to withdraw
// to the contract caller
IWHBAR(whbarContract).withdraw(address(this), msg.sender, wad);
}
```
## Code overview
Recommended gas limit: 1,000,000
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractFunctionParameters,
ContractExecuteTransaction,
TokenAssociateTransaction,
Hbar,
HbarUnit
} from '@hashgraph/sdk';
//Client pre-checks:
// - WhbarHelper contract has spender allowance for WHBAR token
const params = new ContractFunctionParameters();
params.addUint256(withdrawAmount); //amount in token's smallest unit
await new ContractExecuteTransaction()
.setContractId(whbarHelperContractId)
.setGas(gasLim)
.setFunction('unwrapWhbar', params)
.execute(client);
```
## Next steps
Deposit HBAR and receive WHBAR at 1:1.
How WHBAR works and its security advisory.
# Wrap HBAR for WHBAR
Source: https://docs.saucerswap.finance/developers/whbar/wrap-hbar-for-whbar
Wrap native HBAR into WHBAR tokens at a 1:1 ratio through the WhbarHelper deposit function, with token association requirements and a code example.
Contract ID: [WhbarHelper](https://hashscan.io/mainnet/contract/0.0.5808826)
Ensure that the [WHBAR](https://hashscan.io/mainnet/token/0.0.1456986) token ID is associated with the account prior to calling the deposit function. Failure to do so will result in a `TOKEN_NOT_ASSOCIATED_TO_ACCOUNT` error.
Function name: `deposit`
```solidity WhbarHelper.sol theme={null}
function deposit() public payable {
IWHBAR(whbarContract).deposit{value: msg.value}(msg.sender, msg.sender);
}
```
## Code overview
Recommended gas limit: 100,000
Resources:
* [SaucerSwap deployed contract IDs](/developers/contracts)
* [Hedera JavaScript SDK](https://github.com/hashgraph/hedera-sdk-js)
* [Associate tokens to an account](https://docs.hedera.com/hedera/sdks-and-apis/sdks/token-service/associate-tokens-to-an-account)
* [Calling a smart contract function](https://docs.hedera.com/hedera/sdks-and-apis/sdks/smart-contracts/call-a-smart-contract-function)
```typescript theme={null}
import {
ContractExecuteTransaction,
TokenAssociateTransaction,
Hbar,
HbarUnit
} from '@hashgraph/sdk';
//Client pre-checks:
// - WHBAR token is associated
const depositHbar = Hbar.from(depositAmount, HbarUnit.Hbar)
await new ContractExecuteTransaction()
.setContractId(whbarHelperContractId)
.setPayableAmount(depositHbar)
.setGas(gasLim)
.setFunction('deposit')
.execute(client);
```
## Next steps
Withdraw WHBAR back to native HBAR.
How WHBAR works and its security advisory.
# Bridge to Hedera
Source: https://docs.saucerswap.finance/get-started/bridge-to-hedera
Move assets from Ethereum, Base, and other chains onto Hedera using the in-app bridge, Squid via Axelar, or Stargate via LayerZero — Hashport is gone.
Hedera connects to other chains through two live interoperability networks: Axelar and LayerZero. You can bridge through SaucerSwap's own **bridge** page or go directly to the underlying front ends.
The Hashport bridge was permanently decommissioned on May 31, 2026, and assets wrapped by it are permanently unredeemable. Do not follow older guides that route through Hashport, and do not send assets to Hashport contracts. Tokens carrying the `[hts]` suffix (for example USDC\[hts]) are legacy Hashport-wrapped assets that can no longer be redeemed for the original asset on their source chain.
## SaucerSwap bridge (recommended)
The [bridge page](https://www.saucerswap.finance/bridge) of the web app lets you move assets between Hedera and other chains without leaving SaucerSwap. Under the hood it routes through the Axelar and LayerZero networks. See the [bridge tutorial](/tutorials/bridge) for a step-by-step walkthrough, fee and timing expectations, and troubleshooting.
## Squid (Axelar)
[Axelar](https://axelar.network/) provides proof-of-stake-secured cross-chain communication. [Squid](https://app.squidrouter.com/) is the main routing front end built on it, supporting bridging and cross-chain swaps between Hedera and major EVM chains. Squid works best with an EVM wallet such as MetaMask.
Token issuers can deploy existing Hedera HTS tokens to other chains through Axelar's Interchain Token Service — see [For projects](/resources/for-projects) for the listing walkthrough.
## Stargate (LayerZero)
[LayerZero](https://layerzero.network/) is an omnichain interoperability protocol for lightweight message passing across chains. [Stargate](https://stargate.finance/bridge) is its primary bridging front end and supports transfers between Hedera and other connected networks.
## Tracking a transfer
Bridging takes anywhere from a few minutes to a few hours depending on the chains involved. For Axelar-routed transfers, you can track status on [AxelarScan](https://axelarscan.io/) by searching your transaction hash or wallet address.
## Next steps
Use the in-app bridge step by step, with fee and timing expectations.
You need HBAR for network fees before you can swap bridged assets.
Swap your bridged assets for any listed HTS token.
# Frequently asked questions
Source: https://docs.saucerswap.finance/get-started/faq
Answers to common questions about SaucerSwap: getting started, swapping, order book trading, liquidity, staking, fees, tokens, and troubleshooting.
## Getting started
### How can I get started?
Create a [Hedera wallet](/get-started/wallet), [obtain HBAR](/get-started/hbar) for network fees, then follow the [quickstart](/get-started/quickstart) to make your first swap on the [web app](https://www.saucerswap.finance/).
### Where can I obtain HBAR?
You can obtain HBAR by purchasing it on centralized exchanges, using fiat-to-crypto gateways such as MoonPay or Banxa, or by swapping other tokens for it on SaucerSwap. See [Get HBAR](/get-started/hbar).
### Where can I obtain SAUCE?
SAUCE is available on SaucerSwap itself and on external exchanges. Known exchanges that list SAUCE can be found on [CoinMarketCap](https://coinmarketcap.com/currencies/saucerswap/#Markets).
### Does Hedera have a blockchain explorer like Etherscan?
Yes. [HashScan](https://hashscan.io/mainnet/dashboard) serves the same function on Hedera that Etherscan serves on Ethereum: every account, token, contract, and transaction is publicly viewable.
### Who developed the SaucerSwap protocol?
[SaucerSwap Labs](/contributors/saucerswap-labs) develops the open-source SaucerSwap protocol and maintains the web interface.
### Did SaucerSwap receive a grant?
Yes. SaucerSwap received a 20 million HBAR grant from the [HBAR Foundation](https://www.hbarfoundation.org/) (whose ecosystem role has since been absorbed into the [Hedera Foundation](https://hedera.foundation/)).
### Is SaucerSwap audited?
Yes. SaucerSwap contracts have been audited by firms including Hacken, Omniscia, and Halborn (which audited V3 in May 2026). See [Audits](/developers/security/audits).
## Trading
### What is an AMM?
An automated market maker (AMM) is a type of decentralized exchange that prices a token pair with a mathematical formula instead of matching individual buyers and sellers. Trades execute instantly against liquidity pools funded by liquidity providers.
### Can I place a limit order?
Yes. SaucerSwap V3 is a central limit order book, live on the **trade** page, where you can place limit and market orders on supported markets. See the [trade tutorial](/tutorials/trade) and the [V3 concepts page](/protocol/saucerswap-v3).
Separately, V2 liquidity providers can emulate a fee-earning limit order by depositing liquidity into a price range entirely above or below the current spot price.
### What is the difference between the trade and swap pages?
The **trade** page is the V3 central limit order book: you place orders at prices you choose, and they match against other orders (and, on enabled markets, AMM liquidity). The **swap** page executes instantly against V1 and V2 AMM pools at the best quoted route. See [How SaucerSwap works](/protocol/overview).
### What is slippage?
Slippage is the difference between the expected price of a trade and the price at which it executes. It occurs on both centralized and decentralized exchanges, typically due to market volatility, large trade sizes, or low liquidity. You can set your slippage tolerance in the swap settings — see the [swap tutorial](/tutorials/swap).
### What sets SaucerSwap apart from Uniswap?
SaucerSwap is built on the Hedera Token Service (HTS), giving it high throughput and low, U.S. dollar-denominated fees. Hedera's fair transaction ordering removes the mempool-based MEV attacks seen in Ethereum protocols. SaucerSwap also offers features Uniswap does not: a central limit order book (V3), LARI liquidity incentives, a yield-bearing HBAR wrapper, and single-sided staking. See [How SaucerSwap works](/protocol/overview).
### What is a token allowance?
Hedera requires your explicit approval before SaucerSwap contracts can move tokens on your behalf. When you swap, you choose between a one-time allowance for the exact amount or a maximum allowance that avoids repeat approvals. For background, see [Hedera network security update & SaucerSwap](https://medium.com/@SaucerSwap/hedera-network-security-update-saucerswap-8d2609b43e20).
## Liquidity
### How does SaucerSwap V2 differ from SaucerSwap V1?
V2 introduces concentrated liquidity, letting liquidity providers allocate capital within specific price ranges for better capital efficiency. V2 also offers multiple fee tiers and replaces V1's yield farm with the more efficient LARI program. V2 is recommended for new liquidity positions; V1 is legacy.
### What is concentrated liquidity?
Concentrated liquidity, a feature of SaucerSwap V2, lets liquidity providers (LPs) choose custom price ranges where their capital is used to facilitate trades. Because liquidity is focused where trading actually happens, less capital achieves the same or better outcomes — higher fee yield per dollar for LPs and lower slippage for traders. All positions aggregate into one composite curve that traders trade against. See [SaucerSwap V2](/protocol/saucerswap-v2).
### What is yield farming?
In SaucerSwap V1, yield farming means staking LP tokens in the Masterchef contract to earn SAUCE and HBAR rewards pro-rata to your share of the farm. See [SaucerSwap V1](/protocol/saucerswap-v1).
### What is LARI?
The Liquidity-Aligned Reward Initiative (LARI) is V2's incentive system. Rewards are distributed automatically every two weeks to eligible V2 positions — no staking step required — and campaigns can be configured in various tokens and amounts. See [SaucerSwap V2](/protocol/saucerswap-v2).
### How are liquidity providers compensated?
Primarily through trading fees generated by swaps in their pool. On top of that, V1 offers Yield Farm rewards and V2 offers LARI rewards.
### What is the breakdown of fees?
Traders pay a swap fee on V1 and V2: fixed 0.30% on V1, and 0.05%, 0.15%, 0.30%, or 1.00% on V2 depending on the pool. Of the collected fee, 5/6 goes to liquidity providers and 1/6 to the protocol, which uses it for SAUCE buybacks distributed between the Infinity Pool and the DAO. V3 order book fees work differently — see [V3 fees](/protocol/saucerswap-v3/fees).
### What is impermanent loss?
Impermanent loss occurs when the price ratio of a pooled token pair diverges from the ratio at deposit time, leaving the liquidity provider with less value than simply holding the tokens. The loss becomes permanent only if you withdraw before the ratio reverts.
### Why am I unable to create a V2 pool?
V2 pool creation is permissioned to minimize liquidity fragmentation, overseen by the [SaucerSwap DAO](/governance/overview). V1 pool creation remains permissionless.
### How do I claim my liquidity provider fees in V1?
Withdraw your liquidity. V1 fees accrue inside the pool and are reflected in the value of your LP tokens, so you receive your share automatically when you redeem them. In V2, by contrast, fees are claimed manually from the position page.
## Staking
### How can I stake my SAUCE tokens?
Go to the [stake page](https://www.saucerswap.finance/stake) and deposit SAUCE into the Infinity Pool. You receive xSAUCE, the liquid staking token, which appreciates against SAUCE as rewards accrue. Unstake at any time to realize rewards — there are no lockups. See the [staking tutorial](/tutorials/stake).
### Where do single-sided staking rewards come from?
Three sources: a share of the protocol's 1/6 cut of V1 and V2 swap fees, a portion of Masterchef farm emissions, and HBAR proof-of-stake rewards earned by the WHBAR contract, which are swapped into SAUCE. See [Single-sided staking](/protocol/single-sided-staking).
## Tokens
### How does the token listing process work?
The SaucerSwap interface is permissionless but tiered for user safety: tokens are categorized as default, extended, or untracked. Default tokens appear in the token menu, extended tokens require acknowledging a disclaimer, and untracked tokens must be loaded manually by token ID. For listing details, see [For projects](/resources/for-projects).
### What is a token association?
On Hedera, token association links a specific HTS token to your account. An account must be associated with a token before it can send, receive, or hold it. The SaucerSwap interface prompts you to associate tokens as needed.
### How was the SAUCE token initially distributed?
14% of the max supply (140 million SAUCE) was distributed to community members holding Planck Epoch Collectible (PEC) NFTs, based on the type and number of NFTs held. No private sales or ICOs were conducted. See [Tokenomics](/tokenomics/overview).
### What is the difference between USDC and USDC\[hts]?
[USDC](https://www.circle.com/usdc) is Circle's fiat-backed stablecoin, issued natively on Hedera as an HTS token. USDC\[hts] is a legacy asset that was bridged from Ethereum through the now-decommissioned Hashport bridge.
Hashport was permanently decommissioned on May 31, 2026, and Hashport-wrapped assets such as USDC\[hts] are permanently unredeemable on their source chains. Prefer natively issued assets, and see [Bridge to Hedera](/get-started/bridge-to-hedera) for live bridge routes.
### Does SaucerSwap support tokens with custom fees?
SaucerSwap V2 does not support tokens with custom fees. SaucerSwap V1 supports tokens with fractional fees where net-of-transfers is disabled, but not tokens with fixed fees. A workaround for fixed fees in V1 is to set a fractional fee at 0% with a fallback fee. For details on HTS custom fees, see the [Hedera docs](https://docs.hedera.com/hedera/sdks-and-apis/hedera-api/token-service/customfees).
## Troubleshooting
### Why is my transaction failing?
The two most common causes are `INSUFFICIENT_PAYER_BALANCE` (add more [HBAR](/get-started/hbar) to cover network fees) and `CONTRACT_REVERT_EXECUTED` (often fixed by raising your slippage tolerance in the interface settings). For error-by-error fixes, see [Troubleshooting](/resources/troubleshooting). If you cannot resolve an issue, open a support ticket on the [Discord server](https://saucerswap.finance/discord).
### Why can I not see my tokens in MetaMask?
MetaMask only displays tokens you have imported. Find the token's EVM address in the SaucerSwap interface or on HashScan, then import it in MetaMask. Your balance will appear once imported.
## Next steps
Go from zero to your first swap in five steps.
Error-keyed fixes for failed transactions and stuck transfers.
Understand pools, the order book, fees, and governance in one page.
Reach the team through official support channels.
# Get HBAR
Source: https://docs.saucerswap.finance/get-started/hbar
HBAR pays every network fee on Hedera. Acquire it through centralized exchanges, fiat on-ramps like MoonPay and Banxa, or by bridging and swapping.
HBAR is the native token of the Hedera network. It pays transaction fees, similar to ETH on Ethereum, so every action on SaucerSwap — swapping, adding liquidity, staking, even associating a token — requires a small amount of HBAR in your account.
## Centralized exchanges
HBAR is listed on many exchanges, including Binance, Coinbase, KuCoin, and MEXC. After buying, withdraw HBAR to your Hedera account ID (`0.0.x`) or, for EVM wallets, your `0x...` address. A full list of exchanges that support HBAR is on [CoinMarketCap](https://coinmarketcap.com/currencies/hedera/#Markets).
Some exchanges require a memo field when withdrawing to certain account types. Follow your exchange's withdrawal instructions exactly, and send a small test amount first if you are unsure.
## Fiat-to-crypto gateways
You can buy HBAR directly with credit or debit cards, bank transfers, Apple Pay, and Google Pay through fiat gateways such as [MoonPay](https://www.moonpay.com/buy/hbar) or [Banxa](https://banxa.com/). These services are available on their own websites and inside the HashPack wallet. The **swap** page of the web app also has a **Buy** tab for fiat purchases.
## Bridge and swap
If you already hold assets on another chain, you can [bridge them to Hedera](/get-started/bridge-to-hedera) and then swap a portion for HBAR on SaucerSwap. Keep in mind the bootstrapping constraint: your Hedera account needs a little HBAR to pay the fee for that first swap, so if you are starting from zero, an exchange withdrawal or fiat gateway is the more direct route.
## Next steps
You have HBAR — complete your first swap in five steps.
Learn the full swap flow, including slippage and allowances.
Move existing assets from Ethereum, Base, and other chains.
# Quickstart: your first swap
Source: https://docs.saucerswap.finance/get-started/quickstart
Go from zero to your first token swap on SaucerSwap in five steps: create a Hedera wallet, fund it with HBAR, associate a token, swap, and verify.
This guide takes you from nothing to a completed swap on Hedera mainnet. It should take about 15 minutes, most of which is acquiring HBAR.
Install a self-custody wallet that supports Hedera. Common choices include [SaucerSwap Wallet](/get-started/saucerswap-wallet) (mobile), HashPack, Kabila Wallet, and MetaMask (EVM wallets work on Hedera with a one-time network setup).
See [Create a Hedera wallet](/get-started/wallet) for setup instructions for each option. Write down your recovery phrase and store it offline — nobody can recover it for you.
HBAR is Hedera's native token and pays network fees for every transaction, so you need some before you can do anything else. Buy it on a centralized exchange and withdraw to your Hedera account, or use a fiat on-ramp such as MoonPay directly from your wallet.
See [Get HBAR](/get-started/hbar) for the full list of options. A few HBAR is enough to cover fees for many transactions; anything above that can be swapped for other tokens.
Open [saucerswap.finance](https://www.saucerswap.finance/), select **connect** in the navigation, and approve the connection in your wallet.
On Hedera, your account must be associated with a Hedera Token Service (HTS) token before it can hold that token. When you swap into a token for the first time, the interface prompts you to associate it — approve the association transaction in your wallet. See [What is a token association?](/get-started/faq#what-is-a-token-association) for background.
Go to the **swap** page. HBAR is selected as the token to sell by default; choose the token you want to buy, enter an amount, and review the quote. Confirm the swap and sign the transaction in your wallet.
The [swap tutorial](/tutorials/swap) walks through slippage settings, quote details, and allowances in depth.
Your new balance appears on the **dashboard** page under **My Positions**. For an independent record, look up your account on [HashScan](https://hashscan.io/mainnet/dashboard), Hedera's network explorer, where every transaction and token balance is publicly visible.
If a transaction fails, the two most common causes are insufficient HBAR for network fees and slippage tolerance set too low. See [Troubleshooting](/resources/troubleshooting) for error-by-error fixes.
## Next steps
Master the full swap flow: token classes, slippage, quote details, and allowances.
Place limit and market orders on the V3 central limit order book.
Earn compounding rewards with single-sided staking — no pairing, no lockups.
Move tokens from Ethereum, Base, and other chains onto Hedera.
# SaucerSwap Wallet
Source: https://docs.saucerswap.finance/get-started/saucerswap-wallet
SaucerSwap Wallet is a self-custody mobile wallet for Hedera on iOS and Android: swap, stake, explore tokens, and connect to Hedera dApps on the go.
[SaucerSwap Wallet](https://www.saucerswap.finance/saucerswap-wallet) is SaucerSwap Labs' self-custody mobile wallet for Hedera. It brings the core protocol features to your phone: swapping, staking, exploring tokens, and connecting to Hedera dApps.
## Download
* iOS: [Apple App Store](https://apps.apple.com/us/app/saucerswap-hedera-wallet/id6747405489)
* Android: [Google Play Store](https://play.google.com/store/apps/details?id=com.saucerswap.mobile)
## Self-custody
SaucerSwap Wallet is fully self-custodial: your keys are generated and stored on your device, and SaucerSwap Labs never has access to them or your funds.
Back up your recovery phrase when you create the wallet and store it offline. If you lose the phrase and the device, the account cannot be recovered.
## Core features
| Feature | What it does |
| --------------- | ------------------------------------------- |
| Swap | Trade HTS tokens directly from the app |
| Stake | Stake SAUCE for xSAUCE in the Infinity Pool |
| Explore | Browse token prices and market data |
| dApp connection | Connect to Hedera dApps from your phone |
| Portfolio | Track your token balances in one place |
## Next steps
Fund your wallet with HBAR to pay network fees.
Complete your first swap in five steps.
Compare SaucerSwap Wallet with HashPack and MetaMask.
# Create a Hedera wallet
Source: https://docs.saucerswap.finance/get-started/wallet
Set up a self-custody wallet for Hedera: SaucerSwap Wallet, HashPack, Kabila Wallet, or MetaMask with the Hedera JSON-RPC relay.
To use SaucerSwap you need a self-custody wallet that supports Hedera accounts. All four options below work with the web app; SaucerSwap Wallet, HashPack, and Kabila Wallet are Hedera-native, while MetaMask connects through Hedera's Ethereum Virtual Machine (EVM) compatibility layer.
Your recovery phrase is the only way to restore a self-custody wallet. Write it down, store it offline, and never enter it on a website. SaucerSwap Labs will never ask for it.
## SaucerSwap Wallet
[SaucerSwap Wallet](https://www.saucerswap.finance/saucerswap-wallet) is SaucerSwap Labs' self-custody mobile wallet for Hedera, built to help you swap, stake, explore tokens, and connect to Hedera dApps from your phone.
* iOS: download from the [Apple App Store](https://apps.apple.com/us/app/saucerswap-hedera-wallet/id6747405489).
* Android: download from the [Google Play Store](https://play.google.com/store/apps/details?id=com.saucerswap.mobile).
See [SaucerSwap Wallet](/get-started/saucerswap-wallet) for an overview of its features.
## HashPack
[HashPack](https://www.hashpack.app/) is the most widely used wallet on the Hedera network and an official SaucerSwap partner. For step-by-step setup instructions, see [How to create your first account with HashPack](https://www.hashpack.app/post/how-to-create-your-first-account-with-hashpack).
* Desktop: install the HashPack extension from the [Chrome Web Store](https://chrome.google.com/webstore/detail/hashpack/gjagmgiddbbciopjhllkdnddhcglnemk).
* iOS: download from the [Apple App Store](https://apps.apple.com/us/app/hashpack/id6444389849).
* Android: download from the [Google Play Store](https://play.google.com/store/apps/details?id=app.hashpack.wallet.twa).
## Kabila Wallet
[Kabila Wallet](https://kabila.app/docs/kabila-wallet) is a non-custodial Hedera wallet available as a browser extension and on iOS and Android. It supports Hedera token association, dApp connections, allowances, multisignature accounts, and native staking. Use Kabila's official wallet page for current download links and setup instructions.
## MetaMask
[MetaMask](https://metamask.io/) is the most widely used EVM wallet. It can hold HTS tokens on Hedera through the network's EVM compatibility layer. For general setup, see [Getting started with MetaMask](https://support.metamask.io/start/getting-started-with-metamask/).
* Desktop: install the extension from [metamask.io](https://metamask.io/).
* iOS: download from the [Apple App Store](https://apps.apple.com/us/app/metamask-blockchain-wallet/id1438144202).
* Android: download from the [Google Play Store](https://play.google.com/store/apps/details?id=io.metamask).
### Add the Hedera network
Before MetaMask can talk to Hedera, you must add a Hedera JSON-RPC relay as a custom network. This is a one-time step.
You have two options:
1. Use [ChainList](https://chainlist.org/chain/295) to add the Hashio RPC (maintained by Hashgraph) with one click.
2. Add the network manually with these values:
| Field | Value |
| ------------------ | --------------------------------------- |
| Network name | Hedera Mainnet |
| RPC URL | `https://mainnet.hashio.io/api` |
| Chain ID | `295` |
| Currency symbol | HBAR |
| Block explorer URL | `https://hashscan.io/mainnet/dashboard` |
MetaMask displays your account as a `0x...` EVM address. HashScan can resolve it to the corresponding `0.0.x` Hedera account ID. Tokens you receive will not appear in MetaMask until you import them by their EVM address — see [Why can I not see my tokens in MetaMask?](/get-started/faq#why-can-i-not-see-my-tokens-in-metamask)
## Next steps
Fund your new wallet with HBAR to pay network fees and start swapping.
Complete your first swap in five steps.
Move assets from other chains into your Hedera wallet.
# DAO reporting
Source: https://docs.saucerswap.finance/governance/dao-reporting
Downloadable transaction-level reports for the SaucerSwap DAO treasury, published as CSV files to the official DAO-Reporting GitHub repository.
SaucerSwap Labs publishes transaction-level reports of DAO treasury activity as CSV files. Each report covers a date range and lists the treasury transactions in that window, so token holders and analysts can audit flows against the [treasury contracts](/governance/overview#treasury-flows-and-dao-controlled-contracts) on HashScan.
Freshness check: July 29, 2026. The latest repository file reports activity only through February 11, 2026, so public reporting is more than five months behind the check date. No fixed publication cadence or named reporting owner is documented in the repository. Treat the dataset as stale and incomplete for current treasury state.
Download the latest published CSV (53.4KB), covering September 25, 2025 through February 11, 2026.
Browse the repository for all published reports.
For per-epoch LARI airdrop results — published separately — see [LARI weights](/protocol/saucerswap-v2/lari-weights).
## Next steps
The treasury flows these reports document.
Per-epoch reward allocations and airdrop results.
Contract and account IDs for independent verification.
# SaucerSwap governance
Source: https://docs.saucerswap.finance/governance/overview
How the SaucerSwap DAO works: token-weighted voting with SAUCE and xSAUCE, the RFC-to-election proposal lifecycle, scope, and treasury contracts.
The SaucerSwap decentralized autonomous organization (DAO) governs key aspects of the protocol: reward allocations, liquidity pool creation, tokenomics adjustments, and treasury management. Decisions are made collectively by community members holding SAUCE and xSAUCE.
## Token-weighted voting
Votes are cast on-chain using the Hedera Consensus Service (HCS). You connect a wallet on the [govern page](https://www.saucerswap.finance/governance), sign a voting message, and it is submitted to a designated topic ID. SaucerSwap retrieves your historical SAUCE and xSAUCE balances at a specified timestamp via the Hedera Mirror Node. You may vote multiple times, but only your final vote counts.
Your voting power is your SAUCE balance plus your xSAUCE balance multiplied by the current SAUCE-per-xSAUCE conversion rate.
Balances held inside liquidity pools are excluded. The conversion rate is the current SAUCE/xSAUCE exchange rate from the [Infinity Pool](/protocol/single-sided-staking).
## Proposal lifecycle
Every change follows the same path: an RFC on the governance forum, then two on-chain votes.
Anyone can post a proposal idea on the [SaucerSwap governance forum](https://gov.saucerswap.finance/) — no voting power required. The RFC stays open for discussion for at least 3 days and can be freely revised by the proposer. Nothing is on-chain yet.
A proposer with at least 100k voting power submits the refined proposal on the govern page for a 2-day vote. The vote is multichoice, always includes a "No change" option, and snapshots account balances every minute. Passing requires a 5M voting power quorum and a majority.
A passing proposal automatically advances to a final 2-day election, typically pitting the winning option against "No change". Enactment requires a 15M voting power quorum and a majority.
If a proposal or election fails, a 2-week cooldown applies before the same RFC can be resubmitted, unless it undergoes a substantive change (as determined by SaucerSwap Labs). A resubmitted RFC restarts the standard 3-day commentary period.
Unsubstantive (cooldown still applies):
* Before: creation of AAA/HBAR farm with 1% weight.
* After: creation of AAA/HBAR farm with 0.75% weight.
Substantive (may resubmit immediately):
* Before: creation of BBB/HBAR V2 pool; 1% LARI allocation of SAUCE.
* After: creation of BBB/HBAR and BBB/USDC V2 pools; LARI campaign with 1,000 BBB per epoch split 50:50 across the pools for 5 epochs.
## Governance scope
The DAO oversees:
* **V1 farm creation and amendment** — new yield farms and adjustments to SAUCE and HBAR emissions for existing farms; see [farm weights](/protocol/saucerswap-v1/farm-weights).
* **V2 pool creation** — V2 pools are created permissioned by DAO vote to prevent liquidity fragmentation. For each pool, the DAO sets the protocol fee parameter, 1/N where 4 ≤ N ≤ 10, and selects the fee tier.
* **LARI campaign creation and amendment** — each proposal specifies campaign duration and token allocations per epoch; see [LARI weights](/protocol/saucerswap-v2/lari-weights).
* **Tokenomics changes** — significant changes to SAUCE tokenomics require DAO approval; see [SAUCE tokenomics](/tokenomics/overview).
* **Treasury management** — fee switches, HBAR staking reward allocation within protocol contracts, SAUCE buyback allocations, and management of treasury assets within SaucerSwap and other protocols.
Matters not specified here — particularly broader financial concerns — are managed by SaucerSwap Labs, which oversees the treasury to fund protocol development and DAO-related activities. Meta-governance matters are also controlled by SaucerSwap Labs for the time being.
## Treasury flows and DAO-controlled contracts
The flows below describe the mechanism; the percentages within each splitter are DAO-adjustable, and per-week amounts vary with emissions and market conditions. For contract-by-contract detail, see [Contract deployments](/developers/contracts); for transaction-level reporting, see [DAO reporting](/governance/dao-reporting).
* **Masterchef emissions** (`0.0.1077627`) — mints SAUCE on the [tokenomics schedule](/tokenomics/overview). Its 5,000 pool-reward points currently allocate 788 to V1 farms, 2,314 to LARI, and 1,898 to the DAO. The additive devcut's current economic destination is 100% xSAUCE staking; an operational splitter can remain in the transfer topology.
* **LARI distribution** — SAUCE designated for LARI accumulates in holding accounts and is airdropped to V2 LPs at the end of each epoch. Current per-epoch totals are published in [LARI weights](/protocol/saucerswap-v2/lari-weights).
* **V1/V2 fee-switch revenue and HBAR staking rewards** — after SAUCE buybacks through BrewsaucerV2 (`0.0.9575119`), the ratified economic allocation is 50% xSAUCE, 10% Development, 10% burn, and 30% protocol-owned liquidity plus incentive reserve.
* **V3 net fees** — taker fees less any maker rebates also fund SAUCE buybacks. The ratified allocation is 30% xSAUCE, 60% Development, 10% burn, and 0% protocol-owned liquidity plus incentive reserve.
* **Collection topology** — V1's 1/6 protocol share accrues to feeTo (`0.0.1062785`); V2 uses each pool's configured 1/N protocol share where 4 ≤ N ≤ 10. Mothership (`0.0.1460199`), sauceSplitter (`0.0.1462981`), hbarSplitter (`0.0.1462986`), stakeToSetter (`0.0.1456973`), and BrewsaucerV2 implement collection and routing. An intermediary contract does not by itself define the economic destination.
The source-specific allocation matrix was ratified through [V3 Launch Economics, thread 368](https://gov.saucerswap.finance/t/v3-launch-economics/368), proposal 6123, and final passing election 6141. [Thread 385](https://gov.saucerswap.finance/t/v3-order-book-calibration-contract-migration-market-set-and-fee-configuration/385), proposal 6285, and final election 6296 later ratified an order-book recalibration on July 22, 2026, but its new configuration and cross-venue routing are not verified as deployed. Use the governance app and live protocol surfaces together.
## Proto-governance
Proto-governance — previously conducted in Discord using Planck Epoch Collectible (PEC) NFTs — was replaced by the on-chain token-weighted voting system described above.
## Next steps
Read live RFCs or start one of your own.
Transaction-level treasury reports.
Stake SAUCE for xSAUCE to increase your voting power over time.
Verify every governance and treasury contract on HashScan.
# SaucerSwap documentation
Source: https://docs.saucerswap.finance/index
Learn how to swap, trade on the order book, provide liquidity, stake SAUCE, and build on SaucerSwap, the largest decentralized exchange on Hedera by volume.
SaucerSwap is a decentralized exchange (DEX) and liquidity hub on [Hedera](https://hedera.com/) — the largest on the network by trading volume, with over \$6B in all-time volume and 19M+ trades as of July 2026.
The protocol combines three trading venues — the V1 automated market maker (AMM), V2 concentrated liquidity, and the V3 central limit order book — plus yield farming, LARI liquidity incentives, single-sided SAUCE staking, cross-chain bridging, and on-chain governance through the SaucerSwap DAO.
## Choose your path
Place limit and market orders on the V3 order book, or swap instantly against AMM liquidity.
Earn trading fees and LARI rewards by supplying tokens to V2 concentrated liquidity pools.
Stake SAUCE in the Infinity Pool and receive xSAUCE, which grows in value as protocol rewards compound.
Integrate SaucerSwap through the REST API, the Orderbook API, or on-chain smart contracts.
Get an HTS token listed on the interface, apply for a farm or LARI campaign, and bridge it cross-chain.
See how the AMM, concentrated liquidity, the order book, staking, and governance fit together.
## New to Hedera?
Go from zero to your first swap in five steps: wallet, HBAR, token association, swap, verify.
Set up SaucerSwap Wallet, HashPack, or MetaMask to hold HBAR and HTS tokens.
## Get help
Answers to the most common questions about trading, liquidity, staking, and fees.
Fix failed transactions, association errors, slippage reverts, and stuck bridge transfers.
Open a ticket on Discord or reach the team through official support channels.
# V3 Orderbook Risk Notice
Source: https://docs.saucerswap.finance/legal/orderbook-risk-notice
Required risk disclosures for SaucerSwap V3 order book trading, covering off-chain infrastructure, on-chain settlement, order lifecycle, and data risks.
Last modified: May 29, 2026
SaucerSwap V3 uses off-chain orderbook infrastructure, settlement-support software, and on-chain settlement components. Settlement-support software may submit matched bundles for on-chain settlement. Off-chain systems may include order-entry tools, order admission, validation, signed order storage, matching, relay, market data, order status, APIs, WebSockets, databases, queues, Redis streams, indexers, mirror nodes, Hedera Consensus Service ("HCS") references where used, operator accounts, wallets, and third-party infrastructure.
Using V3 involves risks, including:
* orders may be rejected, delayed, throttled, dropped, expired, canceled, corrected, partially filled, fully filled, overfilled, underfilled, filled more than once, filled after an apparent terminal state, not filled, or settled later than expected;
* cancellations may fail, lag, or arrive too late to prevent matching or settlement support;
* a displayed cancellation, order status, fill status, balance, or settlement status may be provisional, delayed, stale, incorrect, or inconsistent across the interface, API, WebSocket feed, wallet, explorer, mirror node, indexer, and public network;
* market data, quotes, spreads, depth, balances, fees, routes, order status, fills, and analytics may be stale, wrong, delayed, incomplete, inconsistent, or unavailable;
* order-core, matcher, database, Redis, queue, API, WebSocket, indexer, mirror-node, HCS references where used, wallet, signature, RPC, node, settlement-support software, fee-controller, admin-configuration, maker validation, taker transfer, actual-fee, fee-cap, or order-cap, skipped-maker, filler authorization, fee-discount tier, market-data, market-halt, market-reopen, or third-party systems can fail or behave unexpectedly;
* orders may fill within signed parameters at prices, amounts, or times different from interface estimates;
* orders may match against another order, SaucerSwap automated market maker ("AMM") liquidity, or another configured backstop liquidity source made available by the then-current V3 configuration, and the resulting price, amount, fee, timing, slippage, or settlement path may differ from the interface estimate;
* public networks and smart contracts can fail, halt, reorganize, congest, be exploited, or behave unexpectedly;
* audits, security reviews, bug bounties, monitoring, and testnets reduce but do not eliminate risk and apply only to their stated scope.
SaucerSwap Labs does not provide best execution, price improvement, price protection, quote protection, regulated market surveillance service, fair access, order priority, continuous trading, guaranteed liquidity, liquidity-provision or market-making obligations, uptime, cancellation, recovery, reimbursement, fiduciary, brokerage, custody, regulated clearing, custodial settlement, guaranteed settlement, settlement as a regulated intermediary, or money transmission services. You are responsible for reviewing every wallet prompt, signature mode, signature prefix, signed message, order parameter, approval, allowance, cancellation, and transaction before signing.
# Privacy Policy
Source: https://docs.saucerswap.finance/legal/privacy-policy
How SaucerSwap Labs collects, uses, discloses, and retains information across its websites, interfaces, mobile applications, APIs, and related services.
Last modified: May 29, 2026
This Privacy Policy explains how SaucerSwap Labs, Inc., a Delaware corporation ("SaucerSwap Labs," "we," "our," or "us") collects, uses, discloses, and retains information when you access or use our websites, interfaces, mobile applications, application programming interfaces ("APIs"), developer tools, Orderbook Services (as defined in the Terms), market-data services, WebSocket feeds, support channels, bug-bounty or security-reporting channels, embedded or partner interfaces that link to this Policy, and related services (collectively, the "Services").
This Privacy Policy is incorporated into the SaucerSwap Terms of Service. Capitalized terms not defined here have the meanings given in the Terms. If this Policy conflicts with the Terms, this Policy controls with respect to personal information, personal data, privacy rights, and data processing. The Terms control with respect to contractual service access, risk allocation, and non-privacy matters.
"Personal information," "personal data," and similar terms mean information that identifies, relates to, describes, can reasonably be linked to, or is otherwise regulated as information about a person, wallet, device, household, or user under applicable privacy or data-protection law.
## 1. Scope
This Privacy Policy applies to information we process in connection with the Services, including pre-acceptance visits, wallet-connection pages, legal acceptance flows, beta, testnet, staging, production, API, market-maker, embedded, partner, and third-party-hosted interface instances that link to or include this Policy.
This Policy does not apply to third-party wallets, app stores, RPC providers, mirror nodes, explorers, indexers, cloud providers, token issuers, stablecoin issuers, market makers, liquidity providers, bridges, analytics providers, community platforms, or other Third-Party Services when those parties act as independent controllers or independent businesses. It applies to those parties only where they process information for us as our service provider, processor, or contractor.
Public blockchains, Hedera network records, consensus timestamps, Hedera Consensus Service ("HCS") references where used, mirror nodes, explorers, wallets, counterparties, and third-party indexers may independently process and retain information. Some wallet, order, transaction, HCS-reference, mirror-node, explorer, indexer, and public-chain data may be public, immutable, independently retained, or outside our control.
Wallet addresses, Hedera account IDs, public keys, order hashes, transaction IDs, HCS references, signed authentication messages, signed orders, and similar pseudonymous identifiers are personal information when they identify, relate to, describe, or can reasonably be linked to a person, wallet, device, household, or user. For users in the European Economic Area, United Kingdom, or Switzerland, we treat pseudonymous wallet addresses and account identifiers that can be linked to an individual as personal data by default.
Before you complete legal acceptance, we may process IP address, user agent, approximate location derived from IP address, wallet connection state, cookie or local storage state, device and browser signals, and similar information to display the Services, show the legal acceptance flow, apply geoblocking and sanctions controls, detect abuse, and record whether acceptance was completed.
## 2. Information We Collect
We may collect the categories of information below.
### A. Wallet, Account, Legal Acceptance, And Contact Information
We may collect wallet addresses, Hedera account IDs, public keys, API client identifiers, session identifiers, legal acceptance or privacy acknowledgment event identifiers, Terms version, Privacy Policy version, V3 Orderbook Risk Notice version, document hash or text hash, acceptance timestamp, IP-derived approximate location or jurisdiction signal at acceptance, user agent at acceptance, support identifiers, Discord or community handles you provide to us, email addresses you provide to us, and other information you submit through support, legal, security, bug-bounty, incident-response, business, or feedback channels.
### B. Device, Network, Usage, And App Information
We may collect IP address, user agent, browser type, device type, operating system, approximate location derived from IP address, referring pages, pages viewed, links clicked, timestamps, language settings, cookie identifiers, analytics identifiers, app instance identifiers, crash data, performance data, and other information about how you access or use the Services. If we make a mobile application available, we do not intentionally request GPS or other precise device geolocation unless we provide a separate notice and obtain any permission or consent required by law. We do not use mobile advertising identifiers for cross-context behavioral advertising unless we first provide required platform and legal controls.
### C. Authentication, Session, API, And Security Information
We may collect wallet-auth challenges, signed authentication messages, verification results, JSON Web Tokens ("JWTs") or other session tokens, API keys, API key metadata, API client identifiers, rate-limit counters, request and response metadata, endpoint paths, timestamps, error codes, access logs, security logs, abuse-prevention signals, and related authentication or authorization records. In persistent logs, analytics systems, and support systems under our control, we store API keys, JWTs, session tokens, and similar secrets only in hashed, truncated, encrypted, redacted, or metadata-only form and do not intentionally use raw secrets for analytics.
### D. Orderbook, Trading, And Strategy Information
If you use Orderbook Services, we may collect and process signed order payloads, signatures, signature mode or prefix metadata, order hashes, order identifiers, orderbook IDs, pair IDs, token addresses, token association information, order type, side, price, amount, fee, fee cap, deadline, time-in-force, maker or taker fields, order status, fills, cancellations, expirations, rejections, failures, corrections, Settlement references, transaction IDs, consensus timestamps, HCS or network references, mirror-node or indexer references, order history, related lifecycle events, and inferences about trading or order strategy that can be derived from your orders, API usage, or interaction patterns.
Order payloads and lifecycle records may remain in controlled off-chain systems after a terminal order state where retention is needed for order history, reconciliation, legal acceptance evidence, security, abuse prevention, disputes, audits, regulatory cooperation, or legal claims.
### E. Market Data, WebSocket, Reliability, And Error Telemetry
We may collect WebSocket or [Socket.IO](http://Socket.IO) connection metadata, subscriptions, orderbook snapshots, market-data requests, quote requests, route requests, status requests, lifecycle events, latency data, service health data, database or queue diagnostics, reconciliation logs, crash logs, Sentry or comparable error telemetry, incident-response records, and related operational data.
### F. Compliance, Sanctions, Fraud, Abuse, And Automated-Risk Signals
We may collect or generate sanctions-screening signals, wallet-risk signals, fraud signals, abuse signals, market-manipulation indicators, wash-trading indicators, spoofing or layering indicators, API-abuse signals, geolocation or geoblocking signals, cybercrime or theft indicators, compliance-review records, investigation records, and legal-process records. These signals may be created by us or by compliance, sanctions-screening, blockchain-analytics, geolocation, geoblocking, fraud-prevention, security, or infrastructure providers.
We may use device, network, wallet, and behavior signals to detect abuse, sanctions evasion, fraud, bot activity, or security risk. We do not use device fingerprinting or similar techniques for cross-context behavioral advertising unless we provide required notice and controls before doing so.
### G. Cookies, Analytics, And Similar Technologies
We and our service providers may use cookies, local storage, pixels, SDKs, and similar technologies to operate the Services, remember settings, store local preferences, maintain legal acceptance or privacy acknowledgment state, authenticate sessions, secure accounts, detect abuse, improve reliability, measure usage, and support analytics or communications. Strictly necessary cookies, local storage, and similar technologies are used to provide, secure, or remember requested Services.
Non-essential analytics, measurement, advertising, marketing, or similar technologies, if used, are subject to consent, opt-out, or other controls where required by applicable law. Where consent is required, we provide notice before use, do not treat consent as a condition of using strictly necessary Services, and provide a way to withdraw consent that is no more difficult than giving consent. You may also limit cookies or local storage through browser or device settings, but disabling necessary storage may prevent wallet connection, legal acceptance, session authentication, security controls, or other Services from working.
### H. Legal Process And Government Requests
We may collect, preserve, use, or disclose information in connection with subpoenas, court orders, warrants, legal process, regulator requests, law-enforcement requests, sanctions authority requests, tax requests, government inquiries, audits, disputes, or legal claims. Where legally permitted and appropriate, we may notify affected users or publish transparency information, but we may be prohibited from doing so.
## 3. Sources Of Information
We collect information:
* directly from you when you use the Services, connect a wallet, sign messages, place or cancel orders, use APIs, contact us, submit requests, or provide materials;
* automatically from your device, browser, wallet, API client, or network connection;
* from public blockchains, Hedera network records, consensus timestamps, HCS references where used, mirror nodes, explorers, indexers, wallets, RPC providers, and other public or semi-public infrastructure;
* from service providers, analytics providers, error-log providers, security providers, infrastructure providers, compliance providers, sanctions-screening providers, blockchain-analytics providers, geolocation providers, geoblocking providers, and legal or regulatory sources; and
* from counterparties, market participants, bug-bounty participants, security researchers, community channels, or other third parties where permitted and relevant to the Services.
If we receive wallet, transaction, order, or risk information about a person who is not a direct user, we process that information only where we have a lawful basis and provide notices required by applicable law, taking into account whether direct notice is impossible, disproportionate, or would undermine security, compliance, or legal obligations.
## 4. How We Use Information
We may use information for the following purposes:
* provide, operate, maintain, secure, and improve the Services;
* authenticate wallets, users, sessions, API clients, and API keys;
* present and record legal acceptance, privacy acknowledgment, Risk Notice acknowledgment, document versions, document hashes, and jurisdiction or location signals needed for acceptance and compliance evidence;
* build, verify, admit, save, match, route, relay, display, cancel, expire, correct, support Settlement, attempt operational recovery or reconciliation of controlled off-chain records or service state, and reconcile orders;
* derive, use, and retain trading or order strategy inferences from orders, API usage, or interaction patterns for security, abuse prevention, market-integrity risk controls, compliance, reliability, product improvement, and Service operation;
* operate order history, market data, WebSocket feeds, APIs, rate limits, developer support, service health monitoring, reliability monitoring, debugging, incident response, and abuse prevention;
* provide support, respond to inquiries, process feedback, administer bug-bounty or security-reporting programs, and communicate service notices;
* detect, investigate, prevent, and respond to fraud, sanctions evasion, money laundering, terrorist financing, cybercrime, theft, market manipulation, wash trading, spoofing, layering, orderbook disruption, API abuse, and other unlawful or prohibited activity;
* enforce the Terms, protect legal rights, preserve legal defenses, resolve disputes, perform audits, and manage compliance obligations;
* respond to subpoenas, court orders, legal process, regulator requests, law-enforcement requests, sanctions authority requests, and other government requests;
* comply with applicable law, sanctions obligations, tax or accounting obligations, regulatory obligations, and audit obligations;
* protect users, SaucerSwap Labs, the Protocol, the Services, infrastructure providers, third parties, and the public;
* create aggregate, de-identified, or anonymized analytics, reliability, security, and product-improvement information; and
* perform analytics, measure performance, improve user experience, and develop new or improved services.
Operational recovery or reconciliation may affect controlled off-chain records, displays, API responses, or order-history views. It does not modify public blockchain records or guarantee reversal, correction, recovery, cancellation, or Settlement.
Where applicable law gives you a right to object to processing based on legitimate interests, including GDPR Article 21 rights, you may object by contacting `legal@saucerswap.finance`.
This Privacy Policy describes data practices only. It does not expand the Services, create a separate service-level agreement, guarantee data accuracy or availability, create a duty to monitor, detect, prevent, correct, disclose, reverse, reimburse, or notify users of trading or system issues, or create any custody, brokerage, agency, fiduciary, advisory, best-execution, fair-access, market-integrity, or regulated-intermediary duty.
## 5. Legal Bases For European, UK, And Swiss Users
Where GDPR, UK GDPR, Swiss data-protection law, or similar law applies, we do not rely on your acceptance of this Privacy Policy as consent for core Services processing. We process personal data under the legal bases below, depending on the processing activity and jurisdiction.
* Wallet authentication, session issuance, requested API access, order submission, order status, order history, and support you request: primary basis is contract necessity where the processing is objectively necessary to provide the requested Services; additional bases may include legitimate interests in security, reliability, fraud prevention, and legal claims.
* Legal acceptance, Risk Notice acknowledgment, Privacy Policy acknowledgment, versioning, document hashes, acceptance timestamp, wallet address, IP-derived approximate location, and user agent at acceptance: primary basis is legitimate interests in maintaining enforceable acceptance evidence and legal claims; legal obligation applies where applicable law requires recordkeeping.
* Security, abuse prevention, sanctions-risk controls, geoblocking, fraud prevention, market-integrity risk controls, debugging, reliability, and incident response: primary basis is legitimate interests; legal obligation applies where applicable sanctions, security, regulatory, or legal-process rules require processing.
* Trading or order strategy inferences used for security, abuse prevention, market-integrity risk controls, compliance, reliability, product improvement, and Service operation: primary basis is legitimate interests; legal obligation applies where applicable law requires processing; consent applies where required for a specific non-essential processing activity.
* Legal process, regulatory cooperation, audits, disputes, tax or accounting, sanctions obligations, and legal claims: primary basis is legal obligation where applicable law requires processing and legitimate interests where processing is needed to establish, exercise, or defend legal claims.
* Non-essential analytics, measurement, marketing communications, advertising technologies, or sensitive-data processing where required by law: primary basis is consent, unless applicable law permits another basis and required notices and controls are provided.
Before relying on legitimate interests for material production processing in the EEA, UK, or Switzerland, we assess the relevant legitimate interest, necessity, balancing factors, safeguards, and user rights. We do not rely on vital interests or public-task/public-interest legal bases for ordinary security, fraud-prevention, or incident-response processing.
We do not intentionally collect special-category data under GDPR Article 9. If you provide special-category data to us, or if processing special-category data becomes necessary for legal claims, substantial public interest, explicit consent, or another permitted basis, we process it only where a valid Article 9 condition and other required safeguards apply.
Automated and assisted screening may affect access to the Services. We may use automated tools to classify wallet-risk, sanctions, restricted-jurisdiction, geolocation/geoblocking, fraud, abuse, API-abuse, and market-integrity signals. The logic may consider wallet or account identifiers, transaction and order patterns, IP-derived approximate location, device and network signals, sanctions or restricted-party data, blockchain analytics, and abuse or security signals. The consequences may include blocked access, delayed orders, rejected orders, rate-limited API access, disabled API keys, denied protected endpoints, or manual review. Where applicable law gives you rights related to automated decision-making or profiling, including GDPR Article 22 rights, you may request human review, contest the decision, express your point of view, and obtain information about the decision by contacting `legal@saucerswap.finance`. We aim to respond within one month for GDPR-scope requests, subject to permitted extensions.
Where EU or UK law requires appointment of an EU or UK representative for a covered Service, we will identify that representative in this Policy or a linked privacy notice before intentionally offering that covered Service in the relevant scope. If a representative has not been identified for a covered jurisdiction where one is legally required, protected access may be restricted until the required notice is provided. If we appoint a Data Protection Officer, we will identify the DPO's contact details in this Policy or a linked notice.
Where EU, UK, or Swiss data-protection law applies, you may have the right to lodge a complaint with a supervisory authority.
## 6. How We Disclose Information
We may disclose information to:
* cloud, hosting, database, logging, analytics, error-monitoring, security, infrastructure, CDN, wallet-connectivity, RPC, mirror-node, indexer, API, and communications providers;
* compliance, sanctions-screening, blockchain-analytics, fraud-prevention, geolocation, geoblocking, and security vendors;
* legal counsel, auditors, insurers, accountants, consultants, bug-bounty administrators, security researchers, and incident-response providers;
* courts, regulators, law enforcement, sanctions authorities, tax authorities, self-regulatory organizations, government agencies, and other authorities;
* affiliates, personnel, authorized contractors, and service providers who need access for operations, security, compliance, investigation, reconciliation, legal, or support purposes;
* counterparties, market participants, market makers, liquidity providers, API counterparties, or infrastructure providers only where transaction or order state is public, operationally necessary, or needed for reconciliation, compliance, investigation, security, dispute resolution, or operation of the Services;
* affiliates, successors, acquirers, or business partners in connection with a merger, financing, corporate transaction, restructuring, sale of assets, or similar transaction, with notice where required by law; and
* other persons with your direction or consent.
We require service providers and processors that process personal information for us to use written terms designed to restrict their processing to our instructions or permitted purposes, require confidentiality and security measures, restrict retention, use, sale, sharing, or disclosure except as permitted, assist with rights requests, security, deletion, audits, and compliance where applicable, and meet Article 28 processor requirements where GDPR or UK GDPR applies.
We maintain or require contractual, technical, operational, access-control, logging, confidentiality, and misuse-prevention controls for non-public order and trading information. Non-public signed order payloads, order intent, API strategy data, or wallet-linked trading history may be disclosed only where public, directed by you, legally required, operationally necessary for the requested Service, or needed for reconciliation, compliance, investigation, security, dispute resolution, or operation of the Services, and subject to applicable confidentiality, access, and misuse restrictions.
As of the Last modified date above, we do not sell personal information for money, do not share personal information for cross-context behavioral advertising, and do not process personal information for targeted advertising. We do not knowingly sell or share personal information of users under 16 or use it for targeted advertising unless applicable law permits it and the required opt-in or parental consent has been obtained. If we begin any sale, sharing, targeted advertising, or use of advertising technologies that requires opt-out controls, we will provide required notices and controls, including a "Do Not Sell or Share My Personal Information" or equivalent mechanism in the website footer, privacy settings, cookie controls, or another legally compliant location before enabling that processing.
We honor legally recognized opt-out preference signals, including Global Privacy Control, for users in jurisdictions where those signals must be honored. We do not sell, share, or process personal information for targeted advertising after receiving a valid opt-out preference signal, except as permitted by applicable law.
Where legally permitted and appropriate, we may notify affected users about legal process or government requests, but we may be prohibited from doing so or may delay notice to preserve security, compliance, investigations, or legal rights.
## 7. Public Networks And Deletion Limits
Some wallet, order, transaction, HCS-reference, mirror-node, explorer, indexer, Settlement, and public-chain data may be public, immutable, independently retained, or outside our control. We cannot delete, alter, or prevent third parties from processing public blockchain records, HCS references where used, consensus timestamps, mirror-node data, explorer copies, third-party indexer copies, wallet records, RPC records, counterparty records, regulator records, or analytics-provider records that are outside our control.
Disconnecting a wallet, clearing browser storage, deleting local settings, revoking a cookie, or submitting a deletion request does not delete public-chain records, HCS references where used, third-party copies, or records we retain where retention is required or permitted for legal obligations, legal claims, security, abuse prevention, fraud prevention, sanctions compliance, regulatory cooperation, disputes, audits, backups, or other grounds recognized by applicable law.
Legal acceptance records, Risk Notice acknowledgment records, Privacy Policy acknowledgment records, document version records, document hashes, acceptance timestamps, wallet addresses, IP-derived approximate location at acceptance, and related user-agent evidence may be retained even after a deletion request where retention is needed to establish, exercise, or defend legal claims, comply with legal obligations, prove acceptance, prevent abuse, or satisfy regulatory, audit, sanctions, or dispute obligations.
When we honor a deletion request, we will delete, de-identify, or restrict personal information in controlled off-chain systems where required and feasible, including support records, account or API metadata, legal acceptance metadata, order-history views, analytics identifiers, and operational logs, subject to legally permitted retention. We will also instruct processors and service providers to delete, de-identify, or restrict personal information where required by applicable law and feasible. Deletion from controlled off-chain systems may not remove public-chain records, HCS references where used, third-party records, historical backups before overwrite, or information retained in legally restricted archives.
Restricted archives are limited-access records preserved for legal, security, compliance, audit, dispute, investigation, backup, or legal-defense purposes. We restrict use of those archives to the purpose for which they are retained and delete, de-identify, or overwrite them when the retention basis expires or the backup cycle completes.
## 8. Retention
We retain information for as long as necessary or appropriate for the purposes described in this Privacy Policy, including to provide and secure the Services, reconcile orders, maintain order history, debug incidents, prevent abuse, comply with law, respond to legal process, cooperate with regulators or law enforcement, resolve disputes, perform audits, maintain backups, enforce the Terms, and establish or defend legal claims.
Retention periods depend on the category of information, sensitivity, operational need, legal need, security risk, volume, relationship to public-chain data, and applicable law. We generally retain session and JWT logs for up to 90 days; API and WebSocket request logs for up to 12 months; order lifecycle, Settlement-support, and legal acceptance or privacy acknowledgment records for up to 7 years after the later of terminal order state, last protected access, API key deactivation, account closure, dispute closure, or legal hold release; security, sanctions, abuse, investigation, legal-process, and dispute records for up to 7 years after closure; support and bug-bounty records for up to 3 years; and backups until overwritten in the ordinary backup cycle, generally within 90 days.
"Last protected access" means the last time a wallet, account, API key, session, or client accessed a protected Orderbook Service, API, market-maker program, gated interface, or other access path requiring current legal acceptance. Session logs, API logs, and reliability records may be promoted to longer incident, security, investigation, or dispute retention if they become relevant to a security incident, abuse investigation, legal process, regulatory request, sanctions review, dispute, or legal claim.
We may retain longer where necessary for legal claims, sanctions, audits, investigations, regulatory requests, legal holds, or legal process. We periodically review retained records, restrict access where retention is still required, and delete, de-identify, aggregate, or overwrite records when retention is no longer necessary and deletion is technically feasible.
## 9. Security
We use technical, administrative, and organizational measures designed to protect information, including access controls, role-based permissions, logging, confidentiality obligations, encryption in transit where supported, encryption or protected storage at rest where appropriate, secret redaction or hashing in persistent systems, vulnerability management, incident-response processes, service-provider diligence, and misuse-prevention controls for non-public order and trading information.
No system is completely secure. We do not guarantee that information will be secure, uninterrupted, or free from unauthorized access, loss, misuse, alteration, or disclosure. You are responsible for securing your wallet, private keys, seed phrases, devices, accounts, and credentials.
If we become aware of a personal-data breach or security incident that triggers notification obligations, we will notify affected individuals, regulators, processors, controllers, or other required parties as required by applicable law, including within applicable statutory timelines. Security researchers and users may report vulnerabilities or suspected data incidents by contacting `legal@saucerswap.finance` with "Security" in the subject line or through any published bug-bounty or security-reporting channel.
## 10. Your Choices And Privacy Rights
Depending on your location and applicable law, you may have rights to access, correct, delete, restrict, object to, or receive a portable copy of personal information; withdraw consent; opt out of sale, sharing, targeted advertising, certain profiling, or certain automated decision-making; limit certain uses of sensitive personal information; appeal a rights-request denial; receive non-discriminatory treatment for exercising rights; file a complaint with a regulator; or lodge a complaint with a supervisory authority.
You may contact us at `legal@saucerswap.finance` to exercise rights. If processing is based on consent, you may withdraw consent through the same interface where available, through cookie or privacy controls where available, by using unsubscribe links for marketing communications, or by contacting us. Withdrawal does not affect processing that occurred before withdrawal or processing based on another legal basis.
We may need to verify your identity and authority before responding. Verification may include confirming control of an email address, wallet address, API client, signed message, request details, or other information reasonably related to the request. We will not require you to create a new account solely to submit a request, and we will not use verification procedures that are unreasonable or designed to prevent exercise of rights.
We generally respond to GDPR, UK GDPR, and Swiss requests within one month, subject to permitted extensions. We generally respond to California and other U.S. state privacy requests within 45 days, subject to permitted extensions. If we deny a request where an appeal right applies, we will explain how to appeal. You may appeal by replying to our denial or contacting `legal@saucerswap.finance` with "Privacy Appeal" in the subject line. We aim to respond to appeals within 60 days or the timeframe required by applicable law.
We may deny or limit requests where permitted by law, including where information is public-chain data, outside our control, necessary for legal obligations, legal claims, security, abuse prevention, sanctions compliance, fraud prevention, order reconciliation, legal acceptance evidence, compliance, dispute, audit, backup, or other legally recognized retention grounds.
We do not discriminate against you for exercising privacy rights. We will not deny Services, charge different prices, provide a different quality of Services, or retaliate because you exercised a privacy right, except where the difference is reasonably related to the value of the data or permitted by law.
## 11. California And U.S. State Notice At Collection
Residents of California and certain other U.S. states may have additional rights under applicable privacy laws, including the right to know or access categories and specific pieces of personal information, delete personal information, correct inaccurate personal information, opt out of sale, sharing, targeted advertising, certain profiling, or certain automated decision-making, limit certain uses of sensitive personal information, receive non-discriminatory treatment, and appeal certain decisions.
For the 12 months before the Last modified date above, the categories of personal information we may have collected are described below. Sources, purposes, disclosures, and retention are described in Sections 2 through 8. We do not sell personal information for money. As of the Last modified date above, we do not share personal information for cross-context behavioral advertising and do not process personal information for targeted advertising. We disclose personal information for business purposes to the categories of recipients described in Section 6.
* Identifiers: wallet address, Hedera account ID, public key, API client ID, session ID, legal acceptance event ID, email or handle you provide. Purposes include authentication, legal acceptance, support, security, compliance, dispute handling, and Service operation. Retention is described in Section 8.
* Internet or electronic network activity: IP address, user agent, endpoint logs, WebSocket logs, usage events, cookie or local storage identifiers, app or analytics identifiers. Purposes include Service operation, security, analytics, abuse prevention, reliability, and legal acceptance. Retention is described in Section 8.
* Commercial and transaction information: orders, order status, fills, cancellations, expirations, fees, Settlement references, transaction IDs, API usage, and order history. Purposes include Orderbook operation, Settlement support, order history, reconciliation, security, disputes, and compliance. Retention is described in Section 8.
* Approximate geolocation: approximate location derived from IP address or acceptance location signal. Purposes include geoblocking, sanctions, abuse prevention, security, and legal compliance. We do not intentionally request precise geolocation unless separate notice and required controls are provided.
* Inferences and risk signals: wallet-risk, fraud, abuse, sanctions, market-manipulation, reliability, compliance, or strategy inferences. Purposes include security, sanctions, fraud and abuse prevention, market-integrity risk controls, legal compliance, and Service reliability.
* Sensitive personal information where applicable: precise geolocation if ever collected, government ID, biometric information, criminal-history information, special-category data, or other sensitive data only if you provide it or where required for legally permitted compliance, security, support, legal process, fraud prevention, or similar purposes. We do not use sensitive personal information to infer characteristics except where permitted by law.
If we use sensitive personal information in a way that gives you a right to limit its use or disclosure, we will provide a "Limit the Use of My Sensitive Personal Information" or equivalent mechanism. If we begin any sale, sharing, targeted advertising, or use of advertising technologies that requires opt-out controls, we will provide a "Do Not Sell or Share My Personal Information" or equivalent mechanism in the website footer, privacy settings, cookie controls, or another legally compliant location before enabling that processing. We honor recognized opt-out preference signals, including Global Privacy Control, for users in applicable jurisdictions.
If we have actual knowledge that a user is under 16, we will not sell or share that user's personal information or use it for targeted advertising unless applicable law permits it and the required opt-in or parental consent has been obtained. Authorized agents may submit requests where permitted by law. We may require signed authorization, proof of authority, identity verification, and direct confirmation from the user where permitted by law.
We may use automated or assisted tools to classify wallet-risk, sanctions, restricted-jurisdiction, geolocation/geoblocking, fraud, abuse, API-abuse, and market-integrity signals. The consequences may include blocked access, delayed orders, rejected orders, rate-limited API access, disabled API keys, denied protected endpoints, or manual review. The main factors may include wallet or account identifiers, transaction and order patterns, IP-derived approximate location, device and network signals, sanctions or restricted-party data, blockchain analytics, and abuse or security signals. Where applicable law gives you rights related to automated decision-making or profiling, you may request human review, contest the decision, express your point of view, and obtain information about the decision by contacting `legal@saucerswap.finance`.
This Section is intended to cover applicable U.S. state privacy laws, including California, Colorado, Connecticut, Virginia, Texas, Montana, Oregon, Delaware, Iowa, Indiana, Tennessee, and other state laws where they apply. State-specific rights may vary.
## 12. International Transfers
We are based in the United States and may process information in the United States and other countries. Those countries may have data protection laws different from those in your jurisdiction and may allow government, law-enforcement, national-security, or regulatory access under local law.
Where required for transfers from the EEA, UK, or Switzerland to countries without an adequacy decision, we use appropriate transfer mechanisms. For processor transfers, these may include the European Commission Standard Contractual Clauses controller-to-processor module, the UK International Data Transfer Addendum or International Data Transfer Agreement, the Swiss addendum or Swiss-law adaptations, and transfer impact assessments where required. For controller-to-controller transfers, these may include the applicable controller-to-controller Standard Contractual Clauses module and related safeguards. Where a provider participates in the EU-U.S., UK Extension, or Swiss-U.S. Data Privacy Framework and we rely on that participation, we verify that the certification appears current before onboarding and periodically thereafter. Transfer impact assessments support SCC-based transfers; they are not treated as a standalone transfer mechanism.
Public blockchain and Hedera network infrastructure, HCS consensus records, mirror nodes, explorers, RPC providers, wallets, validators, and other network participants may be operated from or accessible in multiple jurisdictions. Transfers inherent in your use of public or third-party network infrastructure may be outside our control.
Users in countries with data localization, transfer, or cross-border processing rules may have additional rights or restrictions. We assess and apply those rules where they apply to our controlled processing.
You may request information about, or a copy of, applicable transfer safeguards by contacting `legal@saucerswap.finance`.
## 13. Children
The Services are not intended for children or minors. You may not use the Services if you are under 18. We do not knowingly collect personal information from children under 13, under 16 for GDPR-scope users unless a lower member-state age applies, or under the minimum age of digital consent in the applicable jurisdiction.
We rely on eligibility representations, legal acceptance controls, and other reasonable measures appropriate to the Services to help prevent underage use, but those measures are not perfect. If we learn that we collected personal information from a child in violation of applicable law, we will take reasonable steps to delete or restrict that information promptly. Any retention of such information will occur only if required by law or approved for a specific legal, safety, or compliance reason.
If you believe a child has provided personal information to us, contact us at `legal@saucerswap.finance`.
## 14. Third-Party Services
The Services may link to or interoperate with Third-Party Services. Third-Party Services have their own privacy practices. We are not responsible for those practices. You should review the privacy policies and terms of Third-Party Services before using them.
When you connect or use a wallet, the wallet provider may receive information about your interaction with the Services, including site URL, session context, transaction data, wallet address, and signed messages. Wallet provider data practices are outside our control.
When you submit transactions, orders, or network calls, RPC providers, mirror nodes, indexers, explorers, public networks, and validators may receive transaction data, wallet addresses, metadata, and network calls. This processing may occur independently of SaucerSwap Labs and may be public, immutable, or globally accessible.
If you interact with us through Discord, Telegram, X, email, support forms, bug-bounty platforms, app stores, wallets, or other community or support channels, we may process your handle, profile information visible in that channel, message contents, attachments, timestamps, moderation signals, support history, security-report details, and related operational metadata. Those channels may be operated by third parties with their own privacy practices, and public or shared-channel messages may be visible to others.
SaucerSwap Labs personnel, moderators, contractors, or service providers may monitor, screenshot, log, preserve, or use community-channel messages for support, moderation, compliance, investigation, security, market-integrity risk controls, dispute handling, or legal purposes where permitted by law and platform rules.
Current third-party provider categories may include hosting and cloud infrastructure, analytics and measurement, error monitoring, security, compliance and sanctions screening, blockchain analytics, geolocation or geoblocking, RPC and network infrastructure, mirror nodes and indexers, wallets, communications, support, bug-bounty administration, professional advisers, and community platforms. Where applicable law requires named provider or sub-processor information, we provide it through a linked notice, privacy or legal page, contract notice, or request process.
## 15. Changes To This Privacy Policy
We may update this Privacy Policy from time to time. We will update the "Last modified" date when we do.
Material privacy changes include changes that materially affect categories of personal information collected, purposes of processing, legal bases, retention periods, recipient categories, sale, sharing, targeted advertising, profiling, automated decision-making, international transfer mechanisms, privacy rights, or other processing that a reasonable user would consider important. For material privacy changes, we will provide additional notice, re-notification, renewed acknowledgment, or consent where required by applicable law. For purely editorial, formatting, clarification, or non-material updates, we may post the updated Policy without separate re-notification where applicable law permits it.
Where consent is required for new or changed processing, we will obtain consent before beginning that processing and will provide a way to withdraw consent. If you withdraw consent or do not provide required consent, the affected non-essential processing will not occur, but core Services may continue where another legal basis applies.
We may maintain prior versions, version identifiers, document hashes, or acceptance records to identify which Policy version applied at a given time. Where required or appropriate, we may provide access to prior versions through a "Previous versions" notice, legal page, request process, or acceptance record.
## 16. Contact
If you have questions or requests, contact:
SaucerSwap Labs, Inc.
Attn: Legal
63 Federal Street, Unit #349
Portland, ME 04101
Email: `legal@saucerswap.finance`
Privacy rights, legal, and security requests may be sent to `legal@saucerswap.finance`. For security reports, include "Security" in the subject line or use any published bug-bounty or security-reporting channel.
As of the Last modified date above, SaucerSwap Labs has not identified a Data Protection Officer in this Policy. If a DPO is appointed or required for a covered Service, we will identify the DPO's contact details in this Policy or a linked notice. If an EU or UK representative is required for a covered Service, we will identify the representative's contact details in this Policy or a linked notice before intentionally offering that covered Service in the relevant scope.
# Terms of Service
Source: https://docs.saucerswap.finance/legal/terms-of-service
The terms and conditions governing access to SaucerSwap Labs services, including the web app, APIs, Orderbook Services, and market-maker access.
Last modified: May 29, 2026
These Terms of Service (the "Terms") explain the terms and conditions by which you may access or use the Services provided by SaucerSwap Labs, Inc., a Delaware corporation ("SaucerSwap Labs," "we," "our," or "us"). These Terms incorporate our Privacy Policy, any V3 Orderbook Risk Notice presented to you, any API, market-maker, or enterprise terms that apply to your access, and any supplemental terms presented for a Service by reference. Please read these Terms, the Privacy Policy, any applicable risk notice, and any supplemental terms carefully.
By accessing or using the Services, connecting a wallet, clicking an "I agree" or similar control, placing or saving an order, using any Orderbook Services, using any application programming interface ("API"), creating or using any API key, or continuing to use the Services after we present or post updated Terms, you agree to these Terms. Passive continued use after posting may be used only for non-material updates where applicable law permits it. For material updates, continued use does not replace required affirmative acceptance or acknowledgment. Material updates include changes that materially affect eligibility, restricted persons or jurisdictions, protected V3 access rules, orderbook risk, data processing, fees, arbitration, class waivers, liability limitations, releases, indemnities, API access, or other rights or obligations that a reasonable user would consider important.
Before any production V3 Orderbook Services, API keys, market-maker access, or other protected orderbook or API access is enabled, SaucerSwap Labs requires current server-side Terms acceptance, V3 Orderbook Risk Notice acceptance, and Privacy Policy acknowledgment for the applicable access path. We may record evidence of acceptance and acknowledgment as described in the Privacy Policy.
Any V3 Orderbook Risk Notice, API terms, market-maker terms, enterprise agreement, or other supplemental terms presented for a Service are incorporated into these Terms for that Service. If a supplemental term or Risk Notice conflicts with these Terms, the more specific term controls only for the covered access, risk, or activity. The Privacy Policy controls with respect to personal information processing. These Terms control with respect to contractual service access, risk allocation, dispute resolution, and other non-privacy matters unless a more specific supplemental term expressly controls.
No API documentation, market-maker program, incentive schedule, fee schedule, support message, Discord message, product documentation, integration guide, community message, or other commercial communication creates a custody, brokerage, agency, fiduciary, advisory, best-execution, fair-access, market-integrity, market-making, clearing, or settlement-as-intermediary duty unless an officer of SaucerSwap Labs expressly agrees to that specific duty in a signed written agreement or SaucerSwap Labs publishes an official regulatory notice or updated Terms stating that duty. No commercial communication creates, waives, or determines any regulatory-registration obligation; any registration, licensing, exemption, no-action, or regulatory-status position depends on applicable law and, where SaucerSwap Labs makes a public status representation, an official regulatory notice or updated Terms.
## 1. The Services
References to "SaucerSwap," "DEX," "exchange," "swap," "pool," "market," "orderbook," or similar terms are product or technical descriptions only. They are not representations that SaucerSwap Labs or any Service is registered, licensed, or regulated as a securities exchange, commodities exchange, swap execution facility, designated contract market, alternative trading system, clearing agency, broker, dealer, futures commission merchant, money transmitter, custodian, fiduciary, adviser, market maker, registered or regulated execution venue, or any similar regulated intermediary.
The "Services" include:
* the website-hosted user interface at `https://saucerswap.finance` and any other domain or interface that links to these Terms;
* any mobile application, widget, browser-accessible interface, white-label interface, embedded interface, partner-hosted interface, third-party-hosted interface, or front-end graphical user interface that we make available or authorize and that links to, incorporates, or presents these Terms;
* APIs, software development kits, documentation, developer tools, market-data tools, and related services;
* order-entry tools, off-chain orderbook interfaces, matching-engine infrastructure, order relay, order admission, order validation, order-status services, market-data services, WebSocket feeds, API services, order verification tools, and Settlement-Support Software related to SaucerSwap V3 or other orderbook-based features (the "Orderbook Services"); and
* related software, content, communications, support, security, compliance, analytics, and operational services, in each case as reasonably incidental to the foregoing.
The Services may help users interact with smart contracts, distributed ledger networks, wallets, third-party services, market-data sources, or other software systems. The Services may change over time. We may add, remove, suspend, restrict, replace, or modify any Service at any time.
References to a "Service" mean any one of the Services. References to an "Orderbook Service" mean any one component, feature, API, interface, tool, feed, workflow, or access path included in the Orderbook Services.
## 2. Definitions
"Approved Non-Custodial Access Path" means an access path that SaucerSwap Labs makes available for a user, API client, market maker, filler, or other participant to interact with the Services through self-custodial wallet signatures, authorized API credentials, or other non-custodial authentication or authorization methods. An Approved Non-Custodial Access Path does not transfer custody of Digital Assets or private keys to SaucerSwap Labs.
"Digital Asset" means any token, coin, stablecoin, payment stablecoin, crypto asset, virtual currency, digital collectible, digital tool, smart-contract right, or other blockchain-based or distributed-ledger-based asset or instrument, including an asset that may be treated under applicable law as a security, commodity, digital commodity, payment instrument, derivative, or other regulated or unregulated instrument depending on the facts and applicable law. Inclusion in this definition, availability through the Services, or display in any interface does not constitute a regulatory-status determination, listing standard, endorsement, or representation that the asset is lawful for any person or jurisdiction.
"Orderbook Services" has the meaning given in Section 1 and includes off-chain and on-chain components used to prepare, admit, validate, store, match, relay, display, cancel, expire, reconcile, or support Settlement of orders.
"Protocol" means smart contracts, distributed ledger components, on-chain settlement components, and related open-source or decentralized systems that the Services may help users access.
"Restricted Person" means any person or entity that, at the time of each access, order, transaction, attempted transaction, API request, or other use of the Services, is subject to sanctions, located in a restricted jurisdiction, organized in a restricted jurisdiction, owned or controlled by a sanctioned person, identified on a restricted-party list, or otherwise prohibited from using the Services under these Terms or applicable law.
"Settlement" means the on-chain, network, smart-contract, wallet, or other final or attempted state change, transfer, confirmation, reconciliation, or settlement-support outcome associated with an order, transaction, cancellation, expiration, or related activity.
"Settlement-Support Software" means software, infrastructure, tools, relayers, fillers, queues, indexers, reconciliation processes, transaction-preparation flows, transaction-submission flows, and related operational systems used to support, attempt, track, reconcile, or display Settlement.
"Third-Party Services" means wallets, RPC providers, mirror nodes, indexers, explorers, bridges, oracles, cloud providers, analytics tools, security vendors, token issuers, stablecoin issuers, market makers, liquidity providers, solvers, relayers, fillers, API participants, blockchains, app stores, and other products, services, software, infrastructure, or data not controlled by SaucerSwap Labs.
## 3. Eligibility And Authority
You may use the Services only if you can form a legally binding contract with us and only if you are at least 18 years old. In no event may you use the Services if you are under 18, even if your local law would otherwise allow a lower age for contract or digital-consent purposes.
If you use the Services on behalf of an entity, you represent that you have authority to bind that entity, that the entity is duly organized and in good standing where required, that the entity is not a Restricted Person, that the entity is not organized in or operating from a restricted jurisdiction, and that the entity's use of the Services complies with these Terms and applicable law.
You represent that you and any entity on whose behalf you use the Services are eligible to use the Services, are not Restricted Persons, are not using the Services for a Restricted Person, and will use only Approved Non-Custodial Access Paths unless we expressly authorize another access path in writing.
The Services are not intended for children or minors. We do not knowingly collect personal information from children under 13, under 16 for GDPR-scope users unless a lower member-state age applies, or under the minimum age of digital consent in the applicable jurisdiction.
## 4. Restricted Persons, Jurisdictions, And Sanctions
You may not use the Services if:
* you are located in, organized in, ordinarily resident in, or accessing the Services from a jurisdiction or territory subject to comprehensive sanctions, embargoes, or other restrictions under then-current official sanctions programs, restricted-party lists, export-control rules, or a restricted-jurisdiction notice presented by SaucerSwap Labs;
* you are identified on, owned by, controlled by, acting for, or acting on behalf of any person identified on any sanctions, restricted-party, denied-party, blocked-person, export-control, or similar list maintained by the United States, United Nations, European Union, United Kingdom, or other applicable authority as those lists exist at the time of each access, order, transaction, or attempted use;
* your wallet, account, funds, transaction, order, or activity is associated with sanctions, ransomware, cybercrime, money laundering, terrorist financing, fraud, market manipulation, theft, exploitation, or other unlawful activity; or
* your use would cause SaucerSwap Labs, any user, any infrastructure provider, or any other person to violate applicable law.
Restricted jurisdictions and official sanctions programs change over time. You are responsible for checking the then-current restrictions that apply to you, including official sanctions, export-control, and restricted-party lists and any restricted-jurisdiction notice presented through the Services or legal acceptance flow. We may update restricted-jurisdiction notices, geoblocking, screening, or access controls without advance notice where legal, sanctions, compliance, security, or operational concerns require it.
You may not use the Services to evade sanctions, violate export controls, conceal proceeds, launder funds, finance terrorism, facilitate cybercrime, bypass geoblocking, obscure your location, or cause any person to violate applicable law. You may not use VPNs, proxies, Tor, relay networks, privacy networks, device-spoofing, location-spoofing, or other obfuscation or anonymization technology to circumvent restrictions we apply.
We may screen wallets, locations, devices, API usage, transactions, orders, or other activity. We may block, restrict, suspend, terminate, reject, delay, rate-limit, or require additional information for any access or activity where we determine that legal, regulatory, sanctions, compliance, security, abuse-prevention, automated-risk, or operational concerns exist. The Privacy Policy describes automated and assisted screening, profiling, human-review rights, and privacy rights that may apply to those controls.
## 5. Self-Custody, Wallets, And Private Keys
The Services are designed to be non-custodial. SaucerSwap Labs does not store your private keys or seed phrases, does not have access to your encrypted or decrypted private keys, does not hold Digital Assets for you, and does not exercise control over any private key or Digital Asset at any point.
You are solely responsible for your wallet, private keys, seed phrases, hardware wallet, software wallet, wallet provider, third-party key management system, wallet credentials, device security, approvals, allowances, signatures, transactions, orders, account security, and use of any Approved Non-Custodial Access Path. We cannot restore lost keys, recover seed phrases, reverse blockchain transactions, guarantee wallet software or hardware behavior, guarantee third-party key-management behavior, or prevent losses caused by wallet compromise, phishing, malicious software, social engineering, support impersonation, user error, or Third-Party Services.
Orderbook Services may process signed order data, signatures, wallet addresses, and related metadata. Processing that information does not mean SaucerSwap Labs takes custody of your private keys or Digital Assets.
## 6. User Orders, Signatures, Approvals, And Cancellations
You are solely responsible for reviewing every wallet prompt, transaction, approval, token association, signed message, typed-data payload, signature mode, signature prefix, EIP-712 payload, Hedera personal-sign payload, order-verification metadata, order payload, order side, order type, maker or taker status, token address, amount, price, slippage setting, fee, fee cap, deadline, time-in-force, recipient, hook or custom logic, allowance, cancellation request, expiration setting, and displayed risk before signing or submitting it.
Signed orders, signatures, approvals, allowances, and related metadata may remain valid until expiration, cancellation, revocation, or another terminal state. Approvals or allowances may permit spending up to high or maximum amounts until you revoke them. Cancellations and expirations are distinct lifecycle events. A cancellation, expiration, revocation, or deadline may not be immediate, may fail, may be delayed, may not reach every relevant system, or may arrive too late to prevent matching, execution, Settlement, or settlement-support activity.
A displayed cancellation, expiration, order status, fill status, balance, or settlement status may be provisional, delayed, stale, incorrect, or inconsistent across the interface, API, WebSocket feed, wallet, explorer, mirror node, indexer, and public network. You acknowledge and agree that no interface or API status is final until confirmed by the relevant on-chain or otherwise authoritative Settlement state.
Market, one-cancels-the-other ("OCO"), conditional, linked, on-chain-cancel, or other advanced order types may depend on server-stamped time-to-live values ("TTLs") or effective deadlines, trigger logic, linked-cancellation logic, API or maker guides, technical specifications, and on-chain cancellation paths as updated from time to time. The specific behavior of advanced order types is governed by the applicable V3 Orderbook Risk Notice, API documentation, and technical specifications as presented or updated for the relevant access path. Those mechanisms may be delayed, may fail, may expire unexpectedly, may fill after an apparent expiration, or may behave differently from interface estimates.
We are not responsible for losses arising from any order, approval, allowance, signature, cancellation, expiration, token association, wallet prompt, typed-data payload, or transaction that you authorize.
## 7. Orderbook Services And Off-Chain Order System
Orderbook Services may include off-chain and on-chain components. They may depend on smart contracts, public networks, wallets, servers, databases, queues, Redis streams, indexers, mirror nodes, APIs, WebSockets, market-data services, RPC providers, operator accounts, configuration settings, third-party infrastructure, and other systems, including without limitation systems that generate or reference Hedera transaction IDs, consensus timestamps, or Hedera Consensus Service ("HCS") references where applicable.
Orderbook Services are non-custodial software infrastructure. They do not require SaucerSwap Labs to hold your private keys or Digital Assets. Your use of Orderbook Services does not create a brokerage, agency, exchange, clearing, custody, advisory, fiduciary, market-making, money transmission, Settlement, settlement-as-intermediary, or best-execution relationship between you and SaucerSwap Labs.
SaucerSwap Labs does not guarantee that any order will be accepted, displayed, routed, relayed, matched, prioritized, partially filled, fully filled, canceled, expired, rejected, corrected, submitted on-chain, settled, confirmed, recovered, or reflected accurately in any interface, API, database, event stream, WebSocket feed, indexer, mirror node, wallet, explorer, or public network.
Orders may be queued, throttled, dropped, rejected, duplicated in display or processing, mis-sequenced, corrected, canceled, expired, partially filled, overfilled, underfilled, filled more than once, filled after an apparent terminal state, filled at unexpected times, filled at prices or amounts within signed parameters but different from interface estimates, matched against another order, matched against SaucerSwap automated market maker ("AMM") liquidity or another backstop liquidity source made available by the then-current V3 configuration, not matched, not settled, or settled after a delay.
Order admission, matching, maker or taker classification, queue priority, tie-breakers, minimum sizes, tick sizes, time-in-force handling, cancellation handling, expiration handling, self-trade controls, backstop-liquidity logic, throttles, and halt behavior may be determined by smart-contract rules, matching-engine code, API documentation, configuration settings, operational controls, and third-party infrastructure as they exist at the relevant time. We may change those rules, settings, and controls prospectively or, where we determine necessary, immediately for legal, security, operational, abuse-prevention, or market-integrity reasons.
These controls are operational and non-discretionary as applied to signed economic parameters unless we expressly state otherwise. They do not authorize SaucerSwap Labs to change the signed price, amount, asset, side, or recipient terms of an order. These rules and controls may affect users differently and do not guarantee equal latency, equal access, priority, fill, cancellation, expiration, or Settlement.
Orderbook Services and public networks may expose orders, transactions, market data, or inferred trading interest to other users, counterparties, validators, relayers, fillers, market makers, liquidity providers, analytics providers, bots, searchers, or other observers. You assume risks of front-running, sandwiching, latency arbitrage, adverse selection, copy trading, inference from public or semi-public data, and other market behavior, whether arising on-chain, off-chain, through APIs, through WebSocket feeds, through HCS references where used, through mirror-node or indexer data, or through third-party systems.
SaucerSwap Labs, its affiliates, personnel, contractors, service providers, market makers, liquidity providers, and API participants may not use non-public user order information for undisclosed preferential trading, front-running, market manipulation, or other misuse. Any access to non-public order information must be limited to what SaucerSwap Labs determines is reasonably necessary for operations, compliance, security, investigation, reconciliation, support, legal process, regulatory cooperation, or dispute handling and must be subject to applicable confidentiality, access, and misuse restrictions.
## 8. No Best Execution Or Market Integrity Warranty
The Services do not provide, and SaucerSwap Labs does not undertake, any duty of best execution, price improvement, price protection, quote protection, order priority, fair access, continuous trading, market making, liquidity-provision or market-making obligations, regulated market surveillance service, market-integrity warranty, uptime, cancellation, recovery, reimbursement, notification, custodial Settlement, guaranteed Settlement, or Settlement as a regulated intermediary. Any monitoring, controls, alerts, reviews, restrictions, or interventions we perform are discretionary operational, security, legal, compliance, abuse-prevention, automated-risk, or market-integrity risk controls, and do not create a duty to detect, prevent, correct, disclose, reverse, or compensate any trading activity or system condition.
Any orderbook, quote, price, depth, spread, trade, volume, status, route, pool, balance, fee, risk, warning, analytics, or market-data display is provided for informational purposes only and may be stale, incomplete, inaccurate, delayed, unavailable, or inconsistent with on-chain state, off-chain state, internal systems, third-party systems, or actual execution or Settlement outcomes. Section 20 explains that the Services do not provide investment, trading, legal, tax, accounting, financial, regulatory, custody, fiduciary, or other professional advice.
Different interfaces, APIs, WebSocket feeds, market-data feeds, users, regions, devices, infrastructure providers, and access programs may receive or display information at different times or with different latency, completeness, refresh rates, precision, or availability. We do not provide, and do not commit to provide, a consolidated tape, latency-equalized feed, market-data parity guarantee, or guarantee that any displayed market data is the same data available to any other person or system.
Any reference to "best price," "optimal," "route," "execution," "settlement," "liquidity," or similar language is not a representation, warranty, recommendation, or guarantee of best execution, best price, availability, priority, timing, fill, cancellation, expiration, or Settlement.
## 9. Spot Only; No Derivatives, Margin, Or Financing
The Services are intended only for spot, non-leveraged, non-margined Digital Asset transactions initiated by users or authorized API, market-maker, filler, or other approved participants through self-custodial wallets, accounts, or Approved Non-Custodial Access Paths.
You may not use the Services to create, trade, offer, arrange, or facilitate futures, options, swaps, perpetual contracts, contracts for difference, leveraged transactions, margined transactions, financed retail commodity transactions under Commodity Exchange Act Section 2(c)(2)(D) or similar law, securities lending, short sales, off-chain credit, synthetic exposure, or any other transaction that would require a registration, license, exemption, permission, or authorization that SaucerSwap Labs has not expressly obtained and disclosed in writing.
For purposes of these Terms, "synthetic exposure" means an arrangement designed to create leveraged, financed, margined, derivative, short, or economically derivative exposure to an asset without owning or transferring the asset on a spot basis. The mere display, holding, transfer, or spot transaction of a wrapped token, yield-bearing token, liquidity-pool token, or other Digital Asset through the Services does not by itself mean that you have created prohibited synthetic exposure, but you remain responsible for determining whether your transaction is lawful and permitted.
## 10. Regulatory Status And No Asset Classification
Digital Assets accessible through the Services may be securities, commodities, derivatives, payment stablecoins, other stablecoins, payment instruments, digital commodities, digital collectibles, digital tools, or other regulated or unregulated instruments depending on the facts and applicable law. The regulatory status of Digital Assets, protocols, orderbooks, market-data systems, stablecoins, and digital-asset intermediaries is evolving and may change without notice.
No statement in these Terms, the Services, any interface, documentation, token list, pool, orderbook, market, quote, route, market-data feed, API response, announcement, Discord message, support response, or other communication is a legal determination, investment recommendation, solicitation, endorsement, or representation that any Digital Asset is or is not a security, commodity, digital commodity, permitted payment stablecoin, derivative, or other regulated instrument.
You are solely responsible for determining whether your use of the Services and any Digital Asset transaction is lawful in your jurisdiction and consistent with any legal, tax, regulatory, compliance, contractual, or fiduciary obligations that apply to you. Nothing in these Terms is a representation that any registration, license, exemption, no-action position, safe harbor, or legal classification is available, unnecessary, or applicable to any person, asset, transaction, market, orderbook, or use of the Services.
## 11. No Regulated Intermediary Relationship
Unless SaucerSwap Labs publishes an official regulatory notice or updated Terms stating otherwise, SaucerSwap Labs has not registered with the SEC as a securities exchange, broker, dealer, alternative trading system, clearing agency, transfer agent, or investment adviser; with the CFTC as a designated contract market, swap execution facility, derivatives clearing organization, futures commission merchant, introducing broker, commodity trading adviser, commodity pool operator, retail foreign exchange dealer, or other CFTC-regulated intermediary; with FinCEN as a money services business; or with any state regulator as a money transmitter, custodian, fiduciary, market maker, registered or regulated execution venue, or similar regulated intermediary with respect to the Services. Nothing in these Terms limits any regulator's jurisdiction, our obligation to comply with applicable law, or our ability to register, license, restrict, suspend, or modify Services if required or appropriate.
No regulated intermediary, agency, fiduciary, brokerage, advisory, custody, regulated clearing, custodial Settlement, guaranteed Settlement, Settlement as a regulated intermediary, money transmission, or best-execution relationship is created by your use of the Services.
Nothing in these Terms represents that any registration, license, exemption, no-action position, safe harbor, approval, or authorization is available, unnecessary, or applicable to any person, asset, transaction, market, orderbook, or use of the Services. Nothing in these Terms creates a duty to provide advance notice of confidential regulatory inquiries, enforcement matters, legal process, restrictions, investigations, or proceedings.
No SEC, CFTC, FinCEN, OFAC, Treasury, state, staff, no-action, interpretive, or other agency statement is incorporated into these Terms as a representation that any Service qualifies for any exemption, safe harbor, registration exclusion, no-action position, or particular regulatory status. Some Orderbook Services may include off-chain order admission, validation, storage, matching, relay, market-data, API, and Settlement-support functions that differ from a passive or purely client-side user interface.
SaucerSwap Labs does not provide investment, trading, legal, tax, accounting, financial, custody, escrow, regulated clearing, custodial Settlement, guaranteed Settlement, Settlement as a regulated intermediary, money transmission, redemption, insurance, or fiduciary services. SaucerSwap Labs does not hold, custody, control, guarantee, redeem, back, reserve, or insure your Digital Assets, stablecoins, private keys, wallet credentials, orders, proceeds, or transaction outcomes.
## 12. Token, Pair, Pool, Orderbook, Market, Route, And Stablecoin Availability
The availability of any token, pair, pool, orderbook, market, route, quote, liquidity source, stablecoin, bridge, wallet, or third-party integration through the Services does not constitute an endorsement, recommendation, solicitation, listing standard, legal classification, suitability determination, due-diligence conclusion, reserve review, issuer review, compliance review, or representation regarding safety, value, legality, liquidity, reserve backing, redemption rights, issuer compliance, sanctions status, tax treatment, or regulatory status.
SaucerSwap Labs has no obligation to conduct or disclose due diligence on any token, stablecoin, issuer, bridge, pool, orderbook, market, route, wallet, or integration. Any review we perform is for our own operational, legal, compliance, or security purposes and does not create a duty to users or a warranty that the asset or integration is safe, lawful, liquid, backed, redeemable, or compliant.
SaucerSwap Labs may add, remove, restrict, geoblock, hide, delist, disable, pause, or modify access to any token, pair, pool, orderbook, market, route, quote, liquidity source, stablecoin, bridge, wallet, or integration at any time without liability. We may do so for legal, regulatory, sanctions, compliance, security, operational, liquidity, abuse-prevention, market-integrity, issuer-risk, third-party dependency, or other reasons, and we are not required to provide a specific reason.
SaucerSwap Labs does not issue, redeem, guarantee, back, reserve, custody, or insure any third-party stablecoin or payment stablecoin available through the Services. Any stablecoin issuer, reserve, redemption right, freeze function, blacklist function, transfer restriction, regulatory status, solvency, audit, attestation, or compliance representation is solely the responsibility of the relevant issuer or third party.
References to a stablecoin or payment stablecoin in the Services do not mean that the asset is issued by a permitted payment stablecoin issuer, is available for lawful use by U.S. persons, is subject to any particular reserve, redemption, attestation, supervision, or AML/sanctions regime, or has been approved by Treasury, OCC, Federal Reserve, FDIC, NCUA, SEC, CFTC, FinCEN, OFAC, or any state regulator.
## 13. APIs, Bots, Market Makers, And Developers
If you use any API, WebSocket feed, software development kit ("SDK"), developer tool, API key, market-maker access, or automated access path, you must comply with these Terms, any API documentation, rate limits, usage restrictions, market-maker agreement, bug-bounty rules, or separate written agreement that applies.
API keys and automated access are revocable privileges, not rights. We may monitor usage, impose or change rate limits, throttle traffic, restrict methods, rotate keys, require allowlisting, require additional verification, suspend access, terminate access, change endpoints, change payloads, or discontinue APIs or feeds at any time. Where commercially reasonable and not inconsistent with legal, security, sanctions, abuse-prevention, or operational needs, we will use reasonable efforts to provide advance or prompt notice of material API deprecations, key revocations, or endpoint removals through the interface, developer documentation, API notice, email, or other reasonable means.
Market-maker, liquidity-provider, API, filler, partner, and enterprise participants may receive different credentials, endpoints, rate limits, throughput limits, latency profiles, documentation, support channels, fee tiers, rebates, incentives, data-access terms, or operational terms under separate written programs. These differences do not create any right for other users to receive the same terms and do not create any best-execution, fair-access, fiduciary, agency, or market-integrity duty. SaucerSwap Labs will not intentionally provide non-public user order information to any participant for undisclosed preferential trading, front-running, or market manipulation. Any non-public order information shared with a participant must be limited to what SaucerSwap Labs determines is reasonably necessary for the participant's requested orderbook, routing, Settlement-support, reconciliation, compliance, security, investigation, support, or dispute-resolution function and subject to applicable confidentiality, access, and misuse restrictions.
You may not:
* scrape, crawl, or harvest data except through documented access paths we authorize;
* conduct load testing, penetration testing, benchmark testing, security testing, reverse engineering, or competitive testing outside an active SaucerSwap Labs bug-bounty program, responsible-disclosure process, or written authorization;
* exploit stale prices, latency, order sequencing, bugs, adverse selection, misconfiguration, or unavailable cancellation paths;
* circumvent rate limits, access controls, geoblocking, authentication, sanctions screening, or monitoring;
* create false volume, wash trades, spoof, layer, quote stuff, self-trade to mislead, manipulate market data, or disrupt any orderbook or matching path; or
* use SaucerSwap Labs' non-public data, trade secrets, confidential information, or proprietary infrastructure to create, train, operate, or improve a competing routing, aggregation, market-data, or trading product in violation of these Terms, API terms, or a separate written agreement.
Good-faith security research and responsible vulnerability disclosure are permitted only to the extent performed through an active SaucerSwap Labs bug-bounty program, published security policy, or written authorization and only if the research avoids user harm, data exfiltration, service disruption, privacy violations, market disruption, and unlawful activity.
Authorized automated use may be governed by separate terms. If separate written terms conflict with these Terms, the separate written terms control only for the expressly covered access or activity and do not create duties, rights, licenses, regulatory status, or access parity for any other person.
## 14. Prohibited Conduct
You may not use the Services to engage in or facilitate:
* fraud, deception, manipulation, false or misleading activity, or illegal activity;
* wash trading, spoofing, layering, quote stuffing, marking the close, pump-and-dump activity, self-trading intended to create false volume, or activity creating a false or misleading appearance of trading activity, price, liquidity, demand, supply, orderbook depth, or market condition;
* front-running through misuse of non-public or misappropriated information;
* oracle manipulation, indexer manipulation, market-data manipulation, denial-of-service activity, API abuse, orderbook disruption, bug exploitation, replay attacks, double-fill attempts, settlement disruption, or circumvention of rate limits or access controls;
* sanctions evasion, money laundering, terrorist financing, cybercrime, ransomware, theft, exploitation, or transactions involving stolen, hacked, or unlawfully obtained assets;
* derivatives, margin, leverage, financing, synthetic exposure, or other prohibited transactions described in Section 9;
* infringement, harassment, impersonation, spam, malware, phishing, unauthorized access, or attacks on any user, wallet, protocol, network, or service provider; or
* any activity that violates applicable law or these Terms.
## 15. Compliance, Regulatory Change, And Emergency Controls
SaucerSwap Labs may, in its sole discretion and without liability, reject, delay, throttle, queue, deprioritize, filter, correct, cancel, expire, disable, restrict, geoblock, delist, close, reopen, halt, suspend, or terminate any Service, Orderbook Service, orderbook, market, order, API key, account access, order-entry path, matching path, settlement-support path, market-data feed, WebSocket feed, token, pair, pool, route, or related feature.
We may take these actions for legal, regulatory, sanctions, compliance, security, abuse-prevention, market-integrity, operational, technical, system-load, third-party dependency, suspected error, suspected manipulation, suspected unlawful activity, or other reasons. We may require wallet screening, location screening, identity checks, additional information, API controls, allowlisting, terms reacceptance, or other compliance steps where we determine they are necessary or appropriate.
Except where required by applicable law, SaucerSwap Labs does not undertake any duty to monitor for, prevent, detect, correct, reverse, recover, reimburse, or notify users of any issue.
## 16. Fees
You are responsible for all network fees, gas fees, token association fees, wallet fees, third-party fees, interface fees, swap fees, orderbook fees, API fees, market-maker fees, partner fees, and other fees that apply to your use of the Services. Fees may change. Displayed fees may be estimates, may differ materially from fees actually charged or incurred, and may not reflect final network, wallet, liquidity, route, or third-party costs. Third-party fees are outside our control.
Where the public user interface charges a fee, we will display or otherwise make available material fee and routing-compensation information we determine appropriate through the interface fee disclosure, order preview, API response, API documentation, program terms, fee schedule, or other notice that applies to the relevant access path. Separate API, market-maker, liquidity, filler, partner, or enterprise programs may include fees, discounts, incentives, rebates, compensation, or other commercial terms, and those terms control for the covered access or activity.
Where any fee, rebate, incentive, market-maker arrangement, liquidity-provider arrangement, API tier, affiliate relationship, default-route parameter, or other arrangement could influence what routes, pools, orderbooks, markets, counterparties, quotes, liquidity sources, depth, speed, fees, or defaults are displayed or made available, SaucerSwap Labs will disclose or make available material terms, conflicts, and limitations through the interface, API documentation, program terms, fee schedule, order preview, or other notice that applies to the relevant access path.
Fee, rebate, incentive, routing-compensation, or conflict disclosures are product and conflict notices only. They do not create a duty of best execution, price improvement, quote protection, routing optimization, fiduciary advice, agency, fair access, market surveillance, market integrity, or equal treatment.
## 17. Third-Party Services And Networks
The Services may link to or interoperate with Third-Party Services. We do not control Third-Party Services and are not responsible for their content, accuracy, availability, privacy practices, security, fees, performance, legality, or operations.
Public networks, wallets, RPC providers, mirror nodes, indexers, bridges, explorers, token issuers, stablecoin issuers, validators, cloud providers, analytics providers, market makers, liquidity providers, solvers, relayers, fillers, API participants, and other Third-Party Services may halt, reorganize, fork, congest, fail, censor, upgrade, change, be exploited, or behave unexpectedly. You use Third-Party Services at your own risk.
## 18. Security Reviews, Audits, Bug Bounties, And Testnets
Security reviews, audits, bug bounty programs, testnet programs, monitoring, safeguards, or risk controls do not create any warranty, representation, service-level agreement, reimbursement obligation, or guarantee that the Services, Protocol, Orderbook Services, smart contracts, APIs, off-chain systems, market data, order data, or third-party dependencies are secure, correct, complete, uninterrupted, compliant, or free from bugs, exploits, misconfiguration, manipulation, cyber incidents, or loss.
Public references to audits or security reviews apply only to the specific scope reviewed and do not imply that unrelated smart contracts, off-chain components, APIs, infrastructure, databases, queues, WebSocket feeds, order-core systems, matchers, front-end components, integrations, or future changes were reviewed.
## 19. Assumption Of Risk
You assume all risks arising from your use of the Services, Digital Assets, wallets, the Protocol, public networks, Orderbook Services, and Third-Party Services.
These risks include:
* loss of Digital Assets, stablecoins, profits, opportunities, data, or access;
* market volatility, slippage, illiquidity, stale prices, failed transactions, unexpected execution, partial fills, no fills, duplicate fills, overfills, underfills, fills after apparent terminal states, delayed fills, delayed or missing settlement, and inability to place, modify, cancel, or settle orders;
* bugs, outages, misconfiguration, latency, data corruption, incomplete data, indexing errors, event-stream errors, WebSocket failures, API failures, database failures, Redis or queue failures, order-core failures, matcher failures, settlement-support software failures, fee-controller or admin-configuration errors, maker validation failures, taker transfer failures, actual-fee, fee-cap, or order-cap mismatches, skipped-maker events, filler authorization failures, fee-discount tier errors, market-halt or market-reopen events, market-data snapshot errors, wallet or signature incompatibilities, token association or allowance failures, operator funding failures, network congestion, chain events, smart-contract errors, sanctions or compliance controls, market halts, cyber incidents, maximal extractable value ("MEV"), sandwiching, front-running, latency arbitrage, adverse selection, public or inferred trading-interest exposure, or third-party service failures;
* fake tokens, malicious tokens, token issuer risk, stablecoin reserve or redemption risk, freeze or blacklist functions, bridge risk, oracle risk, governance risk, admin-key risk, upgrade risk, and regulatory risk;
* phishing, support impersonation, malware, compromised devices, compromised wallets, social engineering, and user error; and
* tax, accounting, legal, regulatory, sanctions, and jurisdictional consequences.
## 20. No Advice
The Services and any information provided through them are for informational and software-access purposes only. We do not provide investment, trading, legal, tax, accounting, financial, regulatory, custody, fiduciary, or other professional advice. You should consult your own advisers before using the Services or engaging in any Digital Asset transaction.
## 21. No Warranties
Plain-language summary for users where required by applicable consumer law: the Services are provided on an "as is" and "as available" basis. We do not promise that the Services, market data, order status, balances, APIs, or third-party systems will be available, accurate, complete, secure, timely, or error-free. These disclaimers apply only to the extent permitted by the law that applies to you and do not limit mandatory consumer, privacy, data-security, personal-injury, fraud, or other non-waivable rights.
THE SERVICES, PROTOCOL, ORDERBOOK SERVICES, APIS, MARKET DATA, DOCUMENTATION, CONTENT, AND ALL RELATED INFORMATION ARE PROVIDED "AS IS" AND "AS AVAILABLE." TO THE MAXIMUM EXTENT PERMITTED BY LAW, SAUCERSWAP LABS DISCLAIMS ALL WARRANTIES AND REPRESENTATIONS, EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, ACCURACY, AVAILABILITY, RELIABILITY, SECURITY, COMPLETENESS, TIMELINESS, AND QUIET ENJOYMENT.
WE DO NOT WARRANT THAT THE SERVICES WILL BE UNINTERRUPTED, ERROR-FREE, SECURE, ACCURATE, COMPLETE, CURRENT, AVAILABLE, COMPATIBLE WITH ANY WALLET OR DEVICE, FREE FROM VULNERABILITIES, OR THAT ANY ORDER, CANCELLATION, EXPIRATION, TRANSACTION, OR SETTLEMENT WILL BE ACCEPTED, MATCHED, FILLED, CANCELED, EXPIRED, SUBMITTED, CONFIRMED, RECOVERED, OR SETTLED.
WE DO NOT WARRANT THE ACCURACY, COMPLETENESS, TIMELINESS, CONSISTENCY, OR AVAILABILITY OF ANY MARKET DATA, ORDER STATUS, BALANCE, ROUTE, QUOTE, FEE ESTIMATE, DEPTH, VOLUME, FILL STATUS, CANCELLATION STATUS, EXPIRATION STATUS, SETTLEMENT STATUS, API RESPONSE, WEBSOCKET MESSAGE, MIRROR-NODE DATA, INDEXER DATA, WALLET DISPLAY, OR THIRD-PARTY DATA.
## 22. Limitation Of Liability
TO THE MAXIMUM EXTENT PERMITTED BY LAW, SAUCERSWAP LABS AND ITS AFFILIATES, STOCKHOLDERS, DIRECTORS, OFFICERS, EMPLOYEES, CONTRACTORS, AGENTS, SERVICE PROVIDERS, AND LICENSORS WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, PUNITIVE, ENHANCED, OR SIMILAR DAMAGES; LOST PROFITS; LOST REVENUE; LOST BUSINESS; LOST OPPORTUNITY; TRADING LOSS; LOSS OF DIGITAL ASSETS; LOSS OF STABLECOINS; LOSS OF DATA; LOSS OF GOODWILL; BUSINESS INTERRUPTION; COMPUTER DAMAGE; DEVICE DAMAGE; SYSTEM FAILURE; REGULATORY LOSS; OR COST OF SUBSTITUTE SERVICES, WHETHER BASED ON WARRANTY, CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY, MISREPRESENTATION, FIDUCIARY THEORY, AGENCY THEORY, CONSUMER-PROTECTION THEORY, STATUTE, OR ANY OTHER LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
For purposes of this Section, loss of Digital Assets, stablecoins, token value, trading opportunity, or expected execution outcome is treated as indirect, consequential, special, or similar loss to the maximum extent permitted by law, even if Digital Asset transactions are the activity for which you used the Services.
THIS LIMITATION APPLIES TO ALL CLAIMS ARISING FROM OR RELATING TO THE SERVICES, INCLUDING ANY ORDER-CORE, MATCHER, ORDERBOOK, API, WEBSOCKET, INDEXER, DATABASE, REDIS, QUEUE, MARKET-DATA, QUOTE, FEE, SETTLEMENT-SUPPORT, WALLET-CONNECTION, SIGNING, AUTHENTICATION, COMPLIANCE-CONTROL, SANCTIONS-SCREENING, BETA, TESTNET, SMART-CONTRACT, PROTOCOL, NETWORK, OR THIRD-PARTY DEPENDENCY ERROR, OUTAGE, DELAY, MISCONFIGURATION, EXPLOIT, VULNERABILITY, OR FAILURE, AND INCLUDES FAILED OR UNEXPECTED EXECUTION, INABILITY TO TRADE OR CANCEL, INCORRECT DISPLAY, DELAYED OR MISSING SETTLEMENT, AND REGULATORY OR COMPLIANCE RESTRICTIONS.
The exclusions and cap in this Section do not apply to fraud, intentional misconduct, willful misconduct, gross negligence as determined under Delaware law, death or personal injury caused by negligence, public injunctive relief, statutory damages, statutory penalties, statutory attorneys' fees or costs, privacy or data-security liability, or any other liability that cannot be excluded or limited under applicable law.
TO THE MAXIMUM EXTENT PERMITTED BY LAW, OUR TOTAL LIABILITY FOR ALL CLAIMS ARISING OUT OF OR RELATING TO THE SERVICES OR THESE TERMS WILL NOT EXCEED THE GREATER OF (A) THE AMOUNT YOU PAID DIRECTLY TO SAUCERSWAP LABS FOR THE SPECIFIC SERVICE GIVING RISE TO THE CLAIM DURING THE THREE MONTHS BEFORE THE EVENT GIVING RISE TO LIABILITY, OR (B) ONE HUNDRED U.S. DOLLARS (\$100.00). THAT THREE-MONTH LOOKBACK IS THE GENERAL CONTRACTUAL CAP. FOR INDIVIDUAL CONSUMERS WHERE MANDATORY LAW DOES NOT ALLOW THAT CAP, OUR LIABILITY WILL BE LIMITED TO THE GREATER OF (X) THE DIRECT FEES YOU PAID DIRECTLY TO SAUCERSWAP LABS FOR THE SPECIFIC SERVICE GIVING RISE TO THE CLAIM DURING THE 12 MONTHS BEFORE THE EVENT GIVING RISE TO LIABILITY, OR (Y) THE MINIMUM AMOUNT REQUIRED BY APPLICABLE MANDATORY LAW.
Some jurisdictions do not allow certain exclusions or limitations of liability. In those jurisdictions, our liability will be limited to the maximum extent permitted by law.
Nothing in these Terms excludes or limits liability for fraud, intentional misconduct, willful misconduct, gross negligence as determined under Delaware law, death or personal injury caused by negligence, or any statutory, consumer, privacy, data-security, or other liability that cannot be excluded or limited under applicable law.
## 23. Release
To the maximum extent permitted by law, you release SaucerSwap Labs and its affiliates, stockholders, directors, officers, employees, contractors, agents, service providers, and licensors only from known claims arising from Third-Party Services, public networks, wallets, Digital Assets, user-authorized orders, signatures, approvals, transactions, expirations, cancellations, or other users, except to the extent caused by SaucerSwap Labs' breach, negligence where liability cannot be waived, fraud, intentional misconduct, willful misconduct, gross negligence, statutory violation, privacy or data-security violation, or other non-waivable liability.
This release is intentionally narrower than the limitation of liability in Section 22. It does not waive unknown claims, prospective claims, statutory rights, public injunctive relief, statutory damages, statutory fees, privacy or data rights, or any right that cannot be waived before a dispute arises. No California Civil Code Section 1542 waiver applies unless presented in a separate post-dispute settlement or release with separate consideration.
## 24. Indemnification
You will defend, indemnify, and hold harmless SaucerSwap Labs and its affiliates, stockholders, directors, officers, employees, contractors, agents, service providers, and licensors from and against third-party claims, damages, losses, liabilities, costs, and expenses, including reasonable attorneys' fees, to the extent caused by your breach of these Terms, unlawful or sanctioned activity, manipulative or abusive trading activity described in Section 14, unauthorized API or automated access, violation of third-party rights, or user content, support, bug-bounty, security-report, or feedback submissions.
Your indemnity obligations do not apply to ordinary consumer use that complies with Sections 3, 4, and 9; claims caused by SaucerSwap Labs or its service providers; disputes not caused by your breach or wrongdoing; SaucerSwap Labs' fraud, intentional misconduct, willful misconduct, gross negligence, non-waivable statutory violation, or non-waivable privacy or data-security claims.
## 25. Trading Information, Conflicts, And Privacy
Our Privacy Policy explains how we collect, use, disclose, and retain information. By using the Services, you acknowledge that wallet addresses, transaction data, order data, HCS references where used, public-chain data, mirror-node data, explorer data, indexer data, and market data may be public, immutable, independently retained, or outside our control.
SaucerSwap Labs may preserve, use, disclose, or provide information about you, your wallet, your orders, your transactions, your API usage, your device or network activity, or your use of the Services to courts, regulators, law enforcement, government authorities, sanctions authorities, self-regulatory organizations, counterparties, infrastructure providers, legal or compliance advisers, auditors, service providers, or other third parties when we believe disclosure is required or appropriate to comply with law, legal process, sanctions obligations, regulatory requests, investigations, security incidents, disputes, fraud or abuse prevention, market-manipulation concerns, or protection of SaucerSwap Labs, users, the Protocol, the Services, or the public.
SaucerSwap Labs maintains, or requires service providers to maintain, contractual, technical, operational, access-control, logging, confidentiality, and misuse-prevention controls for non-public order and trading information accessible to personnel, affiliates, contractors, service providers, market makers, liquidity providers, API counterparties, and other persons who may receive access in connection with the Services. Non-public order and trading information may be accessed or disclosed only where we determine it is reasonably necessary or appropriate for operations, compliance, security, investigation, reconciliation, support, legal process, regulatory cooperation, or dispute handling. Those persons may not use non-public order or trading information for personal trading, front-running, preferential trading, undisclosed routing advantage, market manipulation, or other improper purposes. SaucerSwap Labs, its affiliates, personnel, service providers, market makers, and liquidity providers may hold Digital Assets, trade Digital Assets, or participate in liquidity programs, but they may not use non-public user order information for undisclosed preferential trading or manipulation.
We do not intentionally disclose non-public signed order payloads, order intent, API strategy data, or wallet-linked trading history to market makers, liquidity providers, or API counterparties for their independent trading advantage, except where the disclosure is necessary to operate a requested orderbook, route, settlement-support, reconciliation, compliance, investigation, or dispute-resolution function and is subject to applicable confidentiality, access, and misuse restrictions.
SaucerSwap Labs does not guarantee confidentiality where information is public-chain data, operationally shared, legally required, disclosed under legal process, retained by third parties, exposed by user activity, or exposed by Third-Party Services. We may monitor order, API, market-data, and trading activity for operations, security, sanctions, fraud, abuse, market-manipulation prevention, legal process, regulatory requests, dispute handling, debugging, incident response, and reconciliation.
Where the Services display routes, venues, liquidity sources, depth, speed, fees, reliability, price, or similar information, those displays are informational and may be based on default parameters, available data, configuration settings, operational constraints, or third-party inputs. They are not recommendations, warranties, fiduciary advice, best-execution determinations, or guarantees of outcome.
The Privacy Policy describes data practices only. It does not expand the Services, create a separate service-level agreement, guarantee data accuracy or availability, create a duty to monitor, detect, prevent, correct, disclose, reverse, reimburse, or notify users of trading or system issues, or create any custody, brokerage, agency, fiduciary, advisory, best-execution, fair-access, market-integrity, or regulated-intermediary duty.
## 26. Intellectual Property
The Services, including text, graphics, logos, interfaces, software, designs, compilation, and other content, are owned by SaucerSwap Labs or its licensors and are protected by intellectual property laws. Subject to these Terms, we grant you a limited, revocable, non-exclusive, non-transferable, non-sublicensable license to access and use the Services for your own lawful purposes.
You may not copy, modify, distribute, sell, lease, sublicense, reverse engineer, or create derivative works from the Services except as permitted by applicable open-source licenses or written authorization from us.
The Services may include open-source software. Applicable open-source licenses control the covered software to the extent they conflict with these Terms.
## 27. User Content And Feedback
Subject to the Privacy Policy and applicable privacy, confidentiality, security-reporting, and data-protection rights, if you submit feedback, suggestions, bug reports, support materials, comments, or other content to us, you grant us a worldwide, perpetual, irrevocable, sublicensable, transferable, royalty-free license to use, reproduce, modify, publish, distribute, display, and create derivative works from that content as reasonably necessary to operate, improve, secure, document, and promote the Services, without compensation to you. We will not publicly use personal information from support, security, bug-bounty, or private community submissions for promotional purposes without consent, and we will delete, de-identify, or restrict personal information where required by applicable law. You represent that you have the rights necessary to provide that content and that it does not violate law or third-party rights.
## 28. Modifications To These Terms
We may update these Terms from time to time. We will update the "Last modified" date when we do. Where required or where we determine appropriate, we may provide additional notice or require renewed acceptance. For non-material updates, your continued use of the Services after updated Terms are posted or presented means you accept the updated Terms if applicable law permits acceptance by continued use. If you do not agree to updated Terms, you must stop using the Services.
For material changes to the Terms, Privacy Policy, V3 Orderbook Risk Notice, API terms, orderbook risk, data processing, dispute terms, or protected V3 access rules, you must affirmatively accept or acknowledge the updated versions before you may build or save V3 orders, receive or use wallet-auth JSON Web Tokens ("JWTs") or session tokens, receive or use API keys, or access protected Orderbook Services. Continued use alone will not substitute for required affirmative reacceptance.
During a reasonable transition period after updated Terms are posted, we may allow users who have not yet accepted the updated Terms to access non-protected, informational, or read-only Services if we determine that doing so is legally and operationally appropriate. We are not required to provide a transition period for protected Orderbook Services, API keys, market-maker access, legal, sanctions, security, abuse-prevention, or emergency changes.
If you refuse updated Terms, we may disable protected access and may allow a limited wind-down path for pending orders or in-flight transactions where legally, technically, and operationally feasible. Wind-down access is not guaranteed, may be read-only, may require cancellation or expiration rather than execution, and may be unavailable for legal, sanctions, security, abuse-prevention, market-integrity, or technical reasons.
Material changes to arbitration, class waiver, liability limitation, release, indemnity, privacy, or V3 Orderbook Risk Notice terms will apply prospectively after posting or presentation and, where required by law or where we require renewed acceptance. Disputes arising before the effective date of a material change will be governed by the Terms version in effect when the relevant conduct occurred, unless the parties agree otherwise after the dispute arises.
## 29. Suspension And Termination
We may suspend, restrict, or terminate your access to all or part of the Services at any time, with or without notice, including if we believe that you violated these Terms or applicable law, your use creates risk for users or the Services, legal or regulatory concerns exist, security or abuse concerns exist, or operational reasons require action.
You may stop using the Services at any time. Sections that by their nature should survive termination will survive, including Sections 2 and 4 through 37, and the Terms version applicable to any dispute will survive for that dispute.
## 30. Electronic Communications
You consent to receive communications from us electronically, including through the Services, website notices, modal notices, email, mobile notifications, API notices, or other electronic means. Electronic communications satisfy any legal requirement that communications be in writing.
By accepting these Terms, you consent to receive legal notices, disclosures, agreements, and records electronically. You may request a paper copy or withdraw electronic-record consent by contacting `legal@saucerswap.finance`, but withdrawal may prevent use of protected Orderbook Services. To access and retain records, you need a device, internet access, a current browser, PDF or HTML viewing capability, and storage or printing capability.
This electronic-record consent covers legal notices, disclosures, agreements, policies, risk notices, acceptance records, orderbook and API notices, dispute notices, and other records relating to the Services. By accepting electronically, you confirm that you can access and retain the HTML, PDF, or other electronic records presented at acceptance. You may request a paper copy, withdraw electronic-record consent, or update the information needed to contact you electronically by emailing `legal@saucerswap.finance`; we currently do not charge a fee for a paper copy unless we disclose a fee before fulfilling the request. Withdrawal will be effective within a reasonable time after receipt and may prevent use of protected Orderbook Services. If hardware or software requirements materially change in a way that creates a material risk that you cannot access or retain future electronic records, we will provide revised requirements and obtain renewed consent where required by law.
## 31. Governing Law
These Terms and any dispute arising out of or relating to the Services or these Terms are governed by the laws of the State of Delaware, without regard to conflict-of-laws principles. The Federal Arbitration Act governs the interpretation and enforcement of the arbitration agreement below.
Subject to Section 33, qualifying small-claims proceedings, and any non-waivable consumer, public-injunctive, or local-venue rights that applicable law requires, any court proceeding arising out of or relating to the Services or these Terms must be brought exclusively in the state courts located in New Castle County, Delaware or the United States District Court for the District of Delaware. Each party consents to personal jurisdiction and venue in those courts and waives any objection based on inconvenient forum or lack of personal jurisdiction, except where that waiver is prohibited by applicable law.
## 32. Informal Dispute Resolution
Before starting arbitration or another proceeding, you must first contact us at `legal@saucerswap.finance` and attempt to resolve the dispute informally. Your notice must include your name, the wallet address or account involved if applicable, a description of the dispute, and the relief you seek. If the dispute is not resolved within 60 days after we receive the notice, either party may proceed as described below.
The limitations period for your claim is tolled from the date SaucerSwap Labs receives a compliant informal dispute notice until the earlier of written resolution, written impasse, or 60 days after receipt.
## 33. Arbitration
Any claim or controversy arising out of or relating to the Services, these Terms, or any act or omission for which you contend SaucerSwap Labs is liable, including questions of arbitrability, will be finally and exclusively resolved by binding arbitration administered by the American Arbitration Association ("AAA") under its Consumer Arbitration Rules, except as modified by these Terms.
The arbitration will be conducted remotely, on written submissions, or in New Castle County, Delaware, as determined under the applicable AAA rules, unless the parties agree otherwise or the arbitrator determines that a different location is required by applicable law. For consumer claims, any in-person hearing will occur in the county or locale where the consumer resides, or another location reasonably accessible to the consumer, unless the consumer chooses remote or written proceedings or AAA rules or applicable law require otherwise. New Castle County, Delaware applies only to non-consumer claims or where the consumer and AAA or arbitrator agree it is reasonably accessible. Except for small-claims matters, emergency temporary relief, and non-waivable public injunctive relief, the arbitrator may award any individual relief available in court under law or equity, including statutory damages, statutory fees, costs, and individual injunctive or declaratory relief, subject only to enforceable limitations in these Terms. Judgment on the award may be entered in any court with jurisdiction, including the courts described in Section 31 where applicable.
Nothing in this Section prevents either party from seeking temporary, preliminary, or emergency injunctive or equitable relief in the courts described in Section 31, or another court that applicable law requires or permits for that relief, to preserve the status quo, prevent irreparable harm, protect security, enforce access restrictions, protect intellectual property, or prevent misuse of the Services pending arbitration. Seeking such relief does not waive arbitration, and all arbitrable claims remain subject to arbitration.
You may opt out of the arbitration agreement in this Section 33 by emailing `legal@saucerswap.finance` within 30 days after you first accept these Terms. Your opt-out notice must include the wallet address or Hedera account ID used with the Services, if any, and state that you opt out of arbitration. We will use reasonable efforts to acknowledge receipt of a complete opt-out notice within 10 business days. Opting out of Section 33 does not opt you out of Section 34 unless applicable law requires otherwise. Opting out of arbitration will not affect any other part of these Terms or your ability to use the Services. A valid arbitration opt-out that you timely submit survives later acceptance of amended Terms unless you affirmatively agree otherwise after a dispute arises. A new 30-day arbitration opt-out period opens only if we materially change this Section 33.
Notwithstanding the foregoing, either party may bring an individual claim in small claims court if the claim qualifies. For consumer claims, the AAA Consumer Arbitration Rules, Consumer Due Process Protocol, and applicable AAA consumer fee schedule apply. SaucerSwap Labs will pay arbitration fees and arbitrator compensation that the applicable AAA consumer rules or law require a business to pay, and no arbitrator may reallocate those fees to an individual consumer except where permitted by those rules or applicable law.
Where AAA rules, the AAA Consumer Clause Registry, or the AAA Consumer Due Process Protocol require registration, review, filing, fee payment, or waiver of a provision for AAA administration of consumer claims, SaucerSwap Labs will comply to the extent required before requiring AAA administration of that consumer claim. If the AAA declines or ceases administration of a consumer arbitration because SaucerSwap Labs failed to pay required fees, failed to register or maintain a required consumer clause registration, or refused to waive a provision the AAA requires be waived for Consumer Due Process Protocol compliance, either party may submit the dispute to the courts described in Section 31 unless applicable law requires or permits another forum.
If similar arbitration demands are filed against SaucerSwap Labs or related parties by or with coordinated counsel at or above the threshold in the then-current AAA-ICDR Mass Arbitration Supplementary Rules or other applicable AAA mass-arbitration rules, those rules will apply to the extent accepted by the AAA. The parties agree to cooperate in good faith with any AAA process arbitrator, staged administration, bellwether, mediation, batching, filing-deficiency, or scheduling process that the AAA applies, while preserving individual merits determinations unless the parties agree otherwise.
If the AAA is unavailable for a reason not addressed above, the parties will seek appointment of a substitute administrator or arbitrator under the Federal Arbitration Act with materially similar consumer protections, unless applicable law requires court adjudication.
Nothing in these Terms waives, limits, delays, or requires arbitration of a non-waivable right to seek public injunctive relief where applicable law prohibits that waiver or arbitration. Any such request may be brought in the courts described in Section 31 unless applicable law requires or permits another forum, while individual arbitrable claims remain subject to arbitration unless applicable law requires otherwise.
## 34. Class Action And Jury Trial Waiver
To the maximum extent permitted by applicable law, you and SaucerSwap Labs agree that each may bring claims against the other only in an individual capacity and not as a plaintiff, class member, or representative in any class action, collective action, private attorney general action, representative PAGA action, or other representative proceeding. The arbitrator may not consolidate claims of more than one person and may not preside over any class, collective, private attorney general, PAGA, or representative proceeding, except to the extent applicable law makes that restriction unenforceable for a specific non-waivable claim.
To the maximum extent permitted by applicable law, you and SaucerSwap Labs waive any right to a jury trial.
## 35. Time Limit To Bring Claims
Any claim or cause of action arising out of or relating to the Services or these Terms must be filed within one year after the claim accrues, otherwise the claim is permanently barred. This limitation applies to the maximum extent permitted by law. This one-year period does not apply where prohibited by law; to public injunctive relief; to privacy, data-protection, data-security, personal injury, fraud, intentional-misconduct, or statutory claims with non-waivable limitations periods; or where delayed discovery, equitable tolling, or another mandatory tolling rule applies.
## 36. Notices
You may contact us at:
SaucerSwap Labs, Inc.
Attn: Legal
63 Federal Street, Unit #349
Portland, ME 04101
Email: `legal@saucerswap.finance`
We may provide notices through the Services, by email, by wallet or account notice, by API notice, or by other reasonable electronic means.
## 37. Miscellaneous
These Terms, together with the Privacy Policy, any V3 Orderbook Risk Notice, and any supplemental terms that expressly apply, constitute the entire agreement between you and SaucerSwap Labs regarding the Services. You may not assign these Terms without our prior written consent. We may assign these Terms without restriction, but any assignment by us will not eliminate accrued user rights, and any valid arbitration opt-out or dispute-specific Terms version that binds SaucerSwap Labs will bind our successors and assigns.
If any provision of these Terms is found unenforceable, that provision will be modified to the minimum extent necessary to make it enforceable, and the remaining provisions will remain in effect. If the class action waiver in Section 34 is found unenforceable for a claim, the arbitration agreement will be unenforceable only for that claim unless applicable law requires a broader result. If the jury trial waiver is found unenforceable, that finding will not by itself make the arbitration agreement, class action waiver, or remaining Terms unenforceable.
Our failure to enforce any provision is not a waiver. A waiver must be in writing and signed by an authorized representative. We will not be liable for delay or failure to perform resulting from events beyond our reasonable control, including acts of God, labor disputes, internet or telecommunications failures, denial-of-service attacks, cyberattacks, malware, power outages, node or validator failures, chain reorganizations or halts, bridge failures, oracle failures, wallet failures, cloud-provider failures, RPC-provider failures, mirror-node failures, indexer failures, third-party service failures, market-wide disruption, liquidity disruption, acts of government, legal or regulatory actions, sanctions changes, emergency orders, natural disasters, war, terrorism, civil unrest, public-health emergencies, or other force majeure events.
Nothing in these Terms limits any non-waivable consumer protection, privacy, data-security, public-injunctive, small-claims, statutory-fee, statutory-damages, limitations-period, or other mandatory rights you may have under applicable law, including mandatory protections of your place of residence where those protections apply notwithstanding the Delaware choice-of-law clause.
# How SaucerSwap works
Source: https://docs.saucerswap.finance/protocol/overview
How SaucerSwap's parts fit together on Hedera: AMM pools, the V3 order book, protocol fees, farm and LARI incentives, xSAUCE staking, and the DAO.
SaucerSwap is a decentralized exchange on the Hedera network. It combines three trading venues — the V1 constant-product AMM, the V2 concentrated-liquidity AMM, and the V3 order book — with a shared token economy built around SAUCE. Every venue feeds protocol fees into SAUCE buybacks, and the SaucerSwap DAO steers how emissions and treasury flows are allocated.
```mermaid theme={null}
flowchart TD
T[Traders] -->|swap fees| V1[V1 constant-product pools]
T -->|swap fees| V2[V2 concentrated liquidity pools]
T -->|taker fees| V3[V3 order book]
V1 -->|protocol fee share| B[BrewSaucer SAUCE buybacks]
V2 -->|protocol fee share| B
V3 -->|net order book fees| B
B --> IP[Infinity Pool / xSAUCE holders]
B --> DAO[DAO treasury]
MC[Masterchef emissions] -->|farm rewards| V1LP[V1 liquidity providers]
MC -->|LARI rewards| V2LP[V2 liquidity providers]
MC -->|devcut share| IP
DAO -. governance votes .-> MC
```
## Tokens on Hedera
Every asset on SaucerSwap is a Hedera Token Service (HTS) token. HBAR itself is not an HTS token, so the protocol wraps it into WHBAR behind the scenes; you always see plain HBAR in the interface. Before your account can hold a new token, Hedera requires a one-time token association, which the web app prompts for automatically.
## Three trading venues
| Venue | Model | Best for |
| ---------------------------------------- | ------------------------------------------------- | ------------------------------------- |
| [SaucerSwap V1](/protocol/saucerswap-v1) | Constant-product AMM (Uniswap V2 style) | Legacy pools and long-tail pairs |
| [SaucerSwap V2](/protocol/saucerswap-v2) | Concentrated-liquidity AMM (Uniswap V3 style) | Capital-efficient liquidity provision |
| [SaucerSwap V3](/protocol/saucerswap-v3) | Central limit order book with on-chain settlement | Limit orders and CEX-style trading |
When you swap in the web app, [routing](/protocol/routing) compares available V1 and V2 paths and quotes the trade for you. On the separate trade page, V3 orders can opt into AMM-backed settlement. The swap router does not currently compare AMM quotes with order-book quotes.
## Fees and buybacks
Traders pay a fee on every trade: a percentage of each AMM swap, or a taker fee on order-book fills. Most of each AMM fee goes to liquidity providers, while protocol fee-switch revenue and net V3 fees fund SAUCE buybacks through BrewSaucer. The ratified economic destinations differ by revenue source; see [V3 fees and rebates](/protocol/saucerswap-v3/fees) and [SAUCE tokenomics](/tokenomics/overview) for the allocation matrix.
## Liquidity incentives
The Masterchef contract mints SAUCE on a fixed schedule and distributes it as liquidity incentives:
* **V1 yield farm** — LP token stakers earn SAUCE (and, when enabled, HBAR) according to [farm weights](/protocol/saucerswap-v1/farm-weights) set by governance.
* **V2 LARI** — the Liquidity-Aligned Reward Initiative rewards V2 positions automatically each two-week epoch, weighted by in-range liquidity. See [LARI weights](/protocol/saucerswap-v2/lari-weights).
## Single-sided staking
Staking SAUCE in the Infinity Pool issues xSAUCE, a receipt token whose SAUCE conversion rate rises over time as fee revenue, emissions, and HBAR staking rewards compound into the pool. xSAUCE also carries voting power and unlocks V3 fee discounts. See [Single-sided staking](/protocol/single-sided-staking).
## Governance
SAUCE and xSAUCE holders govern the protocol through token-weighted, on-chain voting: proposals start as a Request for Comment on the [governance forum](https://gov.saucerswap.finance/), then advance through Proposal and Election votes on the web app's govern page. The DAO controls farm weights, LARI campaigns, pool creation, tokenomics changes, and treasury flows. See [Governance](/governance/overview).
## Read more
Make your first swap in the web app, step by step.
Understand the order book: off-chain matching, on-chain settlement, and order types.
Stake SAUCE for xSAUCE and earn a share of protocol revenue.
Supply, emissions, and how protocol fees flow back to SAUCE.
# Swap routing
Source: https://docs.saucerswap.finance/protocol/routing
Where your SaucerSwap price comes from: how the app routes swaps across V1 and V2 pools, how V3 orders tap AMM liquidity, and integrator options.
When you swap in the web app, you do not pick a pool — routing does. This page explains where your quoted price comes from and what the router optimizes for.
## How the app routes a swap
The order router evaluates the available V1 and V2 paths from the input token to the output token and returns the best executable route. That route can be:
* **Direct.** A swap through one V1 or V2 pool.
* **Multi-hop.** A swap routed sequentially through up to three V1 or V2 pools, either because no direct pool exists or because the indirect path prices better.
* **Split route.** A swap divided across multiple paths at the same time to improve executable output and reduce price impact.
The router selects the route with the best executable output for your trade size, accounting for each pool's fee tier and price impact. Larger trades can route differently than small ones, because price impact grows with size relative to pool depth. The chosen route is shown in the swap details before you confirm.
Quoted output is an estimate as of quote time. Your slippage tolerance bounds the worst execution you will accept; the transaction reverts rather than fill beyond it.
## The order book and AMM-backed settlement
The [V3 order book](/protocol/saucerswap-v3) has a separate, one-way AMM backstop. Where enabled, a V3 order can opt into settlement against AMM liquidity, subject to the order's signed parameters.
The swap router does not currently compare an AMM swap quote with an order-book quote. [Governance thread 385](https://gov.saucerswap.finance/t/v3-order-book-calibration-contract-migration-market-set-and-fee-configuration/385), proposal 6285, and final election 6296 ratified that cross-venue comparison on July 22, 2026, but the change is not verified as deployed.
## For integrators
The smart order router is part of the SaucerSwap app and is not exposed as a public API. Integrators quote directly against the venues:
| Surface | How to quote |
| ------------- | ------------------------------------------------------------------------------------------------------------------- |
| V1 pools | Router quote calls — see the [V1 swap quote guide](/developers/v1/swap/swap-quote) |
| V2 pools | `QuoterV2` contract — see the [V2 swap quote guide](/developers/v2/swap/swap-quote) |
| V3 order book | Public quote endpoints (exact-in and exact-out) — see [Orderbook market data](/api-reference/orderbook/market-data) |
## Next steps
Make a swap and read the route details before confirming.
How AMM-backed settlement works on the order book.
Get a quote programmatically in under five minutes.
# SaucerSwap V1
Source: https://docs.saucerswap.finance/protocol/saucerswap-v1
How SaucerSwap V1's constant-product AMM works on Hedera: the xy=k formula, the 0.30% swap fee and its split, price impact, and the yield farm.
SaucerSwap V1 is an automated market maker (AMM) based on Uniswap V2 smart contracts, adapted to work with the Hedera Token Service (HTS) through the Hedera Smart Contract Service (HSCS). For technical detail, refer to the [V1 whitepaper](https://www.saucerswap.finance/whitepaper.pdf).
V1 is SaucerSwap's legacy AMM. For new liquidity positions, [SaucerSwap V2](/protocol/saucerswap-v2) is recommended: it offers concentrated liquidity, higher capital efficiency, and LARI rewards.
## Constant-product formula
The protocol uses a constant product formula, $x \cdot y = k$, for automated liquidity provision. $x$ and $y$ are the reserves of each token in a liquidity pool, and $k$ is the product of these reserves. $k$ remains constant during swaps, so every swap moves the price along a predetermined bonding curve, and the pool always stays balanced.
Liquidity in a V1 pool is spread uniformly across the entire price range $(0, \infty)$. That makes V1 pools simple to provide into — deposits are always a 50:50 value split of the two tokens — at the cost of capital efficiency.
## Fees
Traders pay a 30 basis-point (0.30%) fee on each swap. Of this fee, 5/6 is allocated to liquidity providers, and the remaining 1/6 goes to the protocol. The protocol's share funds SAUCE buybacks, which are distributed between the [Infinity Pool](/protocol/single-sided-staking) and the DAO treasury.
The liquidity providers' share accrues inside the pool, increasing the value of each LP token. The interface displays a 7-day average fees APR:
$$
\text{Fees APR} = \frac{\text{24h volume} \times (\text{fee} \times 5/6)}{\text{liquidity}} \times 365
$$
where fee = 0.30%. Note that the LP token price is not immune to volatility; it moves with the prices of the underlying tokens.
Total APR = fees APR + reward APR, where reward APR is sourced from the [yield farm](/protocol/saucerswap-v1#yield-farm).
## Worked example
**Creating a liquidity pool.** A liquidity provider creates a new pool for HBAR and USDC. With HBAR trading at roughly 1/10 the price of USDC on secondary markets, they deposit at a ratio reflecting that price: 10,000 HBAR and 1,000 USDC. If the initial price is off, arbitrageurs will correct it at the liquidity provider's expense.
The constant product for this pool:
$$
k = x \times y = 10{,}000 \times 1{,}000 = 10{,}000{,}000
$$
**Performing a swap.** A trader swaps $s = 100$ HBAR for USDC. After the 0.30% fee, the effective input is:
$$
s' = s \times (1 - 0.003) = 99.7 \text{ HBAR}
$$
The new reserves must satisfy the invariant:
$$
(x + s') \times (y - \Delta y) = k
$$
Solving for the output:
$$
\Delta y = 1{,}000 - \frac{10{,}000{,}000}{10{,}099.7} \approx 9.9 \text{ USDC}
$$
The trader receives about 9.9 USDC for 100 HBAR — slightly less than the spot rate implies, because of price impact. Price impact is the liquidity "cost" of a swap: the exchange rate worsens as reserves adjust to keep $k$ constant.
$$
\text{Initial price} = \frac{y}{x} = 0.1 \text{ USDC/HBAR} \qquad
\text{Final price} = \frac{990.1}{10{,}100} \approx 0.098 \text{ USDC/HBAR}
$$
$$
\text{Price impact} = \frac{0.098 - 0.1}{0.1} \times 100 \approx -2\%
$$
**Fee distribution.** The 0.3 HBAR fee from this trade is split: 0.25 HBAR is added to the pool for liquidity providers, and 0.05 HBAR goes to the protocol for SAUCE buybacks.
## Yield farm
Yield farming lets V1 liquidity providers stake their LP tokens in the Masterchef contract to earn rewards. The Masterchef handles LP token staking and unstaking and mints SAUCE according to the pre-set emission schedule described in [SAUCE tokenomics](/tokenomics/overview). Farms can also distribute HBAR rewards when the DAO allocates them.
Rewards are proportional to your share of the total LP tokens staked in a pool, scaled by that pool's share of overall emissions — its [farm weight](/protocol/saucerswap-v1/farm-weights). The interface shows this as reward APR:
$$
\text{Reward APR} = \frac{w \times (E_{\text{SAUCE}} + E_{\text{HBAR}})}{\text{staked liquidity}}
$$
where $w$ is the farm weight and $E_{\text{SAUCE}}$ and $E_{\text{HBAR}}$ are the annualized emission rates in dollar terms. Current emission rates and per-farm APRs are displayed live in the [web app](https://www.saucerswap.finance/); farm weights are set through the [governance process](/governance/overview).
## Next steps
Add liquidity to a V1 pool and stake LP tokens in the farm.
See how emissions are split across V1 farms.
Concentrated liquidity: the recommended venue for new positions.
The emission schedule behind farm rewards.
# Farm weights
Source: https://docs.saucerswap.finance/protocol/saucerswap-v1/farm-weights
Current nonzero Masterchef allocation points for SaucerSwap V1 yield farms, with each pool's share of the 788-point V1 allocation.
Each V1 farm receives a share of Masterchef's V1 allocation according to its allocation points. Governance can amend these values, so this table is a dated on-chain snapshot.
| V1 pool | Points | V1 share |
| ------------------------------------------------------------------ | ------: | ----------: |
| [HBAR/SAUCE](https://www.saucerswap.finance/pool/0.0.1461945) | 363 | 46.07% |
| [HBAR/USDC](https://www.saucerswap.finance/pool/0.0.1462797) | 118 | 14.97% |
| [HBAR/DOVU](https://www.saucerswap.finance/pool/0.0.3817615) | 49 | 6.22% |
| [HBAR/HSUITE](https://www.saucerswap.finance/pool/0.0.1464178) | 29 | 3.68% |
| [HBAR/gib](https://www.saucerswap.finance/pool/0.0.7902927) | 26 | 3.30% |
| [HBAR/PACK](https://www.saucerswap.finance/pool/0.0.5981646) | 24 | 3.05% |
| [HBAR/xSAUCE](https://www.saucerswap.finance/pool/0.0.1465211) | 18 | 2.28% |
| [USDC/SAUCE](https://www.saucerswap.finance/pool/0.0.1088553) | 17 | 2.16% |
| [HBAR/QNT.axl](https://www.saucerswap.finance/pool/0.0.10493791) | 17 | 2.16% |
| [HBAR/LINK.axl](https://www.saucerswap.finance/pool/0.0.10493780) | 14 | 1.78% |
| [HBAR/KARATE](https://www.saucerswap.finance/pool/0.0.2751778) | 13 | 1.65% |
| [HBAR/LCX.axl](https://www.saucerswap.finance/pool/0.0.10493784) | 13 | 1.65% |
| [HBAR/WAVAX.axl](https://www.saucerswap.finance/pool/0.0.10493801) | 13 | 1.65% |
| [HBAR/BSL](https://www.saucerswap.finance/pool/0.0.4556534) | 12 | 1.52% |
| [HBAR/GC](https://www.saucerswap.finance/pool/0.0.3279183) | 11 | 1.40% |
| [HBAR/DAVINCI](https://www.saucerswap.finance/pool/0.0.4792562) | 10 | 1.27% |
| [HBAR/KBL](https://www.saucerswap.finance/pool/0.0.7835651) | 10 | 1.27% |
| [HBAR/HST](https://www.saucerswap.finance/pool/0.0.1463354) | 8 | 1.02% |
| [SAUCE/xSAUCE](https://www.saucerswap.finance/pool/0.0.1465865) | 7 | 0.89% |
| [HBAR/STEAM](https://www.saucerswap.finance/pool/0.0.5725728) | 6 | 0.76% |
| [HBAR/GRELF](https://www.saucerswap.finance/pool/0.0.1462910) | 5 | 0.63% |
| [HBAR/SENTX](https://www.saucerswap.finance/pool/0.0.3301046) | 5 | 0.63% |
| **Total** | **788** | **100.00%** |
Checked July 29, 2026 against Masterchef `0.0.1077627` (`poolLength = 76`, `totalAllocPoint = 5,000`) and the public farms/pools APIs. Six legacy Hashport pools have zero points and are omitted. The four `.axl` pools are Axelar ITS assets.
Adjusting one pool's points reweights all V1 farm shares. The live 5,000-point Masterchef total also includes 2,314 points for LARI and 1,898 points for the DAO.
## Next steps
How the V1 AMM and yield farm work.
Propose or vote on farm weight changes.
# SaucerSwap V2
Source: https://docs.saucerswap.finance/protocol/saucerswap-v2
How SaucerSwap V2's concentrated-liquidity AMM works: price ranges and ticks, fee tiers, volatility strategies, position NFTs, and LARI rewards.
SaucerSwap V2 is an automated market maker (AMM) based on Uniswap V3 smart contracts, adapted to work with the Hedera Token Service (HTS) through the Hedera Smart Contract Service (HSCS). For technical detail, refer to the [V2 whitepaper](https://www.saucerswap.finance/whitepaper-v2.pdf).
## Concentrated liquidity
The hallmark feature of V2 is concentrated liquidity: liquidity providers (LPs) allocate capital within specific price ranges instead of across all possible prices $(0, \infty)$ as in [V1](/protocol/saucerswap-v1). Key advantages:
* Up to 4,000x capital efficiency compared to V1, and therefore elevated fee returns on the same capital.
* Trades execute with greatly reduced price impact compared to spreading the same liquidity across an unbounded range.
* LPs can shape exposure to a preferred asset, or deposit entirely above or below the spot price to emulate a fee-earning limit order that executes along a smooth curve.
Take stablecoin pairs as an example. In V1, much of the liquidity between tokens like USDC and USDT sits idle across prices that will never trade. In V2, an LP can concentrate capital in a tight range — say 0.995 to 1.005 USDC/USDT — for far higher utilization and fee earnings.
The trade-off: V2 liquidity becomes inactive when the spot price moves outside your range. Out-of-range positions earn no fees until the price re-enters the range, so active management matters more than in V1.
### Ticks
V2 inherits the Uniswap V3 concept of ticks, partitioning the continuous price range into discrete intervals. Each tick represents a 0.01% price change, and LPs select an upper and lower tick to define a position's boundaries. As swaps move the spot price (the active tick), liquidity activates or deactivates at those boundaries.
## Fee tiers
V2 offers a multi-tiered fee structure so LPs are compensated for varying degrees of risk:
| Fee tier | Tick spacing | Characteristic | Example |
| -------- | ------------ | ----------------------------------------------------- | --------- |
| 0.05% | 10 | Highly stable pairs (minimal price volatility) | USDC/USDT |
| 0.15% | 30 | Moderately stable pairs (low to medium volatility) | USDC/HBAR |
| 0.30% | 60 | Volatile pairs (significant price swings) | LINK/HBAR |
| 1.00% | 200 | Highly volatile pairs (unpredictable price movements) | JAM/HBAR |
Lower fee tiers use tighter tick spacing, allowing greater capital efficiency where prices are most stable. Higher tiers compensate LPs for the larger impermanent-loss risk of volatile pairs.
## Distribution of fees
Traders pay the pool's fee tier on each swap. As in V1, 5/6 of the collected fee goes to LPs and 1/6 to the protocol; the protocol's share funds SAUCE buybacks distributed between the [Infinity Pool](/protocol/single-sided-staking) and the DAO. Unlike V1, LPs earn fees directly in the pool's tokens — a USDC/HBAR position accrues claimable USDC and HBAR.
$$
\text{Fees APR} = \frac{\text{24h volume} \times (\text{fee} \times 5/6)}{L_{\text{bal}}} \times 365
$$
where fee is the pool's tier and $L_{\text{bal}}$ is the total liquidity aggregated over a [balanced range](/protocol/saucerswap-v2#balanced-approach). The interface displays the 7-day average.
Total APR = fees APR + reward APR, where reward APR is sourced from [LARI](/protocol/saucerswap-v2#liquidity-aligned-reward-initiative-lari).
## Volatility strategies
The web app offers preset price ranges per fee tier to streamline liquidity provision.
### Focused approach
| Fee tier | Price range | Tick range |
| -------- | ----------- | ------------- |
| 0.05% | ± 0.30% | ± 30 ticks |
| 0.15% | ± 3.00% | ± 300 ticks |
| 0.30% | ± 5.00% | ± 500 ticks |
| 1.00% | ± 10.00% | ± 1,000 ticks |
Narrow ranges set around the peg (stable pairs) or daily volatility (volatile pairs). Highest fee capture while in range, highest risk of falling out of range.
### Balanced approach
| Fee tier | Price range | Tick range |
| -------- | ----------- | ------------- |
| 0.05% | ± 1.00% | ± 100 ticks |
| 0.15% | ± 9.00% | ± 900 ticks |
| 0.30% | ± 15.00% | ± 1,500 ticks |
| 1.00% | ± 30.00% | ± 3,000 ticks |
Ranges sized to weekly volatility, with headroom for off-peg scenarios on stable pairs.
### Relaxed approach
| Fee tier | Price range | Tick range |
| -------- | ----------- | ------------- |
| 0.05% | ± 2.50% | ± 250 ticks |
| 0.15% | ± 20.00% | ± 2,000 ticks |
| 0.30% | ± 30.00% | ± 3,000 ticks |
| 1.00% | ± 60.00% | ± 6,000 ticks |
Wide ranges sized to longer-term trends and extreme market conditions. Lowest maintenance, lowest fee density.
Range bounds are first rounded to the nearest multiple of the pool's tick spacing before being converted to prices, so treat the strategy parameters as approximations. Presets may be adjusted based on community feedback, and a custom range is always available.
Volatility strategies simplify liquidity provision but do not guarantee performance or reduce impermanent-loss risk. Actively managing positions is strongly advised.
### Common mistakes
* **Setting a range and forgetting it.** Out-of-range positions earn nothing. Check positions on the dashboard after large price moves.
* **Chasing the narrowest range.** Tighter ranges earn more per hour in range but fall out of range sooner; the worked example below shows both sides of this trade-off.
* **Ignoring impermanent loss.** A position that exits its range has fully converted into the less valuable token of the pair.
## Liquidity position NFT
Each V2 liquidity position is represented by a non-fungible token (NFT), because arbitrary price ranges make positions distinct and non-fungible. The NFTs use the HTS standard and embed the position's details: token pair, fee tier, position ID, and min and max ticks. Each minted NFT also carries one of eleven handcrafted illustrations, chosen at random.
## Liquidity-Aligned Reward Initiative (LARI)
While V2 can generate higher real yields, token incentives remain vital for bootstrapping liquidity, broadening SAUCE distribution, and reinforcing governance. LARI is V2's incentive system, and it improves on the V1 farm in two ways: positions are enrolled automatically — no staking or custody transfer — and rewards scale with how efficiently liquidity is deployed, not just how much.
LARI can emit any number of HTS tokens per pool, so projects can run campaigns rewarding their own token alongside SAUCE or HBAR. Rewards are distributed automatically by airdrop at the end of each two-week epoch.
### How it works
1. **Initialization** — before each epoch, every pool is assigned a share of the epoch's rewards. Current shares are published in [LARI weights](/protocol/saucerswap-v2/lari-weights).
2. **Monitoring** — during the epoch, each position accrues "liquidity hours" for time its liquidity spends in the active tick, measured event by event.
3. **Distribution** — at epoch end, each position receives the pool's rewards pro rata to its share of the pool's total liquidity hours, delivered by airdrop.
For a position of size $L$ on the tick interval $[a, b]$ containing the active tick, its liquidity at that tick is:
$$
L_{\text{pool,pos}} = \frac{L}{b - a}
$$
Between consecutive pool events (swaps, mints, burns) separated by $\Delta t_i$ hours, the position accrues:
$$
S_{\text{pool,pos},i} = L_{\text{pool,pos}} \times \Delta t_i
$$
Total liquidity hours for the epoch sum across all $n$ intervals in which the position was active:
$$
T_{\text{pool,pos}} = \sum_{j=1}^{n} S_{\text{pool,pos},j}
$$
The position's reward is its share of the pool's allocation $R_{\text{pool}}$:
$$
R_{\text{pool,pos}} = \frac{R_{\text{pool}} \times T_{\text{pool,pos}}}{T_{\text{pool}}}
$$
Liquidity hours are computed to the second. Positions that fall out of range after a swap are credited for half of that interval. The estimated reward APR shown in the interface is $R_{\text{pool}} \times 26.07145 / L_{\text{pool}}$, annualizing the 14-day epoch.
Alice and Bob both provide \$10k to the USDC/USDT pool (0.05% fee, tick spacing 10), which has 100,000 SAUCE of LARI rewards this epoch.
* **Alice:** wide range, \$0.95 to \$1.05 — 1,000 ticks.
* **Bob:** narrow range, \$0.9995 to \$1.0005 — 10 ticks.
Assume the price stays inside Bob's range all epoch. Liquidity at the active tick:
$$
L_{\text{Bob}} = \frac{10{,}000}{10} = 1{,}000 \qquad L_{\text{Alice}} = \frac{10{,}000}{1{,}000} = 10
$$
Over one 336-hour interval, Bob accrues 336,000 liquidity hours and Alice 3,360. Rewards:
$$
R_{\text{Bob}} = \frac{100{,}000 \times 336{,}000}{339{,}360} = 99{,}010 \qquad
R_{\text{Alice}} = \frac{100{,}000 \times 3{,}360}{339{,}360} = 990
$$
Bob's focused range out-earns Alice's by 100x — but only because the price never left his 0.1%-wide range. Over a real 14-day epoch that is unlikely, and an out-of-range Bob would earn nothing while Alice kept accruing.
### Reward funding
LARI rewards are funded from the DAO's share of Masterchef emissions, plus any tokens that partner projects commit to campaigns. The DAO sets each epoch's total allocation and per-pool weights through governance; see [LARI weights](/protocol/saucerswap-v2/lari-weights) for the live epoch and past distributions, and [SAUCE tokenomics](/tokenomics/overview) for the emission schedule.
## Next steps
Open a concentrated position with a range that fits your strategy.
Current epoch allocations and past airdrop results.
The order book that routes to AMM liquidity as a backstop.
Where the protocol's fee share goes: SAUCE buybacks for xSAUCE.
# LARI weights
Source: https://docs.saucerswap.finance/protocol/saucerswap-v2/lari-weights
Per-pool LARI reward allocations for the current epoch, plus the published airdrop-result range in the official GitHub repository.
Each two-week LARI epoch distributes rewards across V2 pools according to weights set by [governance](/governance/overview). The table below is a dated snapshot; totals and weights can change each epoch.
## Epoch 71: July 27 17:00 UTC — August 10 17:00 UTC
### SAUCE rewards
| Pool | Weight · SAUCE allocation |
| --------------------- | -------------------------------: |
| USDC-HBAR | 20.79% · 241,111.33 SAUCE |
| SAUCE-HBAR | 17.08% · 198,084.74 SAUCE |
| SAUCE-XSAUCE | 2.42% · 28,066.12 SAUCE |
| HBAR-HBARX | 4.00% · 46,390.09 SAUCE |
| xSAUCE-HBAR | 1.32% · 15,308.93 SAUCE |
| USDC-SAUCE | 1.96% · 22,731.30 SAUCE |
| DOVU-HBAR | 9.24% · 107,160.73 SAUCE |
| KARATE-HBAR | 1.92% · 22,267.40 SAUCE |
| JAM-HBAR | 2.65% · 30,733.54 SAUCE |
| CARAT-USDC | 0.60% · 6,958.76 SAUCE |
| USDC-WETH (LayerZero) | 2.35% · 27,254.30 SAUCE |
| HBAR-WETH (LayerZero) | 7.92% · 91,852.10 SAUCE |
| HBAR-WBTC (LayerZero) | 6.39% · 74,108.00 SAUCE |
| USDC-WBTC (LayerZero) | 3.46% · 40,127.47 SAUCE |
| HBAR-HST | 0.66% · 7,654.61 SAUCE |
| HBAR-BONZO | 1.88% · 21,803.50 SAUCE |
| HBAR-PACK | 2.33% · 27,022.35 SAUCE |
| HBAR-GRELF | 1.32% · 15,308.93 SAUCE |
| HBAR-CLXY | 0.89% · 10,322.02 SAUCE |
| HBAR-HLQT | 0.72% · 8,350.46 SAUCE |
| USDC-HCHF | 0.71% · 8,234.48 SAUCE |
| USDC-USDC.axl | 1.76% · 20,411.81 SAUCE |
| HBAR-USDT0 | 1.40% · 16,236.72 SAUCE |
| USDC-USDT0 | 1.23% · 14,265.16 SAUCE |
| HBAR-LINK.axl | 1.49% · 17,280.49 SAUCE |
| HBAR-QNT.axl | 1.85% · 21,455.58 SAUCE |
| HBAR-WAVAX.axl | 0.87% · 10,090.08 SAUCE |
| HBAR-WBNB.axl | 0.79% · 9,154.00 SAUCE |
| **Total** | **100.00% · 1,159,745.00 SAUCE** |
### HBAR rewards
| Pool | Weight · HBAR allocation |
| ---------- | ---------------------------: |
| USDC-HBAR | 50.00% · 19,363.27 HBAR |
| SAUCE-HBAR | 50.00% · 19,363.27 HBAR |
| **Total** | **100.00% · 38,726.53 HBAR** |
Epoch number, dates, weights, and allocations were checked against the live `Epoch71` source tab on August 1, 2026. The two displayed HBAR rows are rounded to two decimals, so their displayed sum differs from the source total by 0.01 HBAR.
## Epoch airdrop results
The official results repository currently publishes CSV files for Epochs 1–60. Later completed-epoch files were not present when this page was checked on July 29, 2026.
Browse and download the published airdrop-result CSV files.
## Next steps
The liquidity-hours mechanism behind these allocations.
Open a position in a rewarded pool to start earning LARI.
LARI campaigns and weights are set by DAO vote.
# SaucerSwap V3
Source: https://docs.saucerswap.finance/protocol/saucerswap-v3
How SaucerSwap V3's central limit order book works: off-chain matching with on-chain settlement on Hedera, order types, AMM backstop, and halts.
SaucerSwap V3 is a central limit order book (CLOB) on Hedera, live on mainnet since June 12, 2026. It brings CEX-style trading — limit orders, market orders, live depth, and charting — to the trade page of the web app, while keeping assets in your own wallet: you sign orders, and settlement happens on-chain.
V3 was audited by Halborn on May 18, 2026, ahead of launch; see [Audits](/developers/security/audits). Trading an order book carries risks that AMM swaps do not — read the [V3 Orderbook Risk Notice](/legal/orderbook-risk-notice) before trading.
## Architecture: off-chain matching, on-chain settlement
V3 uses a hybrid model:
1. **You sign an order, not a transaction.** Orders are structured, signed messages (EIP-712 typed data or a Hedera personal-sign payload). Your tokens stay in your wallet; you grant a token allowance once per token.
2. **Matching happens off-chain.** A purpose-built matching engine maintains the book and matches orders with millisecond latency, which is how the book achieves exchange-grade responsiveness.
3. **Settlement happens on-chain.** Matched orders are submitted to an on-chain settlement contract (the reactor) on Hedera and settle atomically. The reactor verifies signatures and enforces the signed order parameters, and it remains the source of truth for order state.
This design means placing and canceling orders costs no per-trade gas; you pay fees only on fills. It also means displayed order status can briefly lag or differ from on-chain state — the [risk notice](/legal/orderbook-risk-notice) describes these failure modes in detail.
## Order types
| Type | Behavior |
| --------------------------- | -------------------------------------------------------------------------------------------- |
| Limit | Rests on the book at your price until filled, canceled, or expired (order deadlines apply) |
| Market | Executes immediately against available liquidity |
| Maker-only | A limit order restricted to maker fills — it never takes liquidity from the book (post-only) |
| One-cancels-the-other (OCO) | Two linked limit orders; when one fills, the other is canceled |
Orders can be canceled at any time before they fill, at no cost. Cancellation requests are asynchronous — an accepted cancel is not yet a completed cancel — and advanced users can also cancel directly on-chain through the reactor. For exact order parameters, deadlines, and limits, see the [Orderbook API reference](/api-reference/orderbook/overview).
## AMM interplay
V3 does not replace the AMMs — it sits alongside them, and the systems reinforce each other:
* **AMM backstop.** Markets can enable AMM routing, letting an order settle against [V1](/protocol/saucerswap-v1) and [V2](/protocol/saucerswap-v2) pool liquidity when the book alone cannot fill it at a better price. Orders opt into AMM-backed settlement; execution stays within your signed parameters either way.
This is a one-way settlement backstop for V3 orders, not a swap-router comparison between AMM and order-book quotes. Governance thread 385, proposal 6285, and final election 6296 ratified cross-venue comparison on July 22, 2026, but it is not verified as deployed. See [Swap routing](/protocol/routing) for the distinction.
## Market status and halts
Each market carries an independent status (for example, `OPEN` or `CLOSED`) and `isMarketHalted` flag. A market can therefore be marked open while matching is halted. SaucerSwap Labs can halt and reopen markets for legal, security, or operational reasons.
Check both fields before trading. Live values are visible on the trade page and in [`GET /books`](https://orderbook-api.saucerswap.finance/books); see the [market data reference](/api-reference/orderbook/market-data). All five public mainnet books reported `OPEN` and `isMarketHalted: 0` when checked July 29, 2026, but this snapshot can change.
## Self-custody and trust assumptions
V3 is non-custodial: SaucerSwap Labs never holds your keys or tokens, and the reactor only moves funds within the parameters you signed. The order book infrastructure itself (order entry, matching, market data, APIs) is operated off-chain by SaucerSwap Labs, so availability and displayed state depend on that infrastructure. Review every wallet prompt and signed order before approving, and read the [V3 Orderbook Risk Notice](/legal/orderbook-risk-notice) for the complete risk inventory.
## Next steps
Place your first limit or market order on the trade page.
Taker fees, maker rebates, and xSAUCE fee discounts.
Build bots and integrations against the V3 API.
Understand the risks before you trade.
# V3 fees and rebates
Source: https://docs.saucerswap.finance/protocol/saucerswap-v3/fees
How SaucerSwap V3 order book fees work: percentage-based taker fees and maker rebates, xSAUCE fee discounts, fee caps, and the BrewSaucer buyback flow.
V3 charges fees on order book fills. Fees are set per market and per side (maker or taker), can differ by account, and are designed so that takers fund the system: maker rebates, where active, are paid out of taker fees rather than token emissions.
This page shows fee rates as percentages, with basis points in parentheses. The API fields — `takerFeePips`, `makerFeePips`, and `capFractionPips` — return raw pips, where 1 pip = 0.0001% and 100 pips = 1 basis point. Convert those values before displaying them to users.
## Launch baseline and live rates
[V3 Launch Economics, thread 368](https://gov.saucerswap.finance/t/v3-launch-economics/368), proposal 6123, and final passing election 6141 ratified this public launch baseline:
| Market class | Taker · maker |
| --------------------- | ----------------------------------------------------- |
| Non-stable markets | 0.12% (12 bps) taker · 0.002% (0.20 bps) maker rebate |
| Stable–stable markets | 0.06% (6 bps) taker · 0.0005% (0.05 bps) maker rebate |
Market and account configuration can differ from this baseline. Read the effective values live:
| Surface | What it shows |
| ------------------------------------------------ | ------------------------------------------------------------------------------- |
| `GET /books` | Public per-market baseline fields, including `takerFeePips` and `makerFeePips` |
| Trade page order preview | The fee applied to your order before you sign it |
| `GET /fees/:orderbookId?side=maker` (or `taker`) | Your account's fee rates for a market, in pips (requires wallet authentication) |
See the [Orderbook API reference](/api-reference/orderbook/overview) for authentication and endpoint details.
[Thread 385](https://gov.saucerswap.finance/t/v3-order-book-calibration-contract-migration-market-set-and-fee-configuration/385), proposal 6285, and final election 6296 ratified a later order-book recalibration on July 22, 2026, but that configuration is not verified as deployed. Checked July 29, 2026: the five public mainnet books still reported the 12/6 bps launch taker schedule, while every public `makerFeePips` field reported `0`. A rebate is not proven active for a specific account unless its authenticated fee response or order preview shows it.
## Takers pay, makers may earn
* **Taker fees.** Orders that remove liquidity from the book pay the market's effective taker fee on the filled amount.
* **Maker fees and rebates.** A negative maker fee is a rebate funded from taker fees. The effective maker value may be zero or account-specific, so verify it before placing an order.
* **Fee caps.** Markets carry a fee-cap parameter (`capFractionPips`) that bounds the fee actually charged on a fill. The fee you sign against is the most you pay.
Per the [terms of service](/legal/terms-of-service), market-maker, API, and enterprise participants may operate under separate written programs with different fee tiers, rebates, or limits. Public docs describe the public schedule only; see [Market makers](/resources/market-makers) for the onboarding path.
## xSAUCE fee discounts
Holding xSAUCE (staked SAUCE) earns tiered multipliers on a market's baseline fee schedule: positive fees are reduced, and negative maker rebates are increased. Current tiers and thresholds are shown in the web app; your effective rates always come from the fees endpoint or the order preview. To stake, see [Single-sided staking](/protocol/single-sided-staking).
## Where fees go
Net order book fees — taker fees collected minus maker rebates paid — fund SAUCE buybacks through BrewSaucer. Under election 6141, V3 buyback proceeds are allocated 30% to xSAUCE, 60% to Development, and 10% to burn; the POL and incentive-reserve allocation is 0%. See [SAUCE tokenomics](/tokenomics/overview) for the source-specific matrix.
## Next steps
How the order book matches and settles trades.
Convert SAUCE to xSAUCE and lower your trading fees.
Query your live fee rates programmatically.
Onboarding for professional liquidity providers.
# Single-sided staking
Source: https://docs.saucerswap.finance/protocol/single-sided-staking
How the Infinity Pool works: stake SAUCE for xSAUCE, earn from three protocol revenue sources, and understand the rate math behind staking APR.
The Infinity Pool is SaucerSwap's single-sided staking system. Deposit SAUCE and you receive xSAUCE, a receipt token; the SAUCE-per-xSAUCE conversion rate started at 1:1 and rises over time as protocol revenue compounds into the pool. There is no lock-up schedule in the mechanism itself — you unstake by converting xSAUCE back to SAUCE at the current rate on the stake page.
xSAUCE is itself an HTS token: it counts toward your [governance voting power](/governance/overview), earns tiered [V3 trading fee discounts](/protocol/saucerswap-v3/fees), and can be used elsewhere in the ecosystem (for example, in xSAUCE liquidity pools).
## Three revenue sources
Yield in the Infinity Pool is derived from three distinct streams:
1. **Trading fees.** The protocol's share of V1 and V2 swap fees — and net [V3 order book fees](/protocol/saucerswap-v3/fees) — funds SAUCE buybacks, part of which flows to the Infinity Pool.
2. **Farm emissions.** A share of the Masterchef contract's devcut emissions is allocated to single-sided staking rewards; see [SAUCE tokenomics](/tokenomics/overview) for the emission schedule.
3. **HBAR native staking rewards.** HBAR is not an HTS token, so a smart contract wraps it into WHBAR for use on SaucerSwap. The WHBAR contract's HBAR balance is proxy-staked to a Hedera network node. It held 195,071,535.78464572 HBAR when checked July 29, 2026; verify the [live balance on HashScan](https://hashscan.io/mainnet/contract/0.0.1456985) or the [Mirror Node account response](https://mainnet-public.mirrornode.hedera.com/api/v1/accounts/0.0.1456985) rather than relying on the snapshot. Hedera native staking has no slashing and no lock-up, so the balance stays fully available. Accrued HBAR rewards are swapped into SAUCE via a daily buyback.
## Worked example
User A is the first participant. They deposit 10 SAUCE and receive 10 xSAUCE — the initial 1:1 ratio.
10 SAUCE of protocol revenue (fees, HBAR staking rewards, emissions) is added to the pool. The pool now holds 20 SAUCE against 10 xSAUCE, so the rate is 1 xSAUCE = 2 SAUCE. User A could now redeem their 10 xSAUCE for 20 SAUCE.
User B deposits 10 SAUCE. At the 1:2 rate they receive 5 xSAUCE. The pool holds 30 SAUCE against 15 xSAUCE — the rate is unchanged. New stakers never dilute existing ones.
As more SAUCE revenue arrives, every xSAUCE is redeemable for progressively more SAUCE. Rewards accrue in the rate itself; there is nothing to claim.
## Calculating APR
The staking APR shown in the app is derived from the growth of the conversion rate:
$$
\text{Infinity Pool APR} = \left( \frac{R_f}{R_i} - 1 \right) \times 365
$$
where $R$ is the SAUCE/xSAUCE exchange rate, and $R_i$ and $R_f$ are the rates at the start and end of a one-day window. The rate updates once per day, so $\Delta t \approx 24$ hours. Because revenue varies day to day, displayed APR fluctuates; the stake page shows the averaging window it uses.
## Next steps
Walk through staking on the stake page, including staking straight from HBAR.
How xSAUCE lowers your order book trading fees.
Use SAUCE and xSAUCE voting power in the DAO.
The emission and buyback flows feeding the Infinity Pool.
# Analytics
Source: https://docs.saucerswap.finance/resources/analytics
Where to find SaucerSwap data: in-app token, pool, staking, and portfolio analytics, plus third-party trackers like DefiLlama, GeckoTerminal, and CoinGecko.
SaucerSwap publishes live protocol data in the web app, and the protocol is tracked by the major independent aggregators. Third-party surfaces are useful for cross-checking volume and TVL against an external source.
## In the web app
| Surface | What it shows |
| ---------------------------------------------------------- | ----------------------------------------------------------- |
| [Token analytics](https://www.saucerswap.finance/swap) | Per-token price, volume, and market data on the swap page |
| [Pool analytics](https://www.saucerswap.finance/liquidity) | Per-pool TVL, volume, and fee data on the pool page |
| [Staking analytics](https://www.saucerswap.finance/stake) | Infinity Pool rates and distribution data on the stake page |
| [Portfolio](https://www.saucerswap.finance/portfolio) | Your positions, balances, and rewards on the dashboard |
## Third-party trackers
| Tracker | Coverage |
| ---------------------------------------------------------------------------------------- | ---------------------------------------- |
| [DefiLlama](https://defillama.com/protocol/saucerswap) | Protocol TVL and volume across versions |
| [GeckoTerminal — V1](https://www.geckoterminal.com/hedera-hashgraph/saucerswap/pools) | V1 pool prices, volume, and liquidity |
| [GeckoTerminal — V2](https://www.geckoterminal.com/hedera-hashgraph/saucerswap-v2/pools) | V2 pool prices, volume, and liquidity |
| [DexScreener](https://dexscreener.com/hedera) | Hedera pair charts and trades |
| [CoinMarketCap](https://coinmarketcap.com/exchanges/saucerswap/) | Exchange listing with markets and volume |
| [CoinGecko — V1](https://www.coingecko.com/en/exchanges/saucerswap-v1) | V1 exchange listing |
| [CoinGecko — V2](https://www.coingecko.com/en/exchanges/saucerswap-v2) | V2 exchange listing |
| [DappRadar](https://dappradar.com/dapp/saucerswap) | Dapp activity and user metrics |
Third-party trackers ingest data on their own schedules and methodologies, so their figures can differ from the web app and from each other. Treat the web app as the primary source.
## Programmatic access
For raw data — tokens, pools, farms, prices, and the V3 order book — use the APIs instead of scraping analytics pages.
## Next steps
Query tokens, pools, farms, and stats directly from the REST data API.
Read V3 depth, the trade tape, and market quotes over public endpoints.
Track your own positions and rewards on the dashboard, or watch any address.
Understand SAUCE supply, emissions, and how value flows through the protocol.
# Brand assets
Source: https://docs.saucerswap.finance/resources/brand-assets
Official SaucerSwap logos, the Larry mascot icon, SAUCE and xSAUCE token icons, brand colors, and typography for press, partners, and listings.
Official SaucerSwap brand assets for press, partners, and listing sites. These files are the approved marks — use them as provided, without recoloring or redrawing. The live brand page on the main site carries the same set: [saucerswap.finance/resources/brand-assets](https://www.saucerswap.finance/resources/brand-assets).
## Logotype
Full-color SaucerSwap logotype (PNG).
Secondary logotype arrangement (PNG).
Primary logotype on a black background (PNG).
Single-color black logotype for light surfaces (PNG).
Single-color white logotype for dark surfaces (PNG).
## Larry icon
Larry is the official alien mascot of SaucerSwap and doubles as the app icon mark.
Larry icon, primary treatment (PNG).
Larry icon on a black background (PNG).
Larry icon on a white background (PNG).
Single-color Larry icon for one-color contexts (PNG).
## Token icons
Use these icons when displaying SAUCE or xSAUCE in wallets, trackers, and listings.
SAUCE token icon (PNG).
xSAUCE token icon (PNG).
## Colors
The 2026 product design system pairs a near-black ground with green as the signal color:
| Token | Hex | Use |
| ------------ | --------- | --------------------------------------------- |
| Space Black | `#060607` | Page ground in the web app and these docs |
| Signal Green | `#44E760` | Accent and signal color on dark surfaces |
| Action green | `#17803D` | Buttons and links, and the light-mode primary |
## Typography
The brand typeface is Inter.
Inter is open source and available from [Google Fonts](https://fonts.google.com/specimen/Inter).
## Next steps
List your token and submit its icon and metadata for display in the app.
Link the official SaucerSwap channels rather than unofficial accounts.
Reach the business development team for co-marketing and integrations.
# For projects: list your token
Source: https://docs.saucerswap.finance/resources/for-projects
How to list an HTS token on SaucerSwap: pool creation, token classes, icon and metadata submission, farm and LARI incentives, and cross-chain listing.
SaucerSwap listing is permissionless. You do not need to submit a request or ask permission to make your Hedera Token Service (HTS) token tradable — you create a liquidity pool, and users can trade the token immediately. This page covers the full path from first pool to incentivized listing, plus how to take your token cross-chain.
For anything not covered here, contact [outreach@saucerswap.finance](mailto:outreach@saucerswap.finance).
## List a token
Any account can create a SaucerSwap V1 pool for an HTS token. Follow the [V1 liquidity tutorial](/tutorials/liquidity-v1) to create a pool and seed it with initial liquidity. V2 pool creation is permissioned and governed by the [SaucerSwap DAO](/governance/overview) to limit liquidity fragmentation.
Once at least one pool exists, users can trade the token by entering its token ID (for example, `0.0.12345`) in the token selector on the [swap page](/tutorials/swap).
Add a token icon and project metadata so the token displays properly in the web app. See [Token icon and metadata](#token-icon-and-metadata) below.
Default- and extended-class tokens are eligible for [yield farm](#yield-farm-v1) and [LARI](#lari-v2) incentive campaigns through governance.
## Token classes
Tokens on SaucerSwap fall into one of three classes: default, extended, or untracked. Classification affects discoverability in the web app, API coverage, and incentive eligibility — not tradability.
| Capability | Default | Extended | Untracked |
| ------------------------------------ | ------- | -------- | -------------------------------- |
| Appears in the token list by default | Yes | No | No |
| Searchable by name, symbol, or ID | Yes | Yes | No — enter the token ID manually |
| Icon and token info displayed | Yes | Yes | No |
| Included in SaucerSwap APIs | Yes | Yes | No |
| Eligible for yield farm and LARI | Yes | Yes | No |
Criteria, as of July 2026:
* Default — the token has an icon (via token metadata or Davinci Pics) and either a V2 pool or a place among the top 50 V1 pools that contain at least one common token, ranked by aggregated TVL and volume and updated monthly. Common tokens: HBAR, HBARX, SAUCE, xSAUCE, USDC, USDC\[hts], USDT\[hts], WBTC\[hts], WETH\[hts].
* Extended — the token has an icon available via token metadata or Davinci Pics.
* Untracked — every other token. Users can still trade it by entering its token ID.
## Token icon and metadata
### Tokens with an admin or metadata key
Set or update token metadata with third-party tools:
* [Kabila Token Manager](https://tools.kabila.app/en/token-manager)
* [Davinci Token Manager](https://davincigraph.io/tokens/updateMetadata)
Metadata should follow the [Hedera fungible token metadata schema (HIP-405)](https://hips.hedera.com/hip/hip-405).
SaucerSwap checks token information frequently and updates it automatically.
The following fields are supported:
| Field | Type | Description |
| ------------------------- | ------ | ------------------------------------------------------------------ |
| `lightLogo` or `darkLogo` | string | Token icon or logo image |
| `description` | string | Description of the token |
| `website` | string | Website URL |
| `twitter` | string | X (formerly Twitter) handle, without the @ |
| `discord` | string | Discord invite URL |
| `telegram` | string | Telegram link URL |
| `sentinelReport` | string | Published [Sentinel Report](https://sentinel.headstarter.org/) URL |
| `category` | string | Category for the asset, for example meme, stablecoin, or defi |
```json theme={null}
{
"lightLogo": "ar://U-xGP5bDZaqKPAE_4J2Pxqidb4s73qd0VjnuwboFWI8",
"description": "Test token metadata",
"website": "https://hedera.com",
"properties": {
"twitter": "hedera",
"discord": "https://discord.com/invite/uJ5k8DkmKV",
"telegram": "https://t.me/hederahashgraph",
"sentinelReport": "https://sentinel.headstarter.org/details/saucerswap",
"category": "meme"
}
}
```
### Tokens without an admin or metadata key
Add or update the token icon and information on [Davinci Pics](https://davincigraph.io/#pics_home). Updating a token on Davinci Pics requires connecting either:
* the token's treasury account, or
* the account that executed the token create transaction.
## Incentive campaigns
### Yield farm (V1)
The V1 [yield farm](/protocol/saucerswap-v1) lets liquidity providers stake LP tokens in the Masterchef contract to earn dual rewards in SAUCE and HBAR. A token becomes farm-eligible once it is in the default or extended class.
Creating or amending a farm campaign is a governance action: a proposal must follow the [governance process](/governance/overview) and specify which [farm weights](/protocol/saucerswap-v1/farm-weights) would be adjusted to create the new farm. All approved farms emit both SAUCE and HBAR.
### LARI (V2)
The Liquidity-Aligned Reward Initiative (LARI) is built into [SaucerSwap V2](/protocol/saucerswap-v2): liquidity providers earn incentives automatically based on the size and efficacy of their positions, with no staking step. Rewards are distributed by airdrop at the end of each two-week epoch, and campaigns can distribute multiple HTS tokens per pool — so you can run a campaign denominated in your own token.
Creating or amending a LARI campaign is also a governance action. A proposal must specify the campaign duration and the token allocation per epoch; see the current [LARI weights](/protocol/saucerswap-v2/lari-weights) for how live campaigns are configured. To initiate a LARI campaign, contact [outreach@saucerswap.finance](mailto:outreach@saucerswap.finance).
## Take your token cross-chain (Axelar ITS + Squid)
You can deploy an existing HTS token to other chains with Axelar's Interchain Token Service (ITS), then list it with Squid so it appears in the token dropdown of SaucerSwap's in-app [bridge](/tutorials/bridge).
### Prerequisites
* Your HTS token exists on Hedera mainnet (or testnet)
* The token's EVM address (`0x...`) — not the `0.0.x` token ID
* [MetaMask](https://metamask.io/) with the Hedera network added, and HBAR for gas
* A signing account that is associated with the token, ideally holding a balance
The fastest path is [Chainlist](https://chainlist.org/?search=hedera\&testnets=true): connect your wallet and select **Add to MetaMask** for Hedera Mainnet (and Hedera Testnet if needed). You can also add the network manually with official Hedera network settings. Confirm you can switch to the Hedera network and see an HBAR balance.
Look up the token by its `0.0.x` ID on [HashScan](https://hashscan.io/mainnet) and copy the EVM address (`0x...`). Make sure it is the token address, not a wallet or account address.
Open the [Axelar ITS portal](https://interchain.axelar.dev/), connect MetaMask, and paste the token's EVM address. Select the destination chains you want (for example, Base or BNB Chain), then sign the transaction in MetaMask and pay gas in HBAR. Wait until the portal shows the token as deployed on the selected chains, then run a small test transfer to confirm.
ITS deployment alone does not surface the token in bridge interfaces. From the ITS page for your token, select **Add Your Token on Squid**, or go directly to the [axelar-configs repository](https://github.com/axelarnetwork/axelar-configs) and follow the instructions to [list an interchain token on Squid](https://github.com/axelarnetwork/axelar-configs/blob/main/cli/wizard/commands/list-squid-token/README.md). A [merged example pull request](https://github.com/axelarnetwork/axelar-configs/pull/332) shows the expected shape. Once your pull request is approved and merged, Squid begins surfacing the token in the bridge modal.
Cross-chain transfers can take from a few minutes to a few hours depending on the chains involved. Track any transfer on [AxelarScan](https://axelarscan.io/) by transaction hash or wallet address. If your token does not appear in Squid after listing, the usual cause is that the `axelar-configs` pull request has not been merged or propagated yet.
## Next steps
Walk through creating and seeding a V1 liquidity pool for your token.
Learn how farm and LARI proposals move from RFC to on-chain vote.
See how live LARI campaigns allocate rewards across pools each epoch.
See the in-app bridge your users will use once your token is listed.
# Glossary
Source: https://docs.saucerswap.finance/resources/glossary
Definitions of the AMM, Hedera, SaucerSwap, and API terms used across these docs, from concentrated liquidity and slippage to pips and token association.
Short definitions of the terms used across these docs, grouped by domain. Each concept with a canonical page links to it.
## AMM concepts
### AMM
An Automated Market Maker: a decentralized exchange design that prices a token pair with a mathematical formula and fills trades from liquidity pools instead of matching buyers and sellers in an order book.
### APR
Annual Percentage Rate: the annualized rate of return on a position. On SaucerSwap, fees APR is the return from trading fees, and reward APR is the return from the [yield farm](/protocol/saucerswap-v1) or [LARI](/protocol/saucerswap-v2).
### Arbitrage
Buying and selling the same asset across venues to profit from price differences. Arbitrage keeps pool prices aligned with the wider market.
### Concentrated liquidity
A [SaucerSwap V2](/protocol/saucerswap-v2) feature that lets liquidity providers deploy capital within specific price ranges instead of across the whole price curve, increasing capital efficiency.
### DEX
A decentralized exchange: a protocol for trading tokens without a central custodian. SaucerSwap is the leading DEX on Hedera.
### Impermanent loss
The loss a liquidity provider takes, relative to simply holding, when the price ratio of a pool's pair diverges from the ratio at deposit time. It becomes permanent only if the position is withdrawn before prices revert. See the [FAQ](/get-started/faq).
### Liquidity pool
A smart contract holding a pair of tokens that traders swap against. Liquidity providers fund the pool and earn a share of trading fees.
### Price impact
The change in a pool's price caused by your own trade. Larger trades against thinner liquidity move the price more.
### Slippage
The difference between the quoted price of a trade and the price at execution, typically caused by market movement between quote and settlement. Slippage tolerance is the maximum difference you allow before the transaction reverts.
### Stablecoin
A token designed to hold a stable value, usually pegged to a fiat currency. USDC is issued natively on Hedera as an HTS token.
### TVL
Total value locked: the total value of assets deposited in a protocol's contracts, commonly used to compare DeFi protocols.
### Yield farming
Earning additional rewards by staking V1 LP tokens in the Masterchef contract, paid in SAUCE and HBAR. See [SaucerSwap V1](/protocol/saucerswap-v1).
## Hedera terms
### EVM
The Ethereum Virtual Machine, the runtime for smart contracts. Hedera is EVM-compatible, so Solidity contracts and EVM addresses (`0x...`) work on Hedera, and every HTS token also has an EVM address.
### Gas
The cost of executing a transaction on the network. Hedera fees are low and denominated in U.S. dollars, paid in HBAR.
### HBAR
Hedera's native cryptocurrency, used to pay network fees and for staking. See [Get HBAR](/get-started/hbar).
### HBARX
An HBAR liquid staking token issued by Stader Labs.
### HCS
The Hedera Consensus Service, a Hedera service for ordered, timestamped message consensus. SaucerSwap V3's infrastructure uses HCS references where applicable; see the [V3 order book risk notice](/legal/orderbook-risk-notice).
### HashScan
A public Hedera network explorer at [hashscan.io](https://hashscan.io/mainnet), serving the same role Etherscan does for Ethereum. Use it to verify accounts, tokens, and the [SaucerSwap contracts](/developers/contracts).
### HTS
The Hedera Token Service, the native Hedera service for creating and managing tokens. SaucerSwap trades HTS tokens.
### Mirror Node
A Hedera node type that stores and serves historical network data over a public REST API. SaucerSwap's APIs and clients use Mirror Nodes to resolve accounts and verify on-chain state.
### Tinybar
The smallest denomination of HBAR; 1 HBAR = 100,000,000 tinybar. The SaucerSwap REST API prices HBAR-denominated values in tinybar.
### Token allowance
An approval that lets a contract spend a specific amount of your tokens on your behalf. SaucerSwap requires allowances to execute swaps and liquidity operations; see [Troubleshooting](/resources/troubleshooting).
### Token association
Linking an HTS token to a Hedera account. An account must associate a token before it can send, receive, or hold it — the most common cause of failed first-time swaps. See [Troubleshooting](/resources/troubleshooting).
## SaucerSwap products
### Infinity Pool
SaucerSwap's single-sided SAUCE staking pool. Deposit SAUCE, receive xSAUCE, and earn as the xSAUCE-to-SAUCE rate rises. See [Single-sided staking](/protocol/single-sided-staking).
### LARI
The Liquidity-Aligned Reward Initiative: V2's incentive system, which distributes rewards to liquidity providers automatically each two-week epoch based on position size and efficacy, with no staking step. See [SaucerSwap V2](/protocol/saucerswap-v2).
### Larry
The official alien mascot of SaucerSwap.
### Masterchef
The V1 smart contract that handles LP token staking and mints SAUCE emissions for the yield farm. See [SaucerSwap V1](/protocol/saucerswap-v1).
### SAUCE
The native token of the SaucerSwap protocol, used for governance voting power, liquidity incentives, and staking. See [Tokenomics](/tokenomics/overview).
### SaucerSwap DAO
The decentralized autonomous organization that governs the protocol; SAUCE confers voting power. See [Governance](/governance/overview).
### SaucerSwap Labs
The company that develops the open-source SaucerSwap protocol and maintains the web app. See [the team](/contributors/saucerswap-labs).
### SaucerSwap V1
The original constant-product AMM, a modified fork of Uniswap V2, with the yield farm. See [SaucerSwap V1](/protocol/saucerswap-v1).
### SaucerSwap V2
The concentrated-liquidity AMM with multiple fee tiers and LARI incentives, based on Uniswap V3 contracts. See [SaucerSwap V2](/protocol/saucerswap-v2).
### SaucerSwap V3
The on-chain central limit order book with off-chain matching and on-chain settlement, live on mainnet since June 12, 2026. See [SaucerSwap V3](/protocol/saucerswap-v3).
### WHBAR
Wrapped HBAR: an HTS token representation of HBAR that lets smart contracts handle HBAR like any other token. It is designed for use by SaucerSwap's contracts rather than directly by end users; see the [WHBAR developer docs](/developers/whbar/overview).
### xSAUCE
The liquid receipt token of the Infinity Pool. Its redemption rate against SAUCE increases as staking yield accrues, and it confers fee discounts on the V3 order book. See [Single-sided staking](/protocol/single-sided-staking) and [V3 fees](/protocol/saucerswap-v3/fees).
## API and order book terms
### API key
The `x-api-key` credential used by the legacy SaucerSwap REST API. See [API authentication](/api-reference/authentication).
### Depth
The standing quantity of orders at each price level of an order book. The Orderbook API serves depth snapshots over REST and live depth diffs over WebSockets; see [Market data](/api-reference/orderbook/market-data).
### EIP-712
The Ethereum typed structured data signing standard. V3 orders are signed as EIP-712 payloads against an environment-specific domain; see [Orders and signing](/api-reference/orderbook/orders).
### JWT
A JSON Web Token: the short-lived credential the Orderbook API issues after a wallet challenge, attached to protected calls as `Authorization: Bearer `. See [Orderbook API authentication](/api-reference/orderbook/authentication).
### Limit order
An order to trade at a specified price or better. It rests on the book until filled, canceled, or expired. See [Trade on the order book](/tutorials/trade).
### Maker and taker
A maker places an order that rests on the book, adding liquidity; a taker fills a resting order, removing it. V3 fee rates are quoted per side; see [V3 fees](/protocol/saucerswap-v3/fees).
### Market order
An order that fills immediately at the best available prices in the book.
### OCO
One-cancels-the-other: a pair of linked limit orders where a fill on one cancels the other. Supported by `POST /orders/save` as server-side metadata; see [Orders and signing](/api-reference/orderbook/orders).
### Order book
A list of resting buy and sell orders at each price level, matched by price-time priority. SaucerSwap V3 runs one per market; see [SaucerSwap V3](/protocol/saucerswap-v3).
### Pips
The fee unit of the V3 order book: 1 pip = 1e-6 = 0.0001%. V3 fee fields such as `takerFeePips` and `makerFeePips` are expressed in pips, not basis points.
### Reactor
The V3 on-chain settlement contract that verifies order signatures and settles matched trades. It is the `verifyingContract` of the EIP-712 domain and the on-chain source of truth for order state.
### Trade tape
The public record of recent fills in a market, served by `GET /trades/:orderbookId`. See [Market data](/api-reference/orderbook/market-data).
### WebSocket
A persistent two-way connection used for streaming. The Orderbook API streams depth diffs and account order events over WebSockets; see [WebSockets](/api-reference/orderbook/websockets).
## Next steps
See how pools, the order book, fees, farms, and staking fit together.
Get answers to the most common questions about trading and providing liquidity.
Resolve common errors like failed swaps and missing token associations.
Compare the REST data API and the Orderbook API, with auth models and base URLs.
# Market makers
Source: https://docs.saucerswap.finance/resources/market-makers
How professional trading firms and bot operators onboard to the SaucerSwap V3 order book: mechanism, API access, policy limits, and contact path.
SaucerSwap V3 is a central limit order book on Hedera with off-chain matching and on-chain settlement. Professional market makers and bot operators integrate through the Orderbook API: market data is designed to be public (unauthenticated access is [rolling out network by network](/api-reference/orderbook/market-data) with the July 2026 deployment), while account-scoped trading endpoints sit behind wallet authentication. This page covers how the market works from a maker's perspective and how to onboard.
## How the market works
* Order flow — clients build orders server-side, sign them client-side (EIP-712, with ECDSA and ED25519 key support), and submit them for matching. Settlement happens on-chain through the reactor contract; the on-chain reactor remains the source of truth. See [Orders and signing](/api-reference/orderbook/orders).
* Fees — fee rates are expressed in pips (1 pip = 1e-6 = 0.0001%), not basis points, and are returned per account and per side by `GET /fees/:orderbookId?side=maker`. For the taker fee and maker rebate model, see [V3 fees](/protocol/saucerswap-v3/fees).
* AMM interplay — books can have AMM liquidity routed in (`isAMMEnabled`), so maker quotes compete with, and are backstopped by, SaucerSwap's V1 and V2 pools. See [How SaucerSwap V3 works](/protocol/saucerswap-v3).
* Market data — the order book list, depth snapshots, the public trade tape, and market quotes are public endpoints; live depth diffs and account order events stream over WebSockets. See [Market data](/api-reference/orderbook/market-data) and [WebSockets](/api-reference/orderbook/websockets).
## Onboarding
Production V3 access requires current acceptance of the [terms of service](/legal/terms-of-service) and the [V3 order book risk notice](/legal/orderbook-risk-notice), recorded server-side for the applicable access path.
Build against `https://testnet-orderbook-api.saucerswap.finance` first. Work through [authentication](/api-reference/orderbook/authentication) (wallet challenge and short-lived JWTs), order build, sign, and save, cancellation finality, and WebSocket reconnects. The [TypeScript client guide](/developers/orderbook/typescript-client) shows a server-side bot shape.
`GET /onboarding/:orderbookId/status` (JWT required) reports whether your account can trade a given market, and `GET /fees/:orderbookId` returns your effective fee rates per side.
Production traffic is subject to rate and service-protection limits. Teams planning sustained high-volume traffic should contact [support@saucerswap.finance](mailto:support@saucerswap.finance) to coordinate limits and support before ramping up.
Switch the same flow to `https://orderbook-api.saucerswap.finance` once your client passes the [production checklist](/api-reference/orderbook/limits-and-errors): re-authentication on `401`, WebSocket reconnects with backoff, snapshot-plus-diff book rebuilds, cancellation reconciliation, and integer-string handling.
Never put a primary wallet private key in a bot process. Use a dedicated integration account, store secrets server-side, and start on testnet before placing mainnet orders.
## Policy limits
The API applies these limits automatically, as of July 2026:
| Constraint | Value |
| --------------------------------- | ------------------- |
| Max open orders per wallet | 5,000 |
| Min order deadline | 30 seconds from now |
| Max order deadline | 90 days from now |
| Max orders per build/save request | 250 |
| Max orders per cancel request | 500 |
Current limits and error behavior are documented in [Limits and errors](/api-reference/orderbook/limits-and-errors).
## Next steps
Endpoint summary, integration flow, and environments for the V3 Orderbook API.
Walk through the wallet challenge flow and JWT handling for protected endpoints.
Study a server-side bot client shape covering build, sign, save, and cancel.
Understand the taker fee and maker rebate model and how fee rates are quoted in pips.
# Troubleshooting
Source: https://docs.saucerswap.finance/resources/troubleshooting
Fixes for the most common SaucerSwap errors: token association, insufficient HBAR, contract reverts, slippage failures, allowances, and stuck bridges.
This page is keyed to the error you are seeing. Find the error name or symptom, apply the fix, and retry. If none of these resolve your issue, open a support ticket in the [official Discord server](https://saucerswap.finance/discord) or email [support@saucerswap.finance](mailto:support@saucerswap.finance) — see [User support](/contact/user-support).
## Token not associated to an account
Symptom — a swap or transfer fails with `TOKEN_NOT_ASSOCIATED_TO_ACCOUNT`, usually on the first attempt to receive a token.
Cause — on Hedera, an account must associate an HTS token before it can send, receive, or hold it. The receiving account has not associated the output token.
Fix — associate the token first. The web app prompts you to associate an unassociated output token before a swap; approve the association transaction in your wallet, then retry. If you are sending to a different account, that account must associate the token itself. Developers executing swaps directly against the contracts must ensure the `to` account has the output token associated before the swap executes.
## Insufficient payer balance
Symptom — a transaction fails with `INSUFFICIENT_PAYER_BALANCE` before doing anything.
Cause — your account does not hold enough HBAR to cover the network fee for the transaction (and, for swaps from HBAR, the swapped amount plus the fee).
Fix — top up HBAR and retry. See [Get HBAR](/get-started/hbar) for ways to fund your account. Keep a small HBAR buffer at all times: every Hedera transaction, including token associations and approvals, costs a fee.
## Contract revert executed
Symptom — a swap or liquidity transaction fails with `CONTRACT_REVERT_EXECUTED`.
Cause — the smart contract rejected the transaction. For swaps, the most common reason is that the price moved beyond your slippage tolerance between quote and execution. Other causes include expired transaction deadlines and missing allowances.
Fix — retry the transaction. If it keeps failing, raise your slippage tolerance slightly in the settings of the web app, or trade a smaller amount. If the token has transfer restrictions or custom fees, check [token compatibility](/get-started/faq) — V2 does not support tokens with custom fees.
## Insufficient output amount (slippage)
Symptom — a swap reverts with a message containing `INSUFFICIENT_OUTPUT_AMOUNT`.
Cause — this is the specific revert behind most slippage failures: the pool could not deliver at least the minimum output your transaction demanded, because the price moved or liquidity is thin relative to your trade size.
Fix — refresh the quote and retry. For volatile pairs or large trades, raise slippage tolerance slightly or split the trade into smaller amounts. Check the price impact shown on the quote before confirming — a high price impact means your own trade moves the price.
## Allowance errors
Symptom — a swap or liquidity action fails at the approval stage, or a transaction reverts because the contract cannot spend your tokens.
Cause — Hedera requires you to grant an allowance before a contract can spend tokens on your behalf. The allowance is missing, too small, or was granted to a different contract than the one now executing.
Fix — approve the token when the web app prompts you (select **Approve** before the swap or deposit), then confirm the main transaction. If a previously granted allowance seems stale after a contract update, approve again. Background on why allowances exist is in the [Hedera network security update announcement](https://medium.com/@SaucerSwap/hedera-network-security-update-saucerswap-8d2609b43e20).
## Tokens missing in MetaMask
Symptom — you hold tokens on Hedera but they do not appear in MetaMask.
Cause — MetaMask only displays tokens you have imported by their EVM contract address.
Fix — find the token's EVM address (`0x...`) in the SaucerSwap web app or on [HashScan](https://hashscan.io/mainnet), then import it in MetaMask. If you need an ERC-20 representation of an HTS token for EVM tooling, see the [ERC-20 wrapping tutorial](/tutorials/erc20-wrapping).
## Bridge transfer looks stuck
Symptom — you bridged tokens and the source-chain transaction succeeded, but the assets have not arrived on the destination chain.
Cause — cross-chain transfers take from a few minutes to a few hours depending on the chains involved. A transfer is rarely lost; it is usually still in flight or awaiting execution on the destination chain.
Fix — track the transfer on [AxelarScan](https://axelarscan.io/) by transaction hash or wallet address. If it does not complete after the initial successful transaction, contact [Squid support](https://support.squidrouter.com/). See the [bridge tutorial](/tutorials/bridge) for expectations per route.
The Hashport bridge was permanently decommissioned on May 31, 2026, and Hashport-wrapped assets are permanently unredeemable. Do not attempt to bridge through Hashport or follow older guides that reference it. See [Bridge to Hedera](/get-started/bridge-to-hedera) for the supported paths.
## Yield farm rewards look lower than estimated
Symptom — the rewards you harvest differ from the estimate shown while farming.
Cause — estimated earnings are projected from the current APR; the displayed estimate is a front-end approximation that trades precision for the cost of reading contract balances.
Fix — no action needed. The amount you actually harvest is accurate; only the on-screen estimate is approximate.
## Next steps
Open a Discord ticket or email support if your issue is not resolved here.
Browse answers to common questions about trading, fees, and liquidity.
Fund your account with HBAR to cover network fees and trading.
Look up token association, allowances, slippage, and other terms.
# Roadmap
Source: https://docs.saucerswap.finance/roadmap
SaucerSwap Labs' development priorities: what shipped, including the V3 order book in June 2026, what is in progress, and longer-term directions.
This roadmap outlines SaucerSwap Labs' priorities for scaling the protocol and the web app. Items are grouped by development priority rather than strict chronological order, and specific timelines and implementations may evolve with technology, market conditions, and community feedback. Shipped work moves to [Completed](#completed) below; dated release notes live in the [changelog](/changelog).
## In progress and near term
* Permissionless V2 pool creation
* Auto DCA tool
* Swap widget
* Multi-currency and local timezone support
* Push notification system
* Faucet webpage and interface
* Improved token classification and listing system
* Expanded token information display on swap pages (market data, analytics, key metrics)
* Transaction reliability and success-rate optimization
* Resilient, faster app performance through multi-AZ infrastructure
* Improved smart contract monitoring and integration with key security providers
* Subgraph integration with data aggregators and analytics platforms, enabling easier access to SaucerSwap event data
* Semantic search of SaucerSwap data (LLM support)
* Website localization for key markets
* Comprehensive pool performance dashboard (deposits, earnings, analytics overview)
* V2 compound and rebalance functionality for liquidity positions
* Cross-protocol partnerships and community engagement initiatives
## Future
* Perpetual futures platform
* Multi-chain expansion strategy
* Hedera "ETF" contracts
* Decentralized website mirrors
* Universal analytics dashboard
* Advanced trading tools
* Cross-chain security infrastructure
* DAO-as-a-service and sub-DAO framework
* Institutional partnerships program
* Cross-chain liquidity networks
## Completed
### 2026
* SaucerSwap V3 order book — mainnet launch on June 12, 2026: on-chain limit and market orders, off-chain matching with on-chain settlement, and the public [Orderbook API](/api-reference/orderbook/overview). Audited by Halborn on May 18, 2026.
* Advanced charting — shipped with the V3 trade page.
* AMM smart order routing — swap quotes can use direct, multi-hop, and split paths across V1 and V2 pools; see [How swaps are routed](/protocol/routing).
* V3 AMM-backed settlement — eligible V3 orders can opt into the live one-way AMM backstop. The cross-venue AMM-versus-order-book quote comparison in [thread 385](https://gov.saucerswap.finance/t/v3-order-book-calibration-contract-migration-market-set-and-fee-configuration/385), proposal 6285, and final election 6296 was ratified on July 22, 2026, but is not verified as deployed.
* Comprehensive app redesign — updated navigation, transaction flow, token menu, and mobile responsiveness.
* Revamped developer documentation — this docs overhaul, July 2026.
* HTS ↔ ERC-20 wrapping tool — see the [wrapping tutorial](/tutorials/erc20-wrapping).
### Earlier milestones
* Mobile app (iOS and Android); wallet audited by QuantStamp on August 20, 2025
* Axelar bridge and LayerZero integrations
* Fiat onramp integration
* Token-weighted voting and governance delegation
* Hedera WalletConnect and MetaMask integrations
* LARI system refinement and automation
* Global search bar
* SAUCE 300 pool ranking system (supports revised token classification)
* Basic user support triaging automation
* SaucerSwap V2 — concentrated-liquidity AMM contracts, LARI, interface, audit, whitepaper, testnet bug bounty, and mainnet launch
* Updated tokenomics model and upgraded buyback program
* Active liquidity management protocol integration
* SDK and API documentation; integrations with data aggregators
* Single-sided staking (Infinity Pool)
* Legal formation of the DAO; Hashgraph DeFi Alliance
* HBAR Foundation grant
* Updated router contract deployment following the [Hedera network security update](https://medium.com/@SaucerSwap/hedera-network-security-update-saucerswap-8d2609b43e20)
* SaucerSwap V1 — AMM contracts, yield farm, audit, whitepaper, testnet bug bounty, and mainnet launch
## Next steps
See dated release notes for shipped protocol, app, and API changes.
Roadmap priorities that touch protocol economics move through the DAO.
Get oriented on the shipped protocol before reading about what is next.
# SAUCE tokenomics
Source: https://docs.saucerswap.finance/tokenomics/overview
SAUCE supply, allocations, and emissions: the completed genesis vesting, the Masterchef schedule, and how V1, V2, and V3 fees flow back to SAUCE.
SAUCE is the native token of the SaucerSwap protocol, created and managed through the [Hedera Token Service](https://hedera.com/token-service) (HTS).
| Property | Value |
| ----------- | -------------------------------------------- |
| Token ID | `0.0.731861` |
| EVM address | `0x00000000000000000000000000000000000b2ad5` |
| Max supply | 1,000,000,000 SAUCE |
SAUCE is a transferable representation of utility functions in the protocol's code:
* **Governance.** SAUCE and xSAUCE carry voting power in the SaucerSwap DAO — see [Governance](/governance/overview).
* **Liquidity incentives.** The Masterchef contract mints SAUCE to reward V1 farms and V2 [LARI](/protocol/saucerswap-v2#liquidity-aligned-reward-initiative-lari) positions.
* **Staking.** Staking SAUCE for xSAUCE earns a share of protocol revenue and tiered [V3 fee discounts](/protocol/saucerswap-v3/fees) — see [Single-sided staking](/protocol/single-sided-staking).
## Supply structure
At genesis (August 2022), 500 million SAUCE were minted: 200 million entered circulation immediately, and 300 million were locked in non-upgradable vesting contracts owned by the SaucerSwap DAO. The remaining 500 million are minted by the Masterchef contract on a predefined emission schedule.
### Initial supply (distributed at genesis)
A total of 200 million SAUCE was released at genesis. The Liquidity, Marketing, and Operations categories fell under DAO ownership; the Community category was distributed to 729 eligible community members.
| Category | Tokens | % of initial supply | % of max supply |
| ---------- | ----------------- | ------------------- | --------------- |
| Liquidity | 20.0 million | 10.00% | 2.00% |
| Community | 140.0 million | 70.00% | 14.00% |
| Marketing | 20.0 million | 10.00% | 2.00% |
| Operations | 20.0 million | 10.00% | 2.00% |
| **Total** | **200.0 million** | **100.00%** | **20.00%** |
* **Liquidity:** converted to SAUCE/HBAR LP tokens and locked for one year.
* **Community:** airdropped to holders of Planck Epoch Collectible (PEC) NFTs by type and count (Gravity 3,000 SAUCE; Electromagnetic 5,000; Weak Nuclear 14,000; Strong Nuclear 30,000).
* **Marketing and Operations:** sent to DAO-controlled multisigs.
There were no private sales of SAUCE.
### Genesis vesting schedule (completed)
The DAO deployed non-upgradeable vesting contracts holding 300 million SAUCE. The three-year linear vesting schedule ended on July 16, 2025.
| Category | Tokens | % of max supply | Vesting contract |
| ---------------- | ----------------- | --------------- | ---------------- |
| Core development | 240.0 million | 24.00% | `0.0.1059453` |
| Marketing | 20.0 million | 2.00% | `0.0.1059333` |
| Operations | 20.0 million | 2.00% | `0.0.1059313` |
| Advisor | 20.0 million | 2.00% | `0.0.1059259` |
| **Total** | **300.0 million** | **30.00%** | |
The end of a vesting schedule does not guarantee that every vested token has been withdrawn. Checked July 29, 2026: Core Development, Operations, and Advisor held 0 SAUCE; Marketing held 199,961.736852 SAUCE.
## Masterchef emissions
The Masterchef contract acts as both the treasury account and the supply key for SAUCE, minting and distributing the remaining emission allocation. On August 8, 2023, the DAO approved the [Tokenomics V2 proposal](https://medium.com/@SaucerSwap/saucerswap-v2-tokenomics-proposal-b355182545a6), which reduced the pool-reward rate by 60% from the V2 launch onward. The configured model reaches its planned endpoint in September 2027, although governance can change the rate or schedule.
The live Masterchef configuration checked July 29, 2026 uses 5,000 allocation points:
| Pool-reward destination | Allocation points | Share of pool rewards | SAUCE/min |
| ----------------------- | ----------------: | --------------------: | -------------: |
| V1 farms | 788 | 15.76% | 19.989833 |
| LARI | 2,314 | 46.28% | 58.701108 |
| DAO | 1,898 | 37.96% | 48.148100 |
| **Pool rewards** | **5,000** | **100.00%** | **126.839040** |
The additive devcut is 10% of pool rewards: 0.2113984 SAUCE/sec, or 12.683904 SAUCE/min. It is minted in addition to the pool-reward rate, so gross Masterchef minting is 2.3253824 SAUCE/sec, or 139.522944 SAUCE/min.
* **V1 farms:** distributed to V1 LP stakers by [farm allocation point](/protocol/saucerswap-v1/farm-weights).
* **LARI:** funds [V2 liquidity rewards](/protocol/saucerswap-v2/lari-weights), with per-pool allocations published for each epoch.
* **DAO:** accrues to the DAO treasury for governance-controlled use.
* **Devcut:** economically allocated to xSAUCE single-sided staking under the current ratified policy. An operational splitter may still appear in the transfer path.
Allocation points, emission rate, and terminal period are governance-adjustable. Treat this as a dated configuration snapshot and verify live state before relying on it.
## Fee flows: buybacks and burn
Emissions are one side of SAUCE tokenomics; the other is protocol revenue flowing back into the token. The following source-specific allocation policy was ratified through [V3 Launch Economics, thread 368](https://gov.saucerswap.finance/t/v3-launch-economics/368), proposal 6123, and final passing election 6141:
| Source | Destination | Share |
| ----------------------------------------------- | ---------------------------------------------- | ----: |
| V1/V2 fee-switch revenue + HBAR staking rewards | xSAUCE | 50% |
| | Development | 10% |
| | Burn | 10% |
| | Protocol-owned liquidity and incentive reserve | 30% |
| V3 net fees | xSAUCE | 30% |
| | Development | 60% |
| | Burn | 10% |
| Masterchef devcut | xSAUCE | 100% |
Fee-switch proceeds and net V3 fees fund SAUCE buybacks through BrewSaucer before the purchased SAUCE is routed to its economic destinations. “Net V3 fees” means taker fees collected less any maker rebates paid. Burns permanently reduce outstanding supply; they do not alter the configured Masterchef schedule or its planned terminal period.
Governance forum text establishes the proposal's scope and chronology; a final passing election establishes ratification. [Thread 385](https://gov.saucerswap.finance/t/v3-order-book-calibration-contract-migration-market-set-and-fee-configuration/385), proposal 6285, and final election 6296 ratified an order-book recalibration on July 22, 2026, but its new fee configuration and cross-venue routing are not verified as deployed. The source-allocation matrix above remains tied to election 6141.
## Historical appendix: the original (pre-V2) model
The original model released 20% of max supply at genesis — categorized at the time as liquidity (2%), airdrops (14%), faucet and giveaways (2%), and DAO treasury (2%) — and emitted the remaining 80% linearly over three years at a constant combined rate of approximately 507.36 SAUCE per minute across vesting and Masterchef streams.
Because Hedera has no block concept, emissions were defined per minute (Hedera maps `block.timestamp` to the transaction consensus timestamp).
| Stream | % of max supply | SAUCE/min |
| ---------------------------- | --------------- | ---------- |
| Team (vesting) | 24.0% | 152.21 |
| Advisor (vesting) | 2.0% | 12.68 |
| Marketing (vesting) | 2.0% | 12.68 |
| DAO treasury (vesting) | 2.0% | 12.68 |
| LP farm rewards (Masterchef) | 50.0% | 317.10 |
| **Total** | **80.0%** | **507.36** |
From genesis to V2 launch, pool rewards were approximately 317.10 SAUCE per minute, with an additive 10% devcut. The Tokenomics V2 proposal (approved August 8, 2023) reduced the pool-reward rate to 126.83904 SAUCE per minute at V2 launch and changed the allocation model.
Exact projected category totals at full emission are intentionally omitted. The historical planning workbook's component formulas and scenario totals do not fully reconcile, and governance can change future allocation points or emission parameters. On-chain supply and contract balances remain the authoritative current-state record.
## Next steps
Where buyback revenue compounds for SAUCE stakers.
The order book fee flow behind buybacks and burns.
How the DAO adjusts emissions and treasury flows.
Current per-epoch reward allocations.
# Bridge assets in the app
Source: https://docs.saucerswap.finance/tutorials/bridge
Move tokens between Hedera and other chains from SaucerSwap's bridge page, with routing over Axelar and LayerZero, fee expectations, and fixes.
The **bridge** page moves assets between Hedera and other chains without leaving the SaucerSwap app. Transfers route over the Axelar and LayerZero interoperability networks — the same infrastructure behind Squid and Stargate — with the routing handled for you.
Never bridge through Hashport guides or contracts: the Hashport bridge was permanently decommissioned on May 31, 2026, and assets wrapped by it are permanently unredeemable. See [Bridge to Hedera](/get-started/bridge-to-hedera).
## Prerequisites
* A connected [wallet](/get-started/wallet) — cross-chain routes generally work best with an EVM wallet such as MetaMask, which can hold assets on both sides
* Gas on the source chain (HBAR when bridging from Hedera; the native token of the source chain otherwise)
* The token you want to bridge
## Bridge step by step
Go to the **bridge** page and connect your wallet.
Select the source chain and the token you are sending, then the destination chain and the token to receive.
Enter how much to bridge. Review the quoted route, the estimated fees (network gas on both chains plus the route's bridge fee), and the estimated arrival time before continuing.
Approve the token if prompted, then confirm the bridge transaction in your wallet.
Cross-chain transfers take anywhere from a few minutes to a few hours depending on the chains involved. The source-chain transaction confirming quickly does not mean the transfer is complete — delivery happens in a second transaction on the destination chain.
Check your balance on the destination chain. For Axelar-routed transfers, track progress on [AxelarScan](https://axelarscan.io/) by searching your transaction hash or wallet address.
## Troubleshooting
| Problem | What to do |
| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Transfer seems stuck | Look up the transaction hash on [AxelarScan](https://axelarscan.io/); most "stuck" transfers are still propagating between chains |
| Tokens arrived but are invisible | On Hedera, associate the token with your account; in MetaMask, import the token by its EVM address |
| Transaction fails at the start | Check you have enough gas on the source chain and that your wallet holds the token being bridged |
| Issue after a successful source transaction | For Squid/Axelar routes, contact [Squid support](https://support.squidrouter.com/) with your transaction hash |
More error-keyed fixes are in [Troubleshooting](/resources/troubleshooting).
## Next steps
The Axelar and LayerZero routes, and the Hashport decommission notice.
Trade bridged tokens for any listed HTS token.
Token issuers: deploy an HTS token to other chains via Axelar ITS.
# Wrap between HTS and ERC-20
Source: https://docs.saucerswap.finance/tutorials/erc20-wrapping
Use SaucerSwap's ERC-20 wrapping tool to convert tokens between their HTS and ERC-20 forms for MetaMask and EVM tooling, and unwrap them back.
Hedera has two token standards living side by side: native Hedera Token Service (HTS) tokens and ERC-20 contract tokens on Hedera's EVM layer. Most of the Hedera ecosystem uses HTS, but some EVM-native wallets, contracts, and cross-chain tooling expect ERC-20. The [ERC-20 wrapping tool](https://www.saucerswap.finance/erc20) converts a token between the two forms, in both directions.
## When you need it
* You bridged or received a token in its ERC-20 form and want to use it on HTS-native surfaces.
* An EVM contract or integration you use (typically via MetaMask) expects a standard ERC-20 rather than an HTS token.
* A cross-chain workflow hands you one form and the destination app needs the other.
If you just want to see an HTS token inside MetaMask, you usually do not need to wrap — importing the token by its EVM address is enough. See [Why can I not see my tokens in MetaMask?](/get-started/faq#why-can-i-not-see-my-tokens-in-metamask)
## Wrap or unwrap
Go to [saucerswap.finance/erc20](https://www.saucerswap.finance/erc20) and connect your wallet.
Select whether you are wrapping (HTS to ERC-20) or unwrapping (ERC-20 to HTS), then pick the token and enter the amount.
Review the transaction and sign it in your wallet. Your balance moves from one form to the other; the interface shows both.
## Risks and caveats
Wrapped and unwrapped balances are separate assets: apps that read one form will not see the other. Before wrapping a large amount, convert a small test amount and confirm the destination app sees it as expected.
* Each wrap or unwrap is a transaction and costs HBAR network fees.
* Receiving the HTS form of a token requires [token association](/get-started/faq#what-is-a-token-association) first; the interface prompts you when needed.
* As always, review exactly what your wallet asks you to sign.
## Next steps
Add the Hedera network to MetaMask and manage EVM-form tokens.
Move tokens between Hedera and other chains in the app.
Trade your tokens against SaucerSwap liquidity.
# Provide liquidity on V1
Source: https://docs.saucerswap.finance/tutorials/liquidity-v1
Supply tokens to SaucerSwap V1 constant-product pools, stake LP tokens in the yield farm, harvest SAUCE and HBAR rewards, and withdraw liquidity.
SaucerSwap V1 pools are classic constant-product AMM pools: you deposit both tokens of a pair at the current ratio and receive LP tokens representing your share. Swap fees accrue inside the pool, so your LP tokens grow in value; staking them in the yield farm earns additional SAUCE and HBAR rewards.
V1 is the legacy liquidity system. For new positions, [V2 concentrated liquidity](/tutorials/liquidity-v2) is recommended — it offers better capital efficiency and LARI rewards. V1 remains fully supported.
## Prerequisites
* A connected [Hedera wallet](/get-started/wallet)
* [HBAR](/get-started/hbar) to cover network fees
* Both tokens of the pair, in roughly equal value
## Supply liquidity
Go to the **pool** page and locate the V1 pool for your pair. Your existing positions are also visible on the **dashboard** page under **V1 Pools**.
Open the pool and choose to supply. Enter how much of either token you want to add — the interface fills in the matching amount of the other token at the pool's current ratio.
Confirm the supply and complete the transaction in your wallet. You receive LP tokens representing your share of the pool.
## Withdraw liquidity
Find your position via the **dashboard** page (**V1 Pools**) or directly from the pool page.
Choose to withdraw, specify how many LP tokens to redeem, confirm, and complete the transaction in your wallet.
Unlike V2, where fees are claimed manually, V1 fees accumulate directly in the pool and increase the value of each LP token. Withdrawing liquidity automatically pays out your share of earned fees.
## Farm your LP tokens
Pools with active farm rewards are marked on the **pool** page. Staking LP tokens in the farm earns SAUCE and HBAR emissions on top of swap fees.
From the pool's position view, locate the stake-liquidity option, enter the number of LP tokens to stake, confirm, and sign in your wallet. If you have no LP tokens yet, supply liquidity first.
Your pending SAUCE and HBAR rewards accrue continuously. Open the harvest view for the pool, select harvest, and complete the transaction to claim them. Farm positions are also listed on the **dashboard** page under **V1 Farms**.
To exit the farm, choose unstake, specify the share of LP tokens to unstake, and confirm in your wallet. You can then withdraw the underlying liquidity.
## Create a new V1 pool
V1 pool creation is permissionless. On the **pool** page, choose to create a V1 pool, select both tokens, and set the initial deposit amounts — their ratio sets the pool's starting price, so match market prices to avoid immediate arbitrage losses. Pool creation carries a fee (≈\$50 paid in HBAR as of July 2026, shown in the interface) as an anti-spam measure.
V1 supports tokens with fractional custom fees (net-of-transfers disabled) but not fixed-fee tokens. See [Does SaucerSwap support tokens with custom fees?](/get-started/faq#does-saucerswap-support-tokens-with-custom-fees)
Providing liquidity exposes you to impermanent loss: if the pair's price ratio diverges from your entry, your position can be worth less than holding the tokens. See [What is impermanent loss?](/get-started/faq#what-is-impermanent-loss)
## Next steps
The recommended path: concentrated liquidity with fee tiers and LARI rewards.
How constant-product pools and the yield farm work under the hood.
Monitor pools, farms, and rewards on the dashboard.
# Provide liquidity on V2
Source: https://docs.saucerswap.finance/tutorials/liquidity-v2
Create and manage SaucerSwap V2 concentrated liquidity positions: choose a fee tier, set a price range, claim fees, earn LARI, or use auto pools.
SaucerSwap V2 uses concentrated liquidity: instead of spreading your capital across all prices, you choose a price range where it works. Inside the range you earn a share of swap fees (and LARI rewards on incentivized pools); outside it, your position sits idle in a single token until price returns.
## Prerequisites
* A connected [Hedera wallet](/get-started/wallet)
* [HBAR](/get-started/hbar) to cover network fees
* Tokens for the pair you want to provide
## Create a manual position
Go to the **pool** page and find the V2 pool for your pair. Pools differ by fee tier (0.05%, 0.15%, 0.30%, or 1.00%) — higher tiers compensate for more volatile pairs.
Open the pool and choose to create a new position.
This is the decision that drives your returns. You have three ways to set it:
* **Volatility strategy** — pre-configured ranges such as **Focused**, **Balanced**, and **Relaxed**. Focused earns more per dollar while in range but falls out of range sooner; Relaxed is the reverse.
* **Manual input** — set exact upper and lower price limits.
* **Depth chart handles** — drag range handles directly on the liquidity chart.
A tighter range means higher fee yield per dollar while price stays inside it, and more frequent rebalancing when it does not. If you would rather not manage a range, see [auto pools](#auto-pools) below.
Enter the amount of either token; the interface computes the other side from your chosen range. A range entirely above or below the current price deposits a single token — this emulates a fee-earning limit order that converts one token to the other as price crosses your range.
Check the amounts, range, and slippage tolerance, then confirm and complete the transaction in your wallet. Your position is minted as an NFT-style position you manage individually.
## Manage a position
Your positions are accessible from the **dashboard** page under **V2 Pools**, or directly from the pool page.
* **Increase liquidity** — open the position, choose to increase, enter the additional amounts, and confirm in your wallet.
* **Decrease liquidity** — choose to decrease, use the slider to pick how much to withdraw, and confirm. Fees earned so far are unaffected until claimed.
* **Claim fees** — open the claim view to see accrued amounts of both tokens, then collect and complete the transaction. V2 fees do not compound automatically; claim them periodically.
Positions in LARI-incentivized pools earn rewards automatically every two weeks with no staking step — see [SaucerSwap V2](/protocol/saucerswap-v2) for how LARI works.
## Auto pools
Auto pools manage the price range for you: you deposit a single token into a vault, and the vault maintains and rebalances a range position. Pools with a vault carry an **AUTO** marker on the **pool** page.
Open an AUTO-marked pool, choose the auto option when creating a position, select the vault, enter your single-token deposit amount, and confirm in your wallet.
The position view shows your deposited liquidity plus vault-level stats such as TVL and earned fees. Vault positions appear on the **dashboard** page under **V2 Vaults**.
From the withdraw view, choose the amount with the slider or preset buttons, then confirm the transaction in your wallet.
## Common mistakes
An out-of-range position earns nothing. When price exits your range, your liquidity converts fully into one token and stops earning fees until price returns or you rebalance. Check your positions after large market moves.
* **Ignoring impermanent loss.** Concentration amplifies it: a tight range converts your capital into the depreciating token faster than a full-range position would. See [What is impermanent loss?](/get-started/faq#what-is-impermanent-loss)
* **Choosing the wrong fee tier.** A stable pair in a 1.00% pool sees little volume; a volatile pair in a 0.05% pool undercompensates your risk. Match the tier the market actually uses — pool volume on the **pool** page tells you.
* **Forgetting to claim fees.** V2 fees sit unclaimed until you collect them; they are not auto-compounded into the position.
## Next steps
Concentrated liquidity math, fee tiers, and the LARI program in depth.
Monitor positions, unclaimed fees, and LARI earnings on the dashboard.
The legacy constant-product pools and yield farm.
# Track your portfolio
Source: https://docs.saucerswap.finance/tutorials/portfolio
Use the SaucerSwap dashboard to monitor token balances, V1 and V2 positions, farm and LARI rewards, xSAUCE, order history, and any watched address.
The **dashboard** page collects everything you hold on SaucerSwap in one place: token balances, liquidity positions, farm and LARI rewards, staking, and your order book history.
## Prerequisites
* A [Hedera wallet](/get-started/wallet) to connect — or just an account ID you want to look at, since portfolio data is public on Hedera
## The Overview tab
The **Overview** tab has two sections.
**My Stats** summarizes value and pending rewards:
| Stat | What it shows |
| ---------------------- | --------------------------------------------------------- |
| Account Value | The combined value of your tracked holdings |
| Unclaimed V2 Earnings | Swap fees accrued to your V2 positions, not yet collected |
| V2 LARI Earnings | LARI rewards attributed to your V2 positions |
| Unclaimed Farm Rewards | Pending V1 farm rewards, in SAUCE and HBAR |
**My Positions** groups your holdings by product: **Tokens**, **V1 Pools**, **V2 Pools**, **V1 Farms**, **V2 Vaults**, **xSAUCE**, and **LARI**. Each group links through to the page where you manage that position — claim V2 fees, harvest farm rewards, or unstake.
Unclaimed V2 fees and farm rewards do not compound. If the dashboard shows meaningful unclaimed amounts, collect them from the position pages.
## The Order History tab
The **Order History** tab lists your V3 order book activity: placed orders, fills, cancellations, and expirations. Use it to reconcile partial fills and confirm cancellations reached a final state. See the [trade tutorial](/tutorials/trade) for how order lifecycles work.
## Watch any address
You do not need to connect a wallet to inspect a portfolio. Enter any Hedera account ID to view its holdings and positions read-only — useful for monitoring a cold wallet, a treasury, or a trader you follow. All of this data is public on Hedera; the dashboard just assembles it.
## Next steps
Collect accrued fees and manage your concentrated liquidity positions.
Understand order statuses and cancellation finality on the order book.
Put unstaked SAUCE to work in the Infinity Pool.
# Stake SAUCE
Source: https://docs.saucerswap.finance/tutorials/stake
Stake SAUCE in the Infinity Pool and receive xSAUCE, a liquid staking token that compounds trading fees, farm allocations, and HBAR staking rewards.
Single-sided staking deposits SAUCE into the Infinity Pool and gives you xSAUCE in return. There is no pairing, no lockup, and no impermanent loss: the SAUCE/xSAUCE exchange rate rises as protocol rewards flow into the pool, so your xSAUCE redeems for more SAUCE over time.
## Prerequisites
* A connected [Hedera wallet](/get-started/wallet)
* [HBAR](/get-started/hbar) to cover network fees
* SAUCE to stake — or just HBAR, which the stake flow can convert for you
## What fuels your rewards
The **stake** page lists the three reward sources that feed the Infinity Pool:
| Source | How it works |
| ------------------- | ------------------------------------------------------------------------------------------ |
| 01 Trading fees | Every swap on SaucerSwap generates protocol fees, used to buy SAUCE and send it to stakers |
| 02 Farm allocations | A share of SAUCE emissions goes to the staking pool |
| 03 HBAR staking | Pooled HBAR is staked to Hedera, and those rewards buy SAUCE for the pool |
For the mechanics and a worked rate example, see [Single-sided staking](/protocol/single-sided-staking).
## Reading the metrics
* **SAUCE/xSAUCE rate** — how much SAUCE one xSAUCE redeems for. It only moves one way: up, as rewards are added (roughly daily).
* **TVL** — the total value staked in the Infinity Pool.
* **Approximate APR** — an estimate derived from the recent growth of the exchange rate; it varies with protocol activity and is not guaranteed.
## Stake
Go to the **stake** page and select **Connect Wallet** if you have not already connected.
Enter how much SAUCE to stake. If you hold HBAR but no SAUCE, the stake flow can swap HBAR for SAUCE and stake it in one pass — choose HBAR as the input instead.
Confirm the stake and sign the transaction in your wallet. If xSAUCE is not yet associated with your account, you are prompted to associate it first.
Your rewards accrue automatically as the SAUCE/xSAUCE rate rises — there is nothing to claim or compound. Your xSAUCE balance appears on the **dashboard** page.
## Unstake
On the **stake** page, switch to the unstake side and enter the amount of xSAUCE to redeem.
Confirm and complete the transaction in your wallet. You receive SAUCE at the current exchange rate — your original stake plus accrued rewards.
You can stake and unstake at any time. There are no lockup periods and no slashing.
xSAUCE is itself a liquid HTS token: you can hold it, transfer it, or use it in supported pools while it keeps appreciating against SAUCE. It also carries governance weight — see [Governance](/governance/overview).
## Next steps
The xSAUCE rate mechanics, reward sources, and a worked example.
Use your SAUCE and xSAUCE to vote on protocol decisions.
See your xSAUCE position and all other holdings on the dashboard.
# Swap tokens
Source: https://docs.saucerswap.finance/tutorials/swap
Swap any listed HTS token on SaucerSwap: pick tokens, set slippage tolerance, review the quote and fees, approve an allowance, and confirm in your wallet.
The **swap** page executes trades instantly against SaucerSwap's V1 and V2 AMM liquidity, automatically routing your trade for the best quoted price. If you want to set your own price instead, use the [order book](/tutorials/trade).
## Prerequisites
* A connected [Hedera wallet](/get-started/wallet)
* [HBAR](/get-started/hbar) to cover network fees
* Tokens to swap (HBAR itself works)
## Swap step by step
Open the [web app](https://www.saucerswap.finance/), go to the **swap** page, and select **Connect Wallet**. Approve the connection in your wallet.
Select the token in the **Sell** field to open the token menu, and pick what you are selling. Do the same in the **Buy** field for the token you want to receive.
Tokens come in three classes: default tokens appear in the menu directly, extended tokens require acknowledging a disclaimer, and untracked tokens must be entered manually by token ID (for example `0.0.123456`) and also require a disclaimer. See [How does the token listing process work?](/get-started/faq#how-does-the-token-listing-process-work)
Type the amount you want to sell, or use the percentage shortcuts (**25%**, **50%**, **MAX**). The **Buy (estimated)** field shows what you can expect to receive. You can instead enter the amount in the buy field to work backward from an exact amount to receive — the sell side then becomes the estimate.
Slippage tolerance is the maximum difference you accept between the quoted and executed price; the swap fails rather than exceed it. The default is 0.5%. A lower value protects your price but can cause failed transactions in volatile or thin markets; a higher value does the reverse. Adjust it in the swap settings. See [What is slippage?](/get-started/faq#what-is-slippage)
Before confirming, check the quote details:
| Detail | Meaning |
| ---------------- | -------------------------------------------------------------------------------------------- |
| Minimum received | The least you can receive after slippage (selling an exact amount) |
| Maximum sold | The most you can sell after slippage (buying an exact amount) |
| Price impact | How much your trade moves the pool price; high impact means low liquidity |
| Fee | The pool swap fee, 0.05% to 1.00% depending on the pool; multi-hop routes pay a fee per pool |
Of each swap fee, 5/6 goes to liquidity providers and 1/6 to the protocol. Network fees are separate and paid in HBAR.
Choose between a one-time [token allowance](/get-started/faq#what-is-a-token-allowance) for this exact amount or a maximum allowance that skips approval on future swaps. Confirm the swap and sign the transaction in your wallet. If the receiving token is not yet associated with your account, the interface prompts you to associate it first.
The interface confirms the completed swap, and your updated balances appear on the **dashboard** page. For an independent record, look up the transaction on [HashScan](https://hashscan.io/mainnet/dashboard).
If the swap fails with a contract revert, your slippage tolerance is usually too low for current market conditions. See [Troubleshooting](/resources/troubleshooting).
## Next steps
Set your own price with limit orders on the V3 order book.
Earn the fees you just paid by supplying liquidity to V2 pools.
See balances, positions, and rewards on the dashboard.
# Trade on the order book
Source: https://docs.saucerswap.finance/tutorials/trade
Use the SaucerSwap V3 central limit order book: read depth and the trade tape, place limit and market orders, track fills, and cancel open orders.
The **trade** page is SaucerSwap V3: a central limit order book (CLOB) where you set the price instead of taking the pool's. Orders are matched off-chain and settled on-chain, and on enabled markets they can also fill against AMM liquidity. For the concepts behind it, see [SaucerSwap V3](/protocol/saucerswap-v3).
Order book trading carries risks beyond swapping: orders can fill partially, later than expected, or at prices different from interface estimates, and displayed statuses can be provisional. Read the [V3 order book risk notice](/legal/orderbook-risk-notice) before trading.
## Prerequisites
* A connected [Hedera wallet](/get-started/wallet)
* [HBAR](/get-started/hbar) to cover network fees
* Tokens on the side of the market you want to trade
## Reading the market
Each market pairs a base token with a quote token, priced as quote per base. The main surfaces on the page:
| Surface | What it shows |
| ----------- | -------------------------------------------------------------------------------------------------------------------- |
| Order book | Resting buy orders (bids) and sell orders (asks) by price level; the gap between best bid and best ask is the spread |
| Trade tape | Recent fills in the market — price, size, and side, most recent first |
| Price chart | The market's price history |
| Order entry | Where you choose side, order type, price, and amount |
Markets have trading increments: prices and sizes snap to the market's tick and lot grid, and each order must meet the market's minimum notional. A market can also be halted by the operator, during which orders do not match.
## Order types
* **Market order** — executes immediately against the best available prices in the book (and AMM liquidity on enabled markets). You trade certainty of execution for certainty of price.
* **Limit order** — rests in the book at your chosen price until it fills, you cancel it, or it expires at its deadline. Limit order deadlines range from 30 seconds to 90 days. A resting limit order is maker flow; an order that crosses the spread takes liquidity.
Fees differ by role: takers pay a fee while makers can receive a rebate, and rates are set per market. See [V3 fees](/protocol/saucerswap-v3/fees).
## Place an order
Go to the **trade** page and select the market you want from the market selector.
Before your first order, the interface requires you to accept the V3 legal terms in-app. Review the [risk notice](/legal/orderbook-risk-notice) and [terms of service](/legal/terms-of-service) first.
Pick buy or sell, then market or limit. For a limit order, set your price and, if you want one, an expiry deadline; for a market order, just the amount.
Enter how much you want to trade. Check the order value, the estimated fee, and — for market orders — how far your size reaches into the book's depth. Large market orders in thin books execute at progressively worse prices.
Confirm and sign the order in your wallet. Signing authorizes settlement within the exact parameters you signed — price limit, amount, and deadline — and nothing beyond them. Review every wallet prompt before signing.
Open orders and fills appear on the trade page, and your full history is on the **dashboard** page under **Order History**. Orders can fill partially: several fills may add up to your total, and a limit order can remain partly filled until its deadline.
## Cancel an order
Select the open order and request cancellation. Cancellation is asynchronous: the request is accepted first and confirmed shortly after, so treat an order as live until you see it reach a canceled state. A cancellation can arrive too late to prevent a match that was already in flight — this is inherent to order book trading, not a malfunction.
## Order lifecycle
An order moves through: open → partially filled (possibly repeatedly) → filled, canceled, or expired. The on-chain settlement contract is the source of truth; interface and API statuses can briefly lag it. If a status looks inconsistent, check the transaction on [HashScan](https://hashscan.io/mainnet/dashboard) before acting on it.
Building a bot or integration? The same order book is fully accessible programmatically — see the [Orderbook API](/api-reference/orderbook/overview).
## Next steps
How off-chain matching, on-chain settlement, and the AMM backstop fit together.
Taker fees, maker rebates, and how fee rates are expressed.
The full V3 order book risk disclosure.
For instant execution at the best quoted route, use the swap page.