> For the complete documentation index, see [llms.txt](https://docs.jaawle.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.jaawle.xyz/protocol/issuer-orders.md).

# Issuer orders

A stock pool holds real tokenized shares, and it holds them as an allocation toward a target, not as a per-trade hedge. Buying a share means an order with the issuer that settles off-chain over minutes to hours, only while the stock market is open. So the pool never trades on a trade: it rebalances a few times a day, in bounded orders, and the perp's risk is managed separately by the open-interest caps, borrow and funding.

The issuer is a partner, not something the contracts know by name. The pool sees an `issuerAdapter` address (an operator wallet at the issuer that holds escrow while an order is in flight) and a `SETTLER` role that books results. Today the issuer is Dinari and the shares are dShares; dividends and USD+ (the issuer's settlement stable) come from the same partner.

## When the keeper places an order

The keeper watches each stock pool's split against its target: 60 % of NAV in shares (`targetInventoryBps`), with a USDC reserve floor of 15 % and a ceiling of 70 % of NAV in shares plus pending orders (`maxDeployRatioBps`). It rebalances on a schedule and after the events that move the split: an executed deposit or redemption, a settled fill, a split, a queued USDC redemption that the idle cash cannot pay, and index routing into or out of the pool. A buy raises the share weight toward the target; a sell raises cash, either because the pool is over-weight or because redemptions are waiting.

## The flow

```mermaid
sequenceDiagram
  participant TW as Keeper
  participant POOL as MarketPool
  participant AD as Issuer adapter wallet
  participant ISS as The issuer
  participant ST as Settler
  TW->>POOL: placeIssuerOrder(isBuy, amount), keeper, regular session
  Note over POOL: envelope checks, id = keccak(pool, ++orderNonce)
  POOL->>AD: escrow USDC (buy) or shares (sell)
  Note over POOL: escrow stays in NAV as pendingUsdc / pendingStock
  TW->>ISS: place the order off-chain, client order id = id
  ISS-->>AD: fill: shares (buy) or cash (sell), minus the issuer's fee
  AD->>POOL: deliver the shares (buy)
  ST->>POOL: settleIssuerOrder(id, filled, spentOrReceived), settler
  Note over POOL: fill-price guard, book the fill, pull the refund
```

### 1. Escrow: `placeIssuerOrder(isBuy, amount)`

Callable by the `KEEPER` only, in the Regular session only, on share-backed pools only. The order id is derived on-chain, `keccak256(pool, ++orderNonce)`, and is what the keeper sends to the issuer as the client order id: a retried job resends the same id and the issuer rejects the duplicate, so a chain event delivered twice can never produce two buys.

For a **buy** (`amount` is USDC):

* `amount x 1e12 <= maxOrderUsd` ($200 000), else `OrderTooLarge`;
* `amount <= idleUsdc()` (USDC above the reserve floor), else `ReserveBreached`;
* `(shares + pending shares) x bid + pending USDC + amount <= maxDeployRatioBps x NAV`, else `DeployRatioExceeded`;
* `usdcBalance -= amount`, `pendingUsdc += amount`, and the USDC is transferred to the adapter wallet.

For a **sell** (`amount` is shares):

* `amount <= stockBalance - reservedStock`: shares reserved for open longs never leave, else `InsufficientInventory`;
* `amount x ask <= maxOrderUsd`, else `OrderTooLarge`;
* `stockBalance -= amount`, `pendingStock += amount`, and the shares are transferred to the adapter wallet.

Either way the escrow stays in NAV at cost (`pendingUsdc`, `pendingStock`), so LP tokens are priced correctly while the order is in flight. `OrderPlaced` and `OrderEscrowed` are emitted with the id and amounts.

### 2. Off-chain: the keeper places the order

The keeper places a market order with the issuer for the pool's enterprise account, quoting the on-chain id, then polls the order and its fulfilments, which are the only source of settled amounts. The issuer charges its own fee on the fill; it is part of the pool's cost of carrying inventory.

### 3. Settle: `settleIssuerOrder(id, filled, spentOrReceived)`

Callable by the `SETTLER` (the adapter wallet's role). It books the finished order and pulls back whatever was not used.

For a **buy**: `spentOrReceived` is the USDC actually spent, at most the escrow. The pool checks that the shares have already been delivered (`stock.balanceOf(pool) >= stockBalance + escrowStock + filled`, else `BalanceMismatch`), runs the fill-price guard, adds `filled` to `stockBalance`, clears `pendingUsdc`, and pulls the unspent USDC (`usdcIn - spent`) from the settler back into `usdcBalance`.

For a **sell**: `filled` is the shares sold, at most the escrow, and `spentOrReceived` the USDC received. The pool runs the guard, pulls the USDC from the settler, clears `pendingStock`, and pulls back the unsold shares.

**Fill-price deviation guard.** The average fill price `spentOrReceived / filled` must be within `maxFillDeviationBps` (300, 3 %) of the oracle mid at settlement time, else the call reverts `FillDeviation(fillPrice, mid, maxBps)`. A bad fill cannot be booked into NAV; the keeper has to resolve it with the issuer. `OrderSettled(id, filled, spentOrReceived, refund)` closes the order.

Partial fills are normal: the unspent USDC or the unsold shares simply come back as the refund.

### 4. Stale orders: `refundStaleOrder(id)`

If an order has not been settled `maxPendingAge` (3 days) after it was placed, the settler returns the full escrow with `refundStaleOrder`, which pulls the USDC or shares back from the adapter wallet and clears the pending amounts. A lost order can therefore never freeze the pool's accounting. `OrderStaleRefunded(id)`.

## Splits

After a stock split the pool's share balance no longer matches its accounting. The keeper calls `syncInventory()`, allowed only when no order is in flight: it reads the real balance (minus liquidity-request escrow), scales `reservedStock` by the same ratio so open longs keep their claim on inventory, and sets `stockBalance` to the actual balance. `InventorySynced(delta)`.

Open positions are not rescaled by the contracts today: a position's `sizeTokens` and entry price are unchanged by a split, so the keeper must handle positions around a split off-chain (the planned change is to scale sizes and divide entry prices from a signed corporate action). Splits are rare on the listed names; treat this as a known gap.

## Interaction with the rest of the pool

* `sweepDividends` is refused while a buy is pending, so a refund is never read as a dividend.
* `syncInventory` is refused while any order is pending.
* The index vault's parent hooks and the pool's own requests are independent of orders; a queued USDC redemption that exceeds idle cash waits for a sell to settle.
* USD+ received from the issuer (dividends or sell proceeds) is swapped for USDC one-for-one by the settler through `sweepUsdPlus`.

## Custody

The pool contract holds the shares; the issuer's transfer restrictions are blacklist-only, so a contract is an ordinary holder. The adapter wallet is a transient escrow, not custody: it holds an order's USDC or shares only between `placeIssuerOrder` and `settleIssuerOrder`. NAV is computable from chain state alone, so no inventory attestation from the issuer is needed.

## Staging

Until the issuer partnership is live, staging runs the same keeper against a stand-in: the order is placed and escrowed exactly as in production, and the stand-in fills it at the oracle price during NYSE hours by minting mock shares into the pool. Deposits, NAV, inventory and the rebalance cadence behave as in production; only the counterparty is simulated. The shares, their backing and the issuer relationship are described in [Tokenized shares and custody](/assets-and-prices/tokenized-shares-and-custody.md).

## Parameters

| parameter           | value            | field                        |
| ------------------- | ---------------- | ---------------------------- |
| target stock weight | 60 % of NAV      | `Config.targetInventoryBps`  |
| USDC reserve floor  | 15 % of NAV      | `Config.reserveBps`          |
| max deployed        | 70 % of NAV      | `Config.maxDeployRatioBps`   |
| max order           | $200 000         | `Config.maxOrderUsd`         |
| fill deviation      | 3 % from the mid | `Config.maxFillDeviationBps` |
| stale after         | 3 days           | `Config.maxPendingAge`       |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.jaawle.xyz/protocol/issuer-orders.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
