# Contracts and fees

Every Qiguard trade runs through the settlement contract of its chain. The settlement contracts are upgradeable proxies, shared with CEXORDEX. The API reads their live state (`paused()`, fee recipient, head block) and shows it in `GET /status`.

### BSC (56)

| Contract | Address |
|---|---|
| Settlement (`transaction.to`, `allowanceTarget`, gasless spender) | `0x79A76e54f354AC7567f97d979EC1b785c15e37d8` |
| USDT (the fee token of USDT-input trades) | `0x55d398326f99059fF775485246999027B3197955` |
| Wrapped native | `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` |
| `PancakeSwap_V2` adapter | `0xD81F42bc939b078684e209CD94f8700F16943622` |
| `PancakeSwap_V2` router | `0x10ED43C718714eb63d5aA57B78B54704E256024E` |
| `PancakeSwap_V3` adapter | `0xb8dfc084c3912B71662044092722fdDA40b15Ab3` |
| `PancakeSwap_V3` router | `0x1b81D678ffb9C0263b24A97847620C99d213eB14` |
| `PancakeSwap_V3` quoter | `0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997` |

### Ethereum (1)

| Contract | Address |
|---|---|
| Settlement (`transaction.to`, `allowanceTarget`, gasless spender) | `0x67433187Db1e57f66E88880b6Be833f6759362b1` |
| USDT (the fee token of USDT-input trades) | `0xdAC17F958D2ee523a2206206994597C13D831ec7` |
| Wrapped native | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` |
| `Uniswap_V2` adapter | `0xD4Ca0A78528391728De85C4FFE5db4FF86cC7043` |
| `Uniswap_V2` router | `0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D` |
| `Uniswap_V3` adapter | `0xBA521B205AB809086B78Ee0B878d1C541F34aA1a` |
| `Uniswap_V3` router | `0xE592427A0AEce92De3Edee1F18E0157C05861564` |
| `Uniswap_V3` quoter | `0x61fFE014bA17989E743c5F6cB21bF9697530B21e` |

### Base (8453)

| Contract | Address |
|---|---|
| Settlement (`transaction.to`, `allowanceTarget`, gasless spender) | `0x67433187Db1e57f66E88880b6Be833f6759362b1` |
| USDT (the fee token of USDT-input trades) | `0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2` |
| Wrapped native | `0x4200000000000000000000000000000000000006` |
| `Uniswap_V2` adapter | `0xD4Ca0A78528391728De85C4FFE5db4FF86cC7043` |
| `Uniswap_V2` router | `0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24` |
| `Uniswap_V3` adapter | `0xB47011d787B432ccF7A53284a74432a0De4397a3` |
| `Uniswap_V3` router | `0x2626664c2603336E57B271c5C0b26F421741e481` |
| `Uniswap_V3` quoter | `0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a` |

### Polygon (137)

| Contract | Address |
|---|---|
| Settlement (`transaction.to`, `allowanceTarget`, gasless spender) | `0xe9280cE8F0990c35c9CA183A7Fb942d57620C5a2` |
| USDT (the fee token of USDT-input trades) | `0xc2132D05D31c914a87C6611C10748AEb04B58e8F` |
| Wrapped native | `0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270` |
| `QuickSwap_V2` adapter | `0x7723B258DB19dB594dfe99D5AFf90c9799ae6e9e` |
| `QuickSwap_V2` router | `0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff` |
| `Uniswap_V3` adapter | `0x8Ba540B7C41278dB99467046f35C10A57526b83E` |
| `Uniswap_V3` router | `0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45` |
| `Uniswap_V3` quoter | `0x61fFE014bA17989E743c5F6cB21bF9697530B21e` |

### All chains

| Contract | Address |
|---|---|
| Permit2 | `0x000000000022D473030F116dDEE9F6B43aC78BA3` |
| Multicall3 | `0xcA11bde05977b3631167028862bE2a173976CA11` |
| Native coin placeholder | `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` |

`GET /status` returns the settlement address, `paused`, `priceBandEnforced`, `feeRecipient` and the head block of every chain, read live and cached for 15 seconds.

## Functions the API calls

| Selector | Function | Used by |
|---|---|---|
| `0xb5019436` | `marketSwap(address,address,uint256,uint256,address,bytes,uint256)` | swap, token to token |
| `0x6f1190c5` | `marketSwapNativeToToken(address,uint256,address,bytes,uint256)` (payable) | swap, selling the native coin |
| `0x1f60a2c7` | `marketSwapTokenToNative(address,uint256,uint256,address,bytes,uint256)` | swap, buying the native coin |
| `0x1701c80d` | `fillOrderWithPermit2((address,address,uint256,address,uint256,address,bytes,uint256,uint256,bytes))` | gasless, sent by the Qiguard relayer |

`routerData` (the route inside the adapter) is `abi.encode(address[] path, uint256 deadline)` for V2 sources and `abi.encode(bytes packedPath, uint256 deadline)` for V3 sources, where the packed path is token (20 bytes), fee (3 bytes), token, and so on.

## Fee rule

The fee is 0.50% (50 bps), or the lower on-chain rate of the taker wallet (`getFeeBps(taker)`). The contract takes it in the same transaction and pays it to its fee recipient:

- USDT-input trades pay it from the sell amount, in USDT.
- Every other trade pays it from the gross output, in the bought token (the native coin when buying the native coin).
- `buyAmount` and `minBuyAmount` in the API are net, and the contract checks the minimum against the net amount.

The full table is on [Swap](swap.md#fee). Gas for gasless trades is sponsored by Qiguard in v1 ([Gasless](gasless.md#sponsored-gas)).

## Calldata tag

Swap calldata ends with an 18-byte tag: `0x71673031` ("qg01") + the first 8 bytes of sha256(app id) + the first 6 bytes of the response `zid`. Example: `0x716730313eb3ac763a2a9d9c5f1c9a7e2b44`. The contract ignores bytes after the call arguments; the tag only attributes the trade to the app.

## Revert reasons

For integrators who send the swap transaction themselves, and for `detail` of a failed gasless trade.

| Selector | Error | Meaning | What to do |
|---|---|---|---|
| `0xbff79e2f` | `InsufficientNetReceived(uint256,uint256)` | The price moved beyond the slippage | Quote again |
| `0xc56873ba` | `OrderExpired()` | The deadline passed | Quote again and send sooner |
| `0x7b9d05ed` | `RouterAdapterNotAllowed()` | The adapter is no longer allowed | Quote again |
| `0x9bfa3c17` | `FeeOnTransferNotSupported()` | The token takes a transfer tax | The token is not supported |
| `0xd93c0665` | `EnforcedPause()` | The settlement contract is paused | Wait; see `GET /status` |
| `0x8686656d` | `InvalidTokenPair()` | For example native coin and its wrapped token | Use another pair |
| `0x2c5211c6` | `InvalidAmount()` | Zero amount | Send a positive amount |
| `0x756688fe` | Permit2 `InvalidNonce()` | The Permit2 nonce is used or invalidated | Quote and sign again |
| `0xcd21db4f` | Permit2 `SignatureExpired(uint256)` | The signed deadline passed | Quote and sign again |
| `0x815e1d64` | Permit2 `InvalidSigner()` | The signer is not the taker | Sign with the taker wallet |
| `0x8baa579f` | Permit2 `InvalidSignature()` | The signature does not match | Sign `trade.eip712` again |
| string `TRANSFER_FROM_FAILED` | Permit2 token pull | The allowance or balance is gone | Top up or approve again |
