# Fabric > Next Generation DEX Aggregator import '../styles/toy.css' import { Animation } from '../components/Animation'
## Approvals When the input token (`sellToken`) is an ERC-20 token, the executor contract must be approved to spend at least the quoted input amount before a fill can execute. Upon entry, the executor contract will attempt to capture the input tokens from the sender. If the sender has not approved the executor contract to spend the required amount of input tokens, the transaction will revert. ### Approval Payload From Quote Quote responses include approval key data only. They do not include a pre-built approval transaction payload. | Field | Type | Description | | --------- | -------- | -------------------------------------------------- | | `token` | `string` | ERC-20 token address to approve. | | `amount` | `string` | Exact approval amount (bigint string, base units). | | `spender` | `string` | Router/spender contract address. | Quotes include an `approval` object for ERC-20 input tokens: ```json { "approval": { "token": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "amount": "1000000", "spender": "0x7c137a37742437d2212b7bd873ed135b5c4c61da" } } ``` ### Approving Use the provided approval data to construct an ERC-20 `approve` transaction and submit it with or before the fill transaction, if necessary. Fabric does **not** perform: * balance checks * allowance checks Integrators must decide whether to submit an approval transaction. ### Recommended Pattern With EIP-7702 and other batching mechanisms, exact approvals atomically bound to the fill are recommended. ## Authentication Fabric does not currently require authentication to request quotes. Requests without an app ID are subject to stricter rate limits and do not have access to custom fee configuration. ### App Identification Header Use the `x-app-id` header to identify the calling app. * You can choose your own app ID for basic identification. * For custom fee configuration or increased rate limits, Fabric will issue an app ID. ## Chain Support We are actively working to expand chain support. Please reach out to us if you have a specific chain you'd like to see supported. | Chain | Status | Notes | | -------- | --------- | --------------- | | Base | `active` | Launched Q1 26 | | Arbitrum | `testing` | Launching Q1 26 | | Ethereum | `planned` | Early Q2 26 | ## Execution Each quote provides a transaction payload to execute the fill. Integrators can submit this transaction payload directly to the blockchain or use it as a reference to construct their own transaction with a different entry point. ### Transaction Payload from Quote Quote responses include a `transaction` object with the following fields: | Field | Type | Description | | ------- | -------- | ---------------------------------------------- | | `to` | `string` | Address of the contract to call for execution. | | `data` | `string` | Calldata for the transaction (Hex string). | | `value` | `string` | Amount of native token (ETH) to send. | Example: ```json "transaction": { "to": "0x7c137a37742437d2212b7bd873ed135b5c4c61da", "data": "0x411bac040000000000000000000000000000....", "value": "0" } ``` ### Native Token Inputs When the input token is a native token (for example, ETH on Ethereum), the `value` field will indicate the amount of native token to send with the transaction. In this case, no ERC-20 approval is necessary. ### Gas Limit Gas is not estimated onchain by the quote API. Integrators must estimate and specify an appropriate gas limit when submitting the transaction for execution. A 50% buffer above estimated gas is recommended to account for estimation variance and ensure transactions do not fail due to out-of-gas errors. ### ERC-20 Token Inputs When the input token is an ERC-20 token, the `value` field will be `0`. In this case, integrators must ensure the executor contract is approved to spend the required amount of input tokens before submitting the transaction. See [Approvals](./approvals) for more details. The executor contract will attempt to capture the input tokens from `msg.sender` upon execution. If the sender has not approved the executor contract to spend the required amount of input tokens, the transaction will revert. ### Wrapping the Contract If you have your own execution contract that wraps the router, you can use the provided transaction payload as a reference to construct a transaction to your own contract. Your contract can then call the router with the provided calldata and parameters. Ensure that: * Your contract correctly forwards the necessary amount of native token (if applicable). * Your contract has the necessary approvals in place to transfer ERC-20 input tokens from `msg.sender` (your contract) before calling the router. ## Fees ### Fabric Fee Schedule Fabric takes surplus and charges a 0 bps fee by default. Integrators can choose to receive up to 100% of surplus in exchange for a fee on the swap. As integrator surplus share increases, Fabric swap fee increases up to `10 bps`. | Integrator Surplus Share | Fabric Swap Fee | | ------------------------ | --------------- | | `0%` | `0 bps` | | `100%` | `10 bps` | ### Integrator Swap Fees Integrators can set a fee on the swap itself using fee params: * `feeBps` (max `1000` bps) * `feeRecipient` (required when `feeBps` is set) ### Integrator Surplus Fees Integrators can define their share of surplus using surplus fee params: * `surplusFeeBps` (max `10000` bps) * `surplusFeeRecipient` (required when `surplusFeeBps` is set) ### Integrator Referral Fees Integrators can use referral fee params for referral attribution: * `referralFeeBps` (max `1000` bps) * `referralFeeRecipient` (required when `referralFeeBps` is set) ### Fee Token Preference Fabric currently decides which token fees are taken in. Default behavior: * prefer major tokens * if neither side is a major token, prefer the output token for fee collection ## Native Tokens Fabric supports native token routing when either `buyToken` or `sellToken` is: `0x0000000000000000000000000000000000000000` When the input token is native: * approvals are not required * approval instructions are not returned in quote responses Native-input fills use transaction `value` instead of ERC-20 allowance flow. ## Fabric Swap API ### SLAP Fabric optimizes across four dimensions: * **Stability**: high API uptime and low revert rate. * **Latency**: lowest possible quote latency for better UX and faster inclusion. * **Accuracy**: quoted output matches executed output when no slippage occurs. * **Price**: leverage optimal liquidity sources in optimal proportions. These goals are jointly optimized for each quote request. Fabric captures swap intent from `GET /v1/quote` query parameters and returns a wallet-ready fill plan. It does not execute trades. It computes the best executable route and returns the data for the caller to sign and submit onchain. ### How It Works 1. The caller sends a quote request with swap intent (`chainId`, `sellToken`, `buyToken`, amount, slippage, and optional fee params). 2. Fabric finds the top `K` candidate routes using efficient graph search across liquidity sources. 3. Fabric builds a route plan that optimizes output while minimizing price impact. 4. For small trades, this is often a single path. For larger trades, the order may be split across multiple paths to reduce impact. 5. Integrator/referrer/surplus fees are recognized and incorporated in quote computation. 6. Fabric generates execution instructions, including: * optional ERC-20 approval instruction when needed * transaction payload for onchain fill 7. The full quote package is returned to the caller for signing and submission. ### Execution Model * Fabric is a routing and quoting layer, not an execution agent. * The integrator or user submits the transaction onchain. * ERC-20 input tokens may require approval before execution. ### Fees * Integrators can configure fees for themselves and referrers. * Surplus fee sharing is supported in the API. * Fabric fees are dynamic and negotiable. ## Quote API Use the `https://route.withfabric.xyz/v1/quote` endpoint to fetch quotes and executable routing details to perform token swaps. ### Request Parameters All request parameters are passed as query parameters via a GET request. Required parameters must be included for a quote to be generated. | Name | Type | Required | Description | | ---------------------- | ------------ | ----------- | -------------------------------------------------------------------------------------- | | `chainId` | `number` | Yes | The chain ID to execute the trade on | | `sellToken` | `address` | Yes | The token being sold (EVM address) | | `buyToken` | `address` | Yes | The token being bought (EVM address) | | `sellAmount` | `dec_string` | Conditional | The amount of input tokens to sell. Mutually exclusive with `buyAmount` | | `buyAmount` | `dec_string` | Conditional | The amount of output tokens to buy. Mutually exclusive with `sellAmount` | | `slippageBps` | `number` | No | The maximum slippage in basis points the user is willing to accept (default `100` bps) | | `receiver` | `address` | No | The address to receive the output tokens (EVM address, defaults to the caller) | | `feeBps` | `number` | No | The fee in basis points to be taken from the trade (max `1000` bps) | | `feeRecipient` | `address` | Conditional | The recipient of the fee (EVM address). Required if `feeBps` is set | | `surplusFeeBps` | `number` | No | Surplus fee in basis points to be taken from the trade (max `10000` bps) | | `surplusFeeRecipient` | `address` | Conditional | Surplus fee recipient (EVM address). Required if `surplusFeeBps` is set | | `referralFeeBps` | `number` | No | Referral fee in basis points (max `1000` bps) | | `referralFeeRecipient` | `address` | Conditional | Referral fee recipient (EVM address). Required if `referralFeeBps` is set | ### Response Payload The response payload for a successful quote request will contain the following fields as a JSON object: | Field | Type | Description | | ----------------------- | ------------ | ------------------------------------------------------------------------------ | | `blockNumber` | `number` | The block number the quote was generated at | | `amountIn` | `dec_string` | The amount the user sends | | `amountOut` | `dec_string` | The amount the user receives | | `minimumAmountOut` | `dec_string` | The minimum amount the user receives depending on slippage protection settings | | `price` | `number?` | The scaled price ratio between input and output tokens (input/output) | | `description` | `string` | A description of the quote | | `tokens` | `array` | List of tokens involved in the route | | `tokens.address` | `address` | The address of the token contract | | `tokens.symbol` | `string` | The symbol of the token | | `tokens.decimals` | `number` | The number of decimals the token uses | | `tokens.transferFeeBps` | `number` | The bps fee on transfer | | `tokens.priceUsd` | `number?` | The USD price of the token (if available) | | `route` | `object` | The route details used for the quote | | `route.swaps` | `array` | The sequence(s) of swaps in the route | | `route.swaps.key` | `string` | A unique key identifying the pool | | `route.swaps.address` | `address` | The address of the liquidity pool | | `route.swaps.protocol` | `string` | The protocol of the liquidity pool | | `route.swaps.fork` | `string` | The name of the fork | | `route.swaps.tokenIn` | `address` | The input token address for the swap | | `route.swaps.tokenOut` | `address` | The output token address for the swap | | `route.swaps.amountIn` | `dec_string` | The amount of input tokens for the swap | | `route.swaps.amountOut` | `dec_string` | The amount of output tokens for the swap | | `route.amountIn` | `dec_string` | The total input amount for the route | | `route.amountOut` | `dec_string` | The total output amount for the route | | `approval` | `object?` | Optional approval instruction if the input token is an ERC-20 | | `approval.token` | `address` | The address of the token to approve | | `approval.amount` | `dec_string` | The amount to approve (in the smallest unit of the token) | | `approval.spender` | `address` | The address that will be allowed to spend the tokens (router address) | | `transaction` | `object` | The transaction instruction to execute the swap | | `transaction.to` | `address` | The address to send the transaction to | | `transaction.data` | `hex` | The data payload for the transaction | | `transaction.value` | `dec_string` | The value to send with the transaction (for native token swaps) | | `fees` | `array` | Fees associated with the quote | | `fees.token` | `address` | The token in which the fee is charged | | `fees.amount` | `dec_string` | The fee amount | | `fees.recipient` | `address` | The recipient of the fee | | `id` | `string` | ID for logging and emitting onchain | ### Error Responses | Status Code | Error Code | Description | | ----------- | ----------------- | ------------------------------------------------------- | | `400` | `invalid_request` | Chain not supported or invalid parameters provided | | `404` | `not_found` | No route was found | | `422` | `unprocessable` | Invalid parameters provided | | `429` | `rate_limited` | Rate limiter circuit triggered | | `500` | `internal_error` | An internal error occurred while processing the request | | `503` | `unavailable` | The router is currently unavailable | Example error response body: ```json { "statusCode": 404, "traceId": "019cc05a-115e-78d3-8f62-e3b041eaeefe", "message": "No route found", } ``` ### Example Request and Response :::code-group ```bash [Request] curl --get 'https://route.withfabric.xyz/v1/quote' \ --data-urlencode 'chainId=8453' \ --data-urlencode 'buyToken=0x4200000000000000000000000000000000000006' \ --data-urlencode 'sellToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' \ --data-urlencode 'sellAmount=1000000' \ --data-urlencode 'slippageBps=50' ``` ```json [Response] { "blockNumber": 42981049, "amountIn": "1000000", "amountOut": "480007296313153", "minimumAmountOut": "477607259831588", "price": 0.0004800458008748098, "description": "Swap 1000000 x 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 -> 0x4200000000000000000000000000000000000006 via 0xdbc6998296caa1652a810dc8d3baf4a8294330f1", "tokens": [ { "address": "0x4200000000000000000000000000000000000006", "symbol": "WETH", "decimals": 18, "transferFeeBps": 0, "priceUsd": 2083.717751790224 }, { "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "symbol": "USDC", "decimals": 6, "transferFeeBps": 0, "priceUsd": 1.0 } ], "route": { "swaps": [ [ { "key": "0xdbc6998296caa1652a810dc8d3baf4a8294330f1", "address": "0xdbc6998296caa1652a810dc8d3baf4a8294330f1", "protocol": "Uniswap V3", "fork": "AeroDromeCL", "tokenIn": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "tokenOut": "0x4200000000000000000000000000000000000006", "amountIn": "1000000", "amountOut": "480007296313153" } ] ], "amountIn": "1000000", "amountOut": "480007296313153" }, "approval": { "token": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "amount": "1000000", "spender": "0x7c137a37742437d2212b7bd873ed135b5c4c61da" }, "transaction": { "to": "0x7c137a37742437d2212b7bd873ed135b5c4c61da", "data": "0x411bac040000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000019cc0385eba735293bb6bc055018a620000000000000000000000000000000000000000000000000001b4906862e7410000000000000000000000000000000000000000000000000001b2619b107d2400000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000042000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002710000000000000000000000000484ce84a92a17c108c94a91bb222daef93eb8ce700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006442b93ff7000000000000000000000000dbc6998296caa1652a810dc8d3baf4a8294330f10000000000000000000000004200000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "value": "0" }, "fees": [], "id": "019cc038-5eba-7352-93bb-6bc055018a62", "appId": null } ``` ::: ## Simulation Fabric does not perform onchain simulation for quote responses. Integrations should validate execution expectations with onchain simulation before submitting transactions. ### Recommended Validation Workflow Typical production workflows use multiple simulation layers: * dApps simulate before triggering wallet flows * wallets simulate before enabling submit/confirm actions * backend services may run additional pre-submit simulation checks Fabric is designed for advanced integrations (including meta-aggregators), so simulation and verification responsibilities sit closer to the integrator/user edge. ### Other Options If you require validation and do not currently have it, use [`spandex.sh`](https://spandex.sh). spandex.sh is a meta-aggregator that validates quotes from multiple providers and compares aggregators using simulated output as the evaluation point. ## Slippage Protection The Fabric executor contract includes built-in slippage protection to ensure that fills execute within the quoted parameters. If the execution price deviates unfavorably beyond the specified slippage tolerance, the transaction will revert. This is enforced via a minimum output, which is computed from the simulated output amount minus the slippage tolerance. The minimum output is included in the calldata for execution and checked onchain at the time of execution. Example: If a quote returns a simulated output of 100 USDC with a slippage tolerance of 100 bps, the minimum output would be calculated as follows: ``` minimumOutput = simulatedOutput * (1 - slippageTolerance) ``` ### Default Slippage Tolerance By default, Fabric applies a slippage tolerance of 100 bps (1%) to all quotes. This means that if the execution price deviates unfavorably by more than 1% from the simulated price, the transaction will revert. Integrators can specify a custom slippage tolerance when requesting a quote if they wish to allow for more or less slippage.