> ## Documentation Index
> Fetch the complete documentation index at: https://docs.windrose.market/llms.txt
> Use this file to discover all available pages before exploring further.

# Units and conventions

> Decimals, fixed-point formats and the quote-unit convention every contract, indexer column and price on Windrose follows.

Every amount on Windrose is one of a handful of formats. Get these right once and every contract call, event and indexer column reads the same way. The worked examples at the end walk one INR launch through all of them.

## The conventions

| Value                    | Format                                                                                               | Where                                                                                                                                                       |
| ------------------------ | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Launch token amounts     | 18 decimals. Total supply `1e27` = 1,000,000,000 tokens                                              | `LaunchToken`, curve `tokensSold`, `holder.balance`                                                                                                         |
| Raw quote amounts        | The quote asset's own decimals: 6 for USDC/USDG/EURC, 18 for every synthetic (`wINR`, `acJPY`, ...)  | Every `quoteInRaw` / `quoteOutRaw` argument and return value, `ERC20.approve` amounts, `creatorFeesAccrued`, `protocolFeesAccrued`                          |
| Quote units              | The raw amount normalised to 18 decimals: `raw * quoteScale`, `quoteScale = 10^(18 - quoteDecimals)` | Curve `realQuote`, `virtualQuote`, `graduationQuote`; every indexer amount column (`quoteAmount`, `fee`, `volumeQuote`, `candle.volume`, `feeClaim.amount`) |
| Spot price               | Quote units per whole token, 1e18 fixed point                                                        | `BondingCurve.spotPrice()`, indexer `priceQuote`, `lastPriceQuote`, candle OHLC                                                                             |
| Oracle rate              | Units of the currency per 1 USD, 1e18 fixed point. USD is fixed at `1e18`                            | `IFxOracle.rate` / `peekRate`, `KeeperFxOracle.post`, `FxVault` events, indexer `rate`                                                                      |
| USD price                | `spotPrice * 1e18 / rate(code)`, 1e18 fixed point                                                    | Indexer `priceUsd`, `lastPriceUsd`                                                                                                                          |
| Dollar amounts in vaults | 6 decimals (raw dollar)                                                                              | `FxVault.assets`, `liabilityAt`, `equityAt`, `status`, `mint(usdcIn)`, `redeem` return value, `deposit`, `withdraw`, `donate`, indexer `usdcAmount`         |
| Synthetic amounts        | 18 decimals                                                                                          | `SynthToken`, `mint` return value, `redeem(synthIn)`                                                                                                        |
| Vault shares             | 18 decimals; the first deposit receives `usdcIn * 1e12` shares (1 dollar = `1e18` shares)            | `FxVault` (the vault is the share ERC-20), `deposit` / `withdraw`                                                                                           |
| Basis points             | `10000` = 100%                                                                                       | Every `*Bps` parameter, `progressBps()`, `crBps`                                                                                                            |
| Currency codes           | ASCII right-padded to `bytes32` (`"INR"` = `0x494e52…00`)                                            | Registry, oracle, factory `CreateParams.code`, curve `code()`                                                                                               |
| Time                     | Unix seconds; deadlines are timestamps, never block numbers                                          | `Router` deadlines, oracle `publishTime`                                                                                                                    |

<Note>
  The contracts call the settlement dollar `usdc` on every chain. On Robinhood Chain it is USDG, on Arc it is USDC; both have 6 decimals. On Arc the native gas balance is an 18-decimal view of the same balance; contracts only ever handle the 6-decimal ERC-20.
</Note>

## Why quote units exist

Quote assets have different decimals (6 for the dollar and EURC, 18 for synthetics). The curve does its maths in one unit so the constant-product formula and the graduation target read the same for every currency: it multiplies raw amounts by `quoteScale` on the way in and divides on the way out. `graduationQuote` is rounded up to a multiple of `quoteScale` so it is always representable as a raw amount. The indexer stores the same 18-decimal unit in every quote column, so a USDG launch and a wINR launch can be compared without knowing the decimals of either.

## Converting between formats

```ts theme={"system"}
const quoteScale = 10n ** BigInt(18 - quoteDecimals);

// raw -> quote units, quote units -> raw
const quote18 = raw * quoteScale;
const raw = quote18 / quoteScale;

// spot price (1e18) -> whole quote per whole token, as a JS number for display only
const price = Number(spotPrice) / 1e18;

// USD price of a launch token (1e18 fixed point)
const priceUsd = (spotPrice * 10n ** 18n) / rate;        // rate = XXX per USD, 1e18

// display in another currency (off-chain FX rate for currencies that are not on chain)
const priceInDisplayCurrency = priceUsd * displayRate / 10n ** 18n;   // displayRate = DISPLAY per USD, 1e18

// dollars <-> synthetic at the oracle rate (before fees)
const synthOut = (usdcIn * rate) / 10n ** 6n;             // 6-dec dollars -> 18-dec synthetic
const usdcOut = (synthIn * 10n ** 6n) / rate;             // 18-dec synthetic -> 6-dec dollars
```

The vault rounds `liabilityAt` up and mints `(usdcIn - fee) * rate / 1e6` rounded down, so a mint followed by a redeem never returns more than it took even with zero fees.

## Worked example: an INR launch at 83.5 INR per USD

The oracle reports `rate("INR") = 83.5e18`. The factory's deployed configuration is 375,000,000 virtual tokens, 750,000,000 curve tokens, 250,000,000 pool tokens and a 6,000 USD virtual quote.

| Step                       | Formula                                                                                  | Value                                                                    |
| -------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| Virtual quote              | `virtualQuoteUsd * rate / 1e18` = `6000e18 * 83.5e18 / 1e18`                             | `501000e18` quote units = 501,000 wINR                                   |
| Graduation target          | `virtualQuote * curveSupply / virtualToken` = `501000e18 * 750e24 / 375e24`              | `1002000e18` = 1,002,000 wINR (12,000 USD)                               |
| Opening spot price         | `y / x` = `501000e18 * 1e18 / (375e24 + 750e24)`                                         | `4.4533e14` = 0.000445 wINR per token                                    |
| Opening USD price          | `spotPrice * 1e18 / rate` = `4.4533e14 * 1e18 / 83.5e18`                                 | `5.333e12` = 0.00000533 USD                                              |
| Tokens sold at graduation  | `curveSupply` (the target is defined as the quote needed to sell the whole curve supply) | 750,000,000                                                              |
| Final spot price           | `(virtualQuote + graduationQuote) / virtualToken` = `1503000e18 * 1e18 / 375e24`         | `4.008e15` = 0.004008 wINR (9 times the opening price)                   |
| Graduation fee             | `2% * 1,002,000`                                                                         | 20,040 wINR to the protocol                                              |
| Liquidity seeded           | `981,960 wINR` plus `981960e18 * x / y` tokens = `981960 * 375e6 / 1503000`              | 245,000,000 tokens; the 5,000,000 left of the pool allocation are burned |
| Market value at graduation | `1e9 tokens * 0.004008 wINR`                                                             | 4,008,000 wINR (48,000 USD)                                              |

The same launch quoted in USDG has `quoteDecimals = 6` and `quoteScale = 1e12`: `virtualQuote = 6000e18`, `graduationQuote = 12000e18`, and a trader who sends `usdcIn = 100e6` raw dollars is charged in raw units while the curve accounts `100e18` quote units.

## Indexer specifics

* Every `bigint` column is returned as a decimal string in GraphQL; hex values (addresses, codes, pool ids) are lowercase.
* `trade.priceQuote` is the execution price of that trade (`quoteAmount / tokenAmount`); `launch.lastPriceQuote` and candles use the spot price after the trade (the curve formula, or the pool price derived from `sqrtPriceX96` after graduation).
* `priceUsd` is `null` until a rate for the launch's currency has been indexed. USD launches use `rate = 1e18`.
* `crBps` is `2^256 - 1` when a vault has no liability, exactly as `FxVault.status()` returns it.

See [GraphQL conventions](/api/graphql) for pagination, filters and table names.
