Skip to main content
This page is the complete reference for the IFÁ Labs Swap Contract. It covers both the periphery module (ifalabs::hetero_swap_periphery) — the intended entry point for integrators — and the core module (ifalabs::hetero_swap_core), which contains the actual logic, error codes, and admin functions. For the underlying price feed this contract consumes, see Sui Function Reference.

Package Structure

Every periphery function is a thin wrapper that delegates directly to the matching core function. There is no safety difference between calling periphery vs. core — but periphery is the documented, stable interface.

Data Types

Pool

The central shared object coordinating the swap contract.
Pass by &mut Pool for state-changing operations and &Pool for read-only quotes and summaries.

AssetConfig

Per-asset configuration stored inside the Pool. Returned as part of get_asset_summary.

AssetVault<T>

A generic shared object holding token reserves and cached valuation for asset type T.
You must pass the vault matching the coin type you’re operating on — Move’s generics enforce this at compile time.

ProtocolFeeVault<T>

A generic shared object accumulating the protocol’s fee share for asset type T.
Required as an argument for swap_exact_input and sweep — not for deposits or withdrawals.

Error Codes

These are the actual error constants from hetero_swap_core. Every abort in the swap contract maps to one of these.
E_ORACLE_PRICE_STALE and E_ORACLE_PRICE_MISSING are the two errors you will hit most often during integration testing. Both originate from the same get_price_checked internal function that every deposit, withdrawal, and swap calls before touching any balances.

Liquidity Functions

deposit_liquidity

Deposits a supported asset into the pool and mints HLP tokens proportional to the deposit’s USD value.
Parameters: Verified abort sequence:
  1. E_POOL_PAUSED if the pool is paused
  2. E_ASSET_NOT_WHITELISTED / E_ASSET_DISABLED if T isn’t whitelisted or is disabled
  3. E_ZERO_AMOUNT if the deposited coin has zero value
  4. E_ORACLE_PRICE_MISSING / E_ORACLE_PRICE_STALE if the oracle price for T is missing or stale
  5. E_ZERO_AMOUNT if the computed USD value of the deposit is zero
  6. E_LP_SUPPLY_ZERO if this is not the first deposit and accounted_value_usd is somehow zero (an invariant guard, not a normal user-facing case)
  7. E_ZERO_AMOUNT if the resulting HLP mint amount rounds to zero
  8. E_SLIPPAGE if the resulting HLP mint amount is less than min_lp_out
Behaviour notes:
  • The first-ever deposit into the pool mints HLP at a fixed ratio (USD value scaled from 30 decimals down to 9 LP decimals) — there is no existing supply to price against.
  • Every subsequent deposit mints HLP proportional to deposit_value_usd / accounted_value_usd × total_lp_supply.
  • HLP is minted directly to ctx.sender() — you cannot deposit on behalf of another address.
Example (TypeScript):

withdraw_liquidity

Burns HLP tokens to redeem a proportional share of a specific asset from the pool.
Parameters: Verified abort sequence:
  1. E_POOL_PAUSED if the pool is paused
  2. E_ASSET_NOT_WHITELISTED / E_ASSET_DISABLED if T isn’t whitelisted or is disabled
  3. E_ZERO_AMOUNT if lp_coin has zero value
  4. E_LP_SUPPLY_ZERO if total_lp_supply is zero (should never happen if you hold valid HLP)
  5. E_ORACLE_PRICE_MISSING / E_ORACLE_PRICE_STALE for asset T
  6. E_ZERO_AMOUNT if the computed output amount rounds to zero
  7. E_SLIPPAGE if the output is less than min_amount_out
  8. E_INSUFFICIENT_LIQUIDITY if vault doesn’t physically hold enough of asset T
  9. E_WITHDRAW_TOO_LARGE if the withdrawal exceeds max_withdraw_bps of the vault’s current balance
  10. E_MIN_LIQUIDITY if the withdrawal would drop the vault below its configured floor
You choose which asset to receive by which AssetVault<T> you pass — not by anything encoded in the HLP token itself. HLP represents pool-wide ownership, not a claim on any specific asset. A withdrawal can fail with E_INSUFFICIENT_LIQUIDITY even while you hold valid HLP, if the specific vault you’re withdrawing from is thin — even though the pool overall has sufficient value.

Swap Functions

swap_exact_input

Swaps an exact amount of one asset for another, priced via the oracle’s derived pair calculation.
Parameters: Verified abort sequence:
  1. E_POOL_PAUSED if the pool is paused
  2. E_SAME_ASSET if TIn and TOut are the same type
  3. E_ASSET_NOT_WHITELISTED / E_ASSET_DISABLED for either TIn or TOut
  4. E_ZERO_AMOUNT if coin_in has zero value
  5. E_ORACLE_PRICE_STALE if the derived pair’s combined timestamp is stale (checked first, via quote_exact_input_internal)
  6. E_SLIPPAGE if the net output (after both fees) is less than min_amount_out
  7. E_INSUFFICIENT_LIQUIDITY if vault_out doesn’t hold enough for amount_out + protocol_fee
  8. E_TRADE_TOO_LARGE if the raw output exceeds max_trade_bps of vault_out’s balance
  9. E_MIN_LIQUIDITY if the trade would drop vault_out below its floor
  10. E_ORACLE_PRICE_MISSING / E_ORACLE_PRICE_STALE again — re-fetched individually per-asset for USD accounting (in addition to the derived-pair check above)
Fee mechanics (verified from source): The swap computes a raw_amount_out from the oracle-derived exchange rate, then deducts two fees from it:
The lp_fee portion stays in vault_out (implicitly benefiting all LPs by not being paid out). The protocol_fee portion is physically moved into protocol_fee_vault_out. Example:

sweep

Converts a dust balance of one asset directly into a target asset. This is exposed only in the periphery module — hetero_swap_core has no separate sweep function. It calls swap_exact_input internally with renamed type parameters.
Behaviour: Identical to swap_exact_input in every respect — same abort sequence, same fee mechanics. There is no relaxed validation path for sweep transactions; it is swap_exact_input under a different name.
To sweep multiple dust tokens into one target asset, compose multiple sweep calls — one per dust token — within a single Sui Programmable Transaction Block (PTB). Each call independently enforces every check listed for swap_exact_input.

Quote Functions (Read-Only)

These simulate the result of an operation without executing it. None mutate state. All still perform the same oracle freshness checks as their state-changing counterparts — a quote can abort with E_ORACLE_PRICE_STALE exactly like a real swap would.

quote_exact_input

Returns — verified exact order from source: Example:

quote_sweep

Identical signature, identical internal logic to quote_exact_input — provided as a semantically named alias for previewing a sweep operation.
Same four-value return order as quote_exact_input.

preview_deposit

Returns: A single u64 — the expected HLP token amount to be minted. Uses the exact same math as deposit_liquidity, so this value should match what you actually receive (assuming no price change between the quote and the real transaction).

preview_withdraw

Returns: A single u64 — the expected amount of asset T you’d receive for burning lp_amount of HLP.
preview_withdraw does not check whether the target vault actually holds enough of asset T to fulfill the withdrawal, nor does it check max_withdraw_bps or min_liquidity. It only computes the proportional USD value and converts it to asset T. A real withdraw_liquidity call with the same inputs can still abort with E_INSUFFICIENT_LIQUIDITY, E_WITHDRAW_TOO_LARGE, or E_MIN_LIQUIDITY even if the preview succeeded.

Pool and Asset Inspection

get_pool_summary

Returns — verified exact order from source. Note this differs from a naive guess: total_lp_supply and accounted_value_usd come before the fee fields, not after.

get_asset_summary

The u256 value at position 4 is vault.cached_value_usd — a cached value updated only when maybe_sync_asset runs (on deposits, withdrawals, swaps, or an explicit sync_asset call, and only if sync_interval_ms has elapsed since the last sync). It is not necessarily the vault’s live USD value at query time. For an always-current value, compute it yourself from vault_balance<T>(vault) and a fresh oracle price.

Other Read-Only Functions

These are simpler getters also exposed by hetero_swap_core, useful for building dashboards without needing the full summary structs.

Admin-Only Functions

These all require the AdminCap — held by the IFÁ Labs team. Listed for transparency and so you understand what configuration changes are possible, not because integrators call them.
Notice pause is a true global switch — there is no per-asset pause. If you need to react to a paused pool in your own integration, check get_pool_summary().0 (the first return value) before attempting any operation.

Function Quick Reference


Next Steps

Sui Swap Contract Overview

Architecture, core concepts, and what’s deployed on testnet.

Swap Contract Addresses

Package ID, Pool ID, AdminCap, and every asset vault on Sui Testnet.

Sui Function Reference

The underlying oracle functions this contract consumes.

Testnet Faucet

Claim testnet tokens to try deposits and swaps yourself.