# Provide Liquidity

```mermaid
sequenceDiagram
  actor User
  participant Router as Router (ActionAddRemoveLiqV3)
  participant FW as FW
  participant CT as CouponToken (CT)
  participant FM as FiraMarket (BT/FW/LP)

  Note over User,Router: User approves tokens to Router (ERC20 approve)
  User->>Router: addLiquidity*(receiver, FM, ...)
  alt Dual Token+BT (addLiquidityDualTokenAndBt)
    Router->>FW: mint FW from token input (deposit)
    FW-->>FM: FW sent to market
    Router->>FM: transferFrom(user, BT, netBtUsed) — BT from user to market
    Router->>FM: mint(receiver, netFwUsed, netBtUsed)
    FM-->>User: LP tokens to receiver
  else Dual FW+BT (addLiquidityDualFwAndBt)
    Router->>FM: transferFrom(user, FW, netFwUsed)
    Router->>FM: transferFrom(user, BT, netBtUsed)
    Router->>FM: mint(receiver, netFwUsed, netBtUsed)
    FM-->>User: LP tokens to receiver
  else Single Token (addLiquiditySingleToken)
    Router->>FW: mint FW from token input
    FW-->>FM: FW to market
    Router->>FM: swapFwForExactBt(market, btOut, "") — swap portion of FW to BT
    FM-->>FM: BT stays in market
    Router->>FM: mint(receiver, netFwLeft, netBtReceived)
    FM-->>User: LP tokens to receiver
  else Single Token Keep CT (addLiquiditySingleTokenKeepCt)
    Router->>FW: mint FW from token input (to Router)
    FW-->>Router: FW out
    Router->>CT: transfer portion of FW to CT contract
    Router->>FM: transfer remaining FW to market
    Router->>CT: mintBC(market, receiver) — BT to market, CT to receiver
    CT-->>FM: BT
    CT-->>User: CT tokens
    Router->>FM: mint(receiver, netFwAddLiquidity, netBtFromMint)
    FM-->>User: LP tokens to receiver
  end
```

**Key references**: `ActionAddRemoveLiqV3.addLiquidityDualTokenAndBt`, `addLiquidityDualFwAndBt`, `addLiquiditySingleToken`, `addLiquiditySingleBt`, `addLiquiditySingleFw`, `addLiquiditySingleTokenKeepCt`, `addLiquiditySingleFwKeepCt`.

## Details

* **Goal**: Provide liquidity to BT/FW market and receive LP.
* **Preconditions**:
  * Approvals for all inputs (`tokenIn`, `BT`, and/or `FW`).
  * Set `minLpOut` and approximation params when single-sided.
* **Additional entrypoints**:
  * `addLiquiditySingleBt` — BT only, swaps portion to FW.
  * `addLiquiditySingleFw` — FW only, swaps portion to BT.
  * `addLiquiditySingleFwKeepCt` — FW + keep CT variant.

## Views and events

**Views**

* Market: `readTokens()`, `isExpired()`, `readState(router)`, `observe(secondsAgos)`.
* LP: `balanceOf(user)`, `totalSupply()` (derive proportional share of `totalBt/totalFw`).

**Events**

* Router: `AddLiquidityDualTokenAndBt`, `AddLiquidityDualFwAndBt`, `AddLiquiditySingleBt`, `AddLiquiditySingleFw`, `AddLiquiditySingleToken`, `AddLiquiditySingleTokenKeepCt`, `AddLiquiditySingleFwKeepCt`.
* Market: `Mint`, `Swap` (during balancing), `UpdateImpliedRate`.

## Reward share (LP)

* Suggested formula: `lpBalance / totalSupply()` over the epoch (TWAP).
* Functions to call:
  * `IERC20(market).balanceOf(user)`, `IERC20(market).totalSupply()`
  * `FiraMarket.readState(router)` → `totalBt`, `totalFw`, `totalLp` (for underlying attribution)
