# FiraMarket

{% hint style="info" %}
**Source:** `src/fira_bonding/core/Market/v3/FiraMarket.sol`
{% endhint %}

## Contract summary

`FiraMarket` extends `FiraERC20` — the LP token *is* the market contract itself. It holds BT and FW reserves and tracks internal balances separately from actual token balances to prevent interference from direct transfers.

Key state is packed into `MarketStorage` for gas: `totalBt`, `totalFw` (int128), `lastLnImpliedRate` (uint96), and oracle observation indices (uint16 each).

## Functionality

### Mint (add liquidity)

`mint(receiver, netFwDesired, netBtDesired)` loads state into memory, calls `MarketMathCore.addLiquidity`, and writes back. On first deposit it locks `MINIMUM_LIQUIDITY` (1000 wei of LP) to `address(1)` to prevent the first-depositor rounding attack. Subsequent deposits mint LP proportional to the limiting token.

Tokens must be transferred to the market before calling `mint` — the contract does not pull.

### Burn (remove liquidity)

`burn(receiverFw, receiverBt, netLpToBurn)` burns LP from `address(this)`, computes proportional FW and BT outputs, and transfers them out. LP must be sent to the market before calling. Works both pre- and post-expiry.

### Swaps

* **`swapExactBtForFw`** — Flash-callback pattern: sends FW out first, then verifies BT repayment via callback.
* **`swapFwForExactBt`** — Sends BT out first, calls back, checks FW repayment.

Both swap functions send the reserve fee portion to the treasury and are gated by `notExpired`.

### Oracle

Every call to `_writeState` writes a new observation to the `OracleLib` ring buffer. `observe(secondsAgos)` returns cumulative `ln(impliedRate)` values for TWAP calculations. `increaseObservationsCardinalityNext` lets anyone pre-allocate observation slots.

### Skim

`skim()` sends any excess BT or FW (above internal totals) to the treasury. This prevents direct transfers from affecting pool pricing.

## Invariants

* Internal `totalBt` and `totalFw` are never affected by direct transfers
* Exchange rate is always >= 1.0 (BT trades at a discount to FW)
* `address(0)` and `address(this)` never have reward or balance accounting
* Swaps and mints revert after expiry; burns work at any time
