# Trading Engine

**Trendle uses pooled liquidity rather than an orderbook.**\
This fits attention markets because dozens of indexes can launch quickly and **share depth** from one liquidity pool, instead of bootstrapping makers per market.

> Trendle’s trading engine turns the **Dollar of Attention (DoA)** index into a market you can **long or short**.&#x20;

Conceptually, it works like this:&#x20;

1. An oracle posts the current DoA for each index;
2. traders open leveraged positions against that reference;&#x20;
3. A pooled liquidity vault underwrites payouts;&#x20;
4. Funding re-centers price to DoA while liquidation removes under-margined positions to protect LPs.

   &#x20;

This is implemented by three contracts that work together: a <mark style="color:yellow;">**PriceFeed**</mark> *(index input)*, a <mark style="color:yellow;">**Pool**</mark> *(LP reserves)*, and <mark style="color:yellow;">**Trading**</mark> *(orders, P\&L, fees, funding, liquidation)*. The outcome is scalable, orderbook-free markets where many attention indexes can share the same liquidity.

### <mark style="color:yellow;">The three on-chain pieces:</mark>

* **PriceFeed** — a oracle intake

Authorized oracle accounts push minute-level index prices per `indexId`. Consumers read via `getPrice(indexId, max)`. If prices go stale, the feed widens spread / errors.

`max` is a boolean guard used when quotes are near-stale or stale-guarded\
• `getPrice(indexId, true)` → returns the upper-bound *(max)* price for conservative checks (e.g., opening/closing longs, or LP-side risk).\
• `getPrice(indexId, false)` → returns the lower-bound *(min)* price for conservative checks in the opposite direction (e.g., shorts).\
\
If the quote is fresh, both calls effectively return the same current DoA. When the feed applies a protective spread due to staleness, the `max` flag decides which side of the spread you get.

<table><thead><tr><th width="183.48828125">Call</th><th width="276.9453125">Use case (typical)</th><th>Returned price when spread applies</th></tr></thead><tbody><tr><td><code>getPrice(id, true)</code></td><td>Long-side checks, LP risk checks</td><td><strong>Upper bound</strong> of DoA band</td></tr><tr><td><code>getPrice(id, false)</code></td><td>Short-side checks</td><td><strong>Lower bound</strong> of DoA band</td></tr></tbody></table>

* **Pool** - LP reserves & collateral routing

LPs deposit whitelisted tokens. The contract tracks `totalReserve`, `lockedReserve`, and enforces minimum free reserve, lockups, and per-index allowlists. Trading locks / unlocks reserve via `adjustReserve`.

* **Trading** - orders, positions, fees, funding & liquidation

Holds market parameters (fees, leverage caps, funding baseline), takes orders, opens/closes positions, calculates P\&L, and settles payouts via the Pool / treasury.\
\&#xNAN;*Settlement waterfall:*

1. Payouts are first covered by the trader’s collateral locked in the Trading contract.
2. If P\&L exceeds collateral, the shortfall is paid from the Pool’s reserves (per the market’s locked exposure).
3. The treasury never pays, it only receives fees (trading, imbalance, liquidation where applicable)

### <mark style="color:yellow;">Life of a trade:</mark>

1. **Place order**

* Trader sends collateral, leverage, side *(long / short)*, and `indexId`. Contract records a `Trade` (status **ORDER** for limit, otherwise executes immediately).

2. **Execution & price check**

* Market: reads current index price from **PriceFeed** and opens a **POSITION** right away.
* Limit: orders are later executed in batches via `processTrades` if the feed shows your limit is hit.

3. **Locking liquidity & fees**

* On open, the engine locks pool reserve against the position and charges:
  * Trading fee + market-imbalance fee *(dynamic extra if one side is overcrowded)*.
  * Fees route to `treasury`.

4. **While open: funding keeps sides in check**
5. **Close or liquidate**

* **Close:** trader calls `closePosition`; P\&L uses current index price ± funding.
* **Liquidate:** if collateral falls below `liquidationThreshold`, anyone can trigger liquidation; a **liquidation fee** applies and the Pool releases/recovers funds.

6. **Payout caps & settlement**

* &#x20;For every position base cap is computed  `cap_base = maxPayoutThreshold × collateral_after_fees`.
* For shorts, there is an additional natural ceiling because the index cannot go below zero. The most a short can earn is the P\&L they’d realize at **price = 0**, i.e. roughly `cap_short_floor = entryIndex × positionSize` (± funding/fees).
* The contract therefore uses:\
  \&#xNAN;**`maxPayout = min(cap_base, cap_short_floor)`** for shorts, and **`maxPayout = cap_base`** for longs.
