# Position Measurement

{% hint style="info" %}
This page describes how to measure user positions across Fira markets. These formulas are useful for analytics, dashboards, and integrations. **No token incentive program is currently active for Fira V1.** If a reward program is introduced in the future, these measurement methods would serve as the basis for allocation calculations.
{% endhint %}

## Fixed Rate Market

### BFR (Borrow Fixed Rate)

* **What to measure**: Net outstanding principal, expressed in USDC (par: 1 BT ≈ 1 USDC).
* **Qualification rule**: Must match a Fira Lending `Borrow` event AND a FiraMarket `Swap` BT→FW plus `FW.Redeem` to USDC in the borrow flow.
* **User value**: `userBorrowBT = LendingMarket.getUserPosition(marketParamsBT, user).borrowAssets`
* **Total value**: `totalBorrowBT = LendingMarket.market(idBT).totalBorrowAssets` (consider calling `accrueInterest(marketParamsBT)` before reading)
* **Reward share**: `userBorrowBT / totalBorrowBT`
* **Function calls**:
  * Lending: `getUserPosition(marketParamsBT, user)`, `position(idBT, user)`, `market(idBT)`; `idBT = marketParamsBT.id()`
  * Tokens/Market: `FiraMarket.readTokens()` → BT address; Market `isExpired()` for status
* **Events to index**: `EventsLib.Borrow`, `FiraMarket.Swap` (BT→FW), `IFiraWrappedStandardized.Redeem`

### BT (Held BT)

* **What to measure**: Net long BT held outside LP and lending markets; subtract borrowed BT; unit BT.
* **User value**: `userBt = IBondToken(BT).balanceOf(user) - LendingMarket.getUserPosition(marketParamsBT, user).borrowAssets`
* **Total value**: `totalBt = IERC20(BT).totalSupply() - IBondToken(BT).balanceOf(market) - IBondToken(BT).balanceOf(lendingMarket)` (exclude BT in LP and lending)
* **Reward share**: `userBt / totalBt` over the epoch (TWAP)
* **Function calls**:
  * Tokens: `IBondToken(BT).balanceOf(user)`, `IERC20(BT).totalSupply()`, `IBondToken(BT).balanceOf(market)`, `IBondToken(BT).balanceOf(lendingMarket)`
  * Lending: `getUserPosition(marketParamsBT, user).borrowAssets`

### CT (Traders and LPs)

* **What to measure**: Net long CT held outside LP/router addresses; unit CT.
* **User value**: `userCt = IBCToken(CT).balanceOf(user)` (subtract CT known to be held in LP/router escrows)
* **Total value**: `totalCt = IERC20(CT).totalSupply()`
* **Reward share**: `userCt / totalCt`
* **Function calls**:
  * Tokens: `IBCToken(CT).balanceOf(user)`, `IERC20(CT).totalSupply()`; `IBCToken(CT).bcIndexStored()` if including index context; `isExpired()` for status

{% hint style="warning" %}
Exclude expired CT. Post-expiry CT is minted but never burned, inflating `totalSupply()`. Consider filtering by excluding known router/contract addresses.
{% endhint %}

### LP (FiraMarket BT/FW pool)

* **What to measure**: LP tokens in BT/FW FiraMarket pools; unit LP (market LPT).
* **User value**: `lpUser = IERC20(market).balanceOf(user)` limited to `market` addresses
* **Total value**: `lpTotal = IERC20(market).totalSupply()` per market
* **Reward share**: `lpUser / lpTotal` (optionally weight by underlying share using `readState(router)` totals)
* **Function calls**:
  * Market: `FiraMarket.readTokens()`, `readState(router)` → totals; `observe(...)` if you need rate context; `isExpired()`
  * LP token: `IERC20(market).balanceOf(user)`, `IERC20(market).totalSupply()`

## Variable Rate Market

### VRB (Variable Rate Borrow)

* **What to measure**: USDC borrowed; unit USDC.
* **User value**: `userVrb = LendingMarket.getUserPosition(marketParamsUSDC, user).borrowAssets`
* **Total value**: `totalVrb = LendingMarket.market(idUSDC).totalBorrowAssets` (consider calling `accrueInterest(marketParamsUSDC)` before reading)
* **Reward share**: `userVrb / totalVrb`
* **Function calls**:
  * Lending (views): `getUserPosition(marketParamsUSDC, user)`, `position(idUSDC, user)`, `market(idUSDC)`; `idUSDC = marketParamsUSDC.id()`
  * Optional: `accrueInterest(marketParamsUSDC)` to update totals before reading `market(idUSDC)`
  * Oracle: `IOracle.price()` (used for health checks; optional for rewards)

### VRL (Variable Rate Lending via vault)

* **What to measure**: USDC lent into the variable-rate vault; unit USDC.
* **User value**: `userVrl = ISisuVault.convertToAssets(ISisuVault.balanceOf(user))`
* **Total value**: `totalVrl = ISisuVault.totalAssets()` (or Σ users' assets for sub-set accounting)
* **Reward share**: `userVrl / totalVrl`
* **Function calls**: `ISisuVault.balanceOf(user)`, `convertToAssets(shares)`, `totalAssets()`, `totalSupply()`

## Indexing notes

* Lending market functions use `MarketParams` and derive `Id` via `marketParams.id()` off-chain or in-contract; to query data you can use `idToMarketParams(id)`.
* For indexing, include `user` as indexed topic when available (e.g., FW `Deposit/Redeem`, Lending events include `onBehalf`/`borrower`).
* CT interface is `IBCToken` (not `IPYieldToken`). Key view functions: `bcIndexStored()`, `bcIndexCurrent()`, `isExpired()`, `getPostExpiryData()`.


---

# 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://docs.fira.money/developers/events-and-indexing/reward-measurement.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.
