Hartii developer docs

HartiiSwap

Contracts

Source: hartii-labs/contracts/contracts/swap/ (Solidity 0.8.20, GPL-3.0-or-later for the V2 port).

HartiiSwapFactory

constructor(address feeToSetter, address feeTo) — deployed with both set to the treasury.

FunctionWhoDescription
createPair(address tokenA, address tokenB) → address pairanyoneDeploys a pair with CREATE, initializes it with the sorted tokens, records it both ways. Reverts HartiiSwap: IDENTICAL_ADDRESSES, HartiiSwap: ZERO_ADDRESS, HartiiSwap: PAIR_EXISTS. The router calls this automatically on the first addLiquidity.
getPair(address, address) → addressviewPair for either token order; zero if none. The only way to find a pair.
allPairs(uint256) → address, allPairsLength()viewEnumeration in creation order.
feeTo(), feeToSetter(), pendingFeeToSetter()viewProtocol-fee recipient and its controller.
setFeeTo(address)feeToSetterZero turns the protocol fee off.
proposeFeeToSetter(address) / acceptFeeToSetter()setter / proposedTwo-step handover.

Events: PairCreated(token0 indexed, token1 indexed, pair, index) (index is 1-based length after push, as in V2), FeeToChanged, FeeToSetterProposed, FeeToSetterAccepted.

HartiiSwapPair

Uniswap V2 pair, unchanged in behaviour. Also the LP ERC-20 (HSLP).

FunctionDescription
token0(), token1()Sorted pair tokens (token0 < token1 by address).
getReserves() → (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)Current reserves. Use these, never raw token balances, to price.
price0CumulativeLast(), price1CumulativeLast()UQ112.112 TWAP accumulators (updated on the first interaction per timestamp).
kLast()reserve0·reserve1 after the last liquidity event while the protocol fee is on.
mint(address to) → liquidityLow-level: mints LP for tokens already transferred in. Use the router.
burn(address to) → (amount0, amount1)Low-level: burns LP already transferred in. Use the router.
swap(amount0Out, amount1Out, to, data)Low-level optimistic swap; with non-empty data calls IHartiiSwapCallee(to).hartiiSwapCall(sender, amount0Out, amount1Out, data) (flash swap). Must end with balance·1000 − amountIn·3 satisfying the K check.
skim(address to), sync()Standard V2 recovery helpers.
ERC-20 + permit(owner, spender, value, deadline, v, r, s)EIP-2612; DOMAIN_SEPARATOR uses name HartiiSwap LP, version 1, and the chain id at deploy.

Reverts: HartiiSwap: LOCKED (reentrancy), INSUFFICIENT_LIQUIDITY_MINTED, INSUFFICIENT_LIQUIDITY_BURNED, INSUFFICIENT_OUTPUT_AMOUNT, INSUFFICIENT_LIQUIDITY, INVALID_TO, INSUFFICIENT_INPUT_AMOUNT, K, OVERFLOW, TRANSFER_FAILED, EXPIRED, INVALID_SIGNATURE, FORBIDDEN.

Events: Mint(sender, amount0, amount1), Burn(sender, amount0, amount1, to), Swap(sender, amount0In, amount1In, amount0Out, amount1Out, to), Sync(reserve0, reserve1), plus ERC-20 Transfer/Approval.

HartiiSwapRouter

factory() and WETH() (WQUAI). All state-changing functions take a deadline (unix seconds) and revert HartiiSwapRouter: EXPIRED after it. Pairs are resolved with factory.getPair; a missing hop reverts HartiiSwapLibrary: PAIR_NOT_FOUND.

Liquidity

FunctionNotes
addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin, to, deadline)Creates the pair if missing. First deposit uses both desired amounts as-is (it sets the price); later deposits are fitted to the pool ratio and must meet the mins (INSUFFICIENT_A_AMOUNT / INSUFFICIENT_B_AMOUNT).
addLiquidityETH(token, amountTokenDesired, amountTokenMin, amountETHMin, to, deadline) payableSame with native QUAI as the second side; excess QUAI is refunded.
removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline)Requires LP approval to the router.
removeLiquidityETH(token, liquidity, amountTokenMin, amountETHMin, to, deadline)Pays the QUAI side as native QUAI.
removeLiquidityWithPermit / removeLiquidityETHWithPermit (+ …, bool approveMax, uint8 v, bytes32 r, bytes32 s)Approve via signature in the same call.
removeLiquidityETHSupportingFeeOnTransferTokens (+ WithPermit)For taxed tokens.

Swaps

FunctionDirection
swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline)exact in
swapTokensForExactTokens(amountOut, amountInMax, path, to, deadline)exact out
swapExactETHForTokens(amountOutMin, path, to, deadline) payableQUAI in, path[0] = WQUAI
swapTokensForExactETH(amountOut, amountInMax, path, to, deadline)QUAI out
swapExactTokensForETH(amountIn, amountOutMin, path, to, deadline)QUAI out
swapETHForExactTokens(amountOut, path, to, deadline) payableexact out, refunds excess QUAI
…SupportingFeeOnTransferTokens variants of the three exact-in swapsfor taxed tokens

Reverts: INSUFFICIENT_OUTPUT_AMOUNT (slippage), EXCESSIVE_INPUT_AMOUNT, INVALID_PATH, TransferHelper: TRANSFER_FROM_FAILED (usually a missing approval to the router).

Pure/view helpers: quote(amountA, reserveA, reserveB), getAmountOut(amountIn, reserveIn, reserveOut), getAmountIn(amountOut, reserveIn, reserveOut), getAmountsOut(amountIn, path), getAmountsIn(amountOut, path). getAmountsOut equals the real swap to the wei (verified on mainnet 2026-09-23: 0.5 QUAI → 162.533099935654199908 QAXE, quote = swap = formula).

HartiiSwapLens

Stateless reads for UIs; no funds, no owner.

FunctionReturns
pool(address pair)PoolInfo { pair, token0 {token, symbol, decimals}, token1 {…}, reserve0, reserve1, totalSupply }
pools(address factory, uint256 start, uint256 count)PoolInfo[] for allPairs[start … start+count), clipped to what exists
positions(address factory, address user, uint256 start, uint256 count)Position { pair, lpBalance, totalSupply, amount0, amount1 }[]amount0/1 are the user's current share of reserves; zero balances included so indices line up with pools

A token whose symbol() reverts is returned with an empty symbol and 18 decimals rather than failing the whole call. Keep count modest (e.g. 50) — the call is unbounded by design.

Gas (measured)

OperationHardhatQuai (Orchard / mainnet)
Deploy factory / router / lens2.24M / 2.98M / 0.79M (Orchard)
addLiquidityETH, first (creates pair)1,994,3542,001,846 (Orchard), 2,170,432 (mainnet QAXE pool)
addLiquidityETH, later164,214152,259
swapExactETHForTokens143,626140,176
swapExactTokensForETH128,602
removeLiquidityETH191,726183,446
Quai Network mainnet · chain 9 · Cyprus-1. Figures marked "read on" a date were read from the chain that day; re-read before relying on them.