# Limit Order

This document explains how Fluxion limit orders work on Mantle mainnet.

It has two parts:

1. **Overview**: what Fluxion limit orders are, how they work, and why an order may or may not fill.
2. **Engineer appendix**: contracts, endpoints, signing domain, request/response shape.

{% hint style="warning" %}
This guide is **Mantle mainnet only**.
{% endhint %}

***

## Part I. Overview

### 1. What is a Fluxion limit order?

A Fluxion limit order is an off-chain order that is settled on-chain when a taker decides to fill it.

In simple terms:

* the maker defines what asset to sell and what asset to receive
* the maker signs the order off-chain
* the signed order is stored in the Fluxion backend orderbook
* a taker fills the order on Mantle mainnet
* settlement happens through the Fluxion Limit Order Protocol contract

This model keeps order creation lightweight, while final settlement still happens on-chain.

### 2. Core architecture

Fluxion on Mantle mainnet has 3 main layers:

1. **Orderbook backend**
   * builds fee-aware orders
   * stores signed orders
   * serves query APIs
2. **On-chain settlement contracts**
   * Fluxion Limit Order Protocol (LOP)
   * FeeTaker
3. **Maker and taker clients**
   * maker builds, signs, and submits orders
   * taker or solver fills them

### 3. How an order is created

{% stepper %}
{% step %}
Call the backend `build` endpoint
{% endstep %}

{% step %}
Receive a fee-aware order payload
{% endstep %}

{% step %}
Sign the EIP-712 order
{% endstep %}

{% step %}
Compute the order hash
{% endstep %}

{% step %}
Submit the signed order to the backend
{% endstep %}

{% step %}
Wait for a taker or resolver to fill it
{% endstep %}
{% endstepper %}

### 4. Important behavior: funds are not locked

When a maker creates a Fluxion limit order, the maker's tokens are **not locked** inside the backend.

That means:

* the order can be visible in the orderbook
* but the maker can still move tokens away later
* the maker can also reduce allowance later
* the order may then become temporarily or permanently unfillable

Fluxion reduces bad orders by doing two checks:

* **submit-time check**: the backend checks spendable collateral before saving the order
* **runtime check**: query endpoints return `isFillable` and `fillabilityReason`

So an order can be:

* valid in storage
* but not fillable at this moment

### 5. Why an order may not fill

A Fluxion order may stay open for several reasons:

1. **The price is not attractive enough**
   * takers only fill when the price is good for them
2. **The maker balance or allowance is not enough anymore**
   * the backend exposes this as runtime fillability information
3. **The order has expired**
4. **The order was canceled on-chain**
5. **The order is already fully filled**

### 6. How fees work in Fluxion

Fluxion uses a **FeeTaker** flow for fee-aware orders.

That means:

* the order `receiver` is the FeeTaker contract, not the maker wallet
* the taker asset first arrives at FeeTaker
* FeeTaker applies the configured fee logic
* the remaining proceeds are forwarded to the maker-defined receiver logic

Important consequence:

* do **not** manually rewrite `receiver`, `extension`, `salt`, or `makerTraits` after the backend builds the order
* if you change them, the signature and order hash flow will break

### 7. How cancellation works

Fluxion order cancellation is an **on-chain action**.

That means:

* canceling an order requires a transaction on Mantle mainnet
* gas is required
* after the cancellation is seen by the backend sync layer, query APIs show the updated state

The backend then reports the order as invalid/canceled.

### 8. Mantle mainnet reference values

#### Network

* **Chain**: Mantle Mainnet
* **Chain ID**: `5000`
* **RPC**: `https://rpc.mantle.xyz`

#### Core contracts

* **Fluxion Limit Order Protocol (LOP)**: `0x11de6011345586785810e52448a44c6595eedc18`

#### Useful example assets

* **WMNT**: `0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8`
* **USDC**: `0x09Bc4E0D864854c6aFB6eB9A9CDF58AC190D0dF9`
* **TSLAx**: `0x8aD3c73F833d3F9A523aB01476625F269aEB7Cf0`

***

## Part II. Engineer Appendix

### 9. Authentication

All orderbook HTTP endpoints and the WebSocket namespace are API-key protected.

Use either:

* `X-API-Key: <API_KEY>`
* `Authorization: Bearer <API_KEY>`

The health endpoint is separate.

### 10. EIP-712 signing domain

For Mantle mainnet, Fluxion signing uses this EIP-712 domain:

```json
{
  "name": "Fluxion Limit Order Protocol",
  "version": "4",
  "chainId": 5000,
  "verifyingContract": "0x11de6011345586785810e52448a44c6595eedc18"
}
```

If any of these values are wrong, the backend will reject the order with an order-hash mismatch or signature validation error.

### 11. Signed order struct

The signed EIP-712 struct is:

```json
{
  "salt": "uint256",
  "maker": "address",
  "receiver": "address",
  "makerAsset": "address",
  "takerAsset": "address",
  "makingAmount": "uint256",
  "takingAmount": "uint256",
  "makerTraits": "uint256"
}
```

Important detail:

* `extension` is **not** part of the signed struct
* `extension` is submitted separately
* some backend responses include `order.extension` and also top-level `extension`
* for signing, sign only the fields in the struct above

### 12. Build an order

#### Endpoint

`POST /orderbook/v4.1/5000/build`

#### Request shape

```json
{
  "maker": "0xYourMakerAddress",
  "makerAsset": "0xMakerToken",
  "takerAsset": "0xTakerToken",
  "makingAmount": "1000000000000000000",
  "takingAmount": "1000000",
  "expiry": "1767225600"
}
```

Notes:

* `receiver` is optional in the request
* the standard build flow still returns a fee-aware order with `receiver = FeeTaker`
* `makingAmount` and `takingAmount` are raw integer token amounts
* `expiry` is optional and uses Unix seconds

#### Example cURL

```bash
curl -X POST "https://<BACKEND_ENDPOINT>" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <API_KEY>" \
  -d '{
    "maker": "0xYourMakerAddress",
    "makerAsset": "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8",
    "takerAsset": "0x09Bc4E0D864854c6aFB6eB9A9CDF58AC190D0dF9",
    "makingAmount": "2000000000000000",
    "takingAmount": "20000"
  }'
```

#### Response shape

```json
{
  "order": {
    "salt": "0x...",
    "maker": "0xYourMakerAddress",
    "receiver": "0x3FDCB4AF7F9019f6F8b669790BDe93BBF91Bbcc0",
    "makerAsset": "0xMakerToken",
    "takerAsset": "0xTakerToken",
    "makingAmount": "2000000000000000",
    "takingAmount": "20000",
    "makerTraits": "0x...",
    "extension": "0x..."
  },
  "extension": "0x...",
  "feeConfig": {
    "feeTakerAddress": "0x3FDCB4AF7F9019f6F8b669790BDe93BBF91Bbcc0",
    "integratorFeeRecipient": "0x...",
    "protocolFeeRecipient": "0x...",
    "integratorFee": 200,
    "integratorShare": 0,
    "resolverFee": 0,
    "whitelistDiscount": 0,
    "whitelist": ["0x..."]
  }
}
```

Important rules:

1. sign the returned order values exactly
2. submit the returned `extension` exactly
3. do not replace `receiver`
4. do not regenerate `salt`
5. do not assume a fixed whitelist set; read `feeConfig.whitelist` from the actual build response

### 13. Salt and extension binding

The standard Fluxion build flow binds `salt` to the hash of the generated `extension`.

This is important because the backend verifies that relation on submit.

In practice, this means:

* if you edit `extension`, the old `salt` becomes invalid
* if you edit `salt`, the extension check breaks
* the safe flow is: **build -> sign -> submit without mutation**

### 14. Compute the order hash

The order hash is the EIP-712 hash of the signed order struct.

Example with `ethers`:

```ts
import { ethers } from "ethers";

const domain = {
  name: "Fluxion Limit Order Protocol",
  version: "4",
  chainId: 5000,
  verifyingContract: "0x11de6011345586785810e52448a44c6595eedc18"
};

const types = {
  Order: [
    { name: "salt", type: "uint256" },
    { name: "maker", type: "address" },
    { name: "receiver", type: "address" },
    { name: "makerAsset", type: "address" },
    { name: "takerAsset", type: "address" },
    { name: "makingAmount", type: "uint256" },
    { name: "takingAmount", type: "uint256" },
    { name: "makerTraits", type: "uint256" }
  ]
};

const message = {
  salt: BigInt(order.salt),
  maker: order.maker,
  receiver: order.receiver,
  makerAsset: order.makerAsset,
  takerAsset: order.takerAsset,
  makingAmount: BigInt(order.makingAmount),
  takingAmount: BigInt(order.takingAmount),
  makerTraits: BigInt(order.makerTraits)
};

const orderHash = ethers.TypedDataEncoder.hash(domain, types, message);
```

### 15. Sign the order

Example with `ethers`:

```ts
const signature = await wallet.signTypedData(domain, types, message);
```

The backend recomputes the order hash and verifies the signature against the maker address.

### 16. Submit an order

#### Endpoint

`POST /orderbook/v4.1/5000`

#### Request shape

```json
{
  "orderHash": "0x...",
  "signature": "0x...",
  "data": {
    "makerAsset": "0xMakerToken",
    "takerAsset": "0xTakerToken",
    "maker": "0xYourMakerAddress",
    "receiver": "0x3FDCB4AF7F9019f6F8b669790BDe93BBF91Bbcc0",
    "makingAmount": "2000000000000000",
    "takingAmount": "20000",
    "salt": "0x...",
    "extension": "0x...",
    "makerTraits": "0x..."
  }
}
```

#### Success response

```json
{
  "success": true
}
```

#### Submit-time checks performed by the backend

The backend checks at least these things:

* extension matches the expected fee configuration
* `salt` matches the generated extension hash rule
* order hash matches the submitted order data
* signature recovers to the maker address
* amounts are sane
* no duplicate order hash
* no duplicate signature
* maker has not exceeded the active-order cap
* maker has enough spendable collateral for active orders on that asset


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://fluxion-network.gitbook.io/fluxion-network/developer-resources/technical-overview-and-api/limit-order.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
