# Trade BT/CT

```mermaid
sequenceDiagram
  actor User
  participant Router as Router (ActionMiscV3)
  participant FW as FW
  participant CT as CouponToken (CT)
  participant BT as BondToken (BT)

  Note over User,Router: User approves token to Router (ERC20 approve)
  User->>Router: mintBcFromToken(receiver, CT, minBcOut, input)
  Router->>FW: mint FW from token (deposit to CT contract)
  FW-->>CT: FW deposited
  Router->>CT: mintBC(receiver, receiver)
  Note over CT: Mints equal BT and CT tokens from FW
  CT->>BT: mintByCT(receiver, amount) — BT minted
  CT-->>User: CT minted to receiver
  BT-->>User: BT minted to receiver

  alt Redeem pre-expiry (requires both BT + CT)
    User->>Router: redeemBcToToken(receiver, CT, netBcIn, output)
    Note over Router: Router pulls BT and CT from user
    Router->>CT: transfer BT from user to CT contract
    Router->>CT: transfer CT from user to CT contract
    Router->>CT: redeemBC(FW) — burns both BT and CT, returns FW
    CT-->>Router: FW out (single atomic operation, no AMM swap)
    Router->>FW: redeem FW → tokenOut
    FW-->>Router: tokenOut
    Router-->>User: tokenOut
  else Redeem post-expiry (requires only BT)
    User->>Router: redeemBcToToken(receiver, CT, netBcIn, output)
    Note over Router: Router pulls only BT from user (CT not needed)
    Router->>CT: transfer BT from user to CT contract
    Router->>CT: redeemBC(FW) — burns BT only, CT is NOT burned
    CT-->>Router: FW out (at bcIndex rate, not 1:1)
    Router->>FW: redeem FW → tokenOut
    FW-->>Router: tokenOut
    Router-->>User: tokenOut
    Note over CT: Post-expiry yield difference goes to treasury
  end
```

**Key references**: `IPActionMiscV3.mintBcFromToken`, `mintBcFromFw`, `redeemBcToToken`, `redeemBcToFw`.

## Details

* **Goal**: Split FW into BT + CT and later unwind back to base token.
* **Preconditions**:
  * Approvals for `tokenIn` to Router.
  * Set `minBcOut` / `minTokenOut` thresholds.
* **Minting**: `mintBcFromToken` / `mintBcFromFw` — always produces equal BT + CT, both pre- and post-expiry. Post-expiry uses frozen `postExpiry.firstBCIndex` for the conversion rate.
* **Redemption pre-expiry**: Both BT and CT must be provided. `CT.redeemBC()` burns both and returns FW. No AMM swap involved.
* **Redemption post-expiry**: Only BT is required. `CT.redeemBC()` burns BT only; CT is NOT burned. FW returned at the current `bcIndex`, and any post-expiry yield accrual goes to the treasury.

## Views and events

**Views**

* CT (`IBCToken`): `bcIndexStored()`, `bcIndexCurrent()`; `FW()`, `BT()`; `isExpired()`, `balanceOf(user)`.
* BT (`IBondToken`): `balanceOf(user)`, `FW()`, `CT()`, `expiry()`, `isExpired()`.
* FW: `previewDeposit`, `previewRedeem`.

**Events**

* Router: `MintBcFromToken`, `MintBcFromFw`, `RedeemBcToToken`, `RedeemBcToFw`.
* CT: `Mint`, `Burn`, `RedeemInterest`.

## Reward share (CT)

* Suggested formula: `userCt / totalCt` over the epoch (TWAP).
* Functions to call:
  * `IBCToken(CT).balanceOf(user)`, `IERC20(CT).totalSupply()`
  * Exclude expired CT. Post-expiry CT is minted but never burned, inflating `totalSupply()` — consider filtering by excluding known router/contract addresses.

## Reward share (BT)

* Suggested formula: `userBt / totalBt` where:
  * `userBt = IBondToken(BT).balanceOf(user) - getUserPosition(marketParamsBT, user).borrowAssets`
  * `totalBt = IERC20(BT).totalSupply() - IBondToken(BT).balanceOf(market) - IBondToken(BT).balanceOf(lendingMarket)`
* Over the epoch (TWAP).
