usdc-plus-exchange 0.1.8

USDC <-> USDC+ exchange library for the Reflect protocol.
Documentation
# USDC+ Exchange Rate Library

A Rust library for computing **real-time exchange rates** between USDC and USDC+ tokens in the **Reflect Protocol**, incorporating live yield from lending.

## Overview

This crate provides four core functions for calculating USDC ↔ USDC+ conversions:

* **Deposit (USDC → USDC+)**

  * `exchange_rate_usdc_input` – raw-data version
  * `exchange_rate_usdc_accounts``AccountInfo` validated version

* **Redeem (USDC+ → USDC)**

  * `exchange_rate_receipt_input` – raw-data version
  * `exchange_rate_receipt_accounts``AccountInfo` validated version

All functions automatically incorporate pending yield before computing the exchange rate.

---

## Usage

### Deposit Example (USDC → USDC+)

```rust
use usdc_plus_exchange::{
    exchange_rate_usdc_input,
    exchange_rate_usdc_accounts,
};

// With raw account bytes:
let tokens = exchange_rate_usdc_input(
    &controller_data,    // USDC controller account bytes
    &spot_market_data,   // Drift spot market account bytes
    &user_account_data,  // Drift user account bytes
    &usdc_plus_mint_data,  // USDC+ mint account bytes
    1_000_000_000        // 1000 USDC (6 decimals)
)?;

// With Anchor AccountInfo (validates account addresses):
let tokens_validated = exchange_rate_usdc_accounts(
    &ctx.accounts.usdc_controller,
    &ctx.accounts.spot_market,
    &ctx.accounts.drift_user,
    &ctx.accounts.usdc_plus_mint,
    1_000_000_000        // 1000 USDC (6 decimals)
)?;
```

### Redeem Example (USDC+ → USDC)

```rust
use usdc_plus_exchange::{
    exchange_rate_receipt_input,
    exchange_rate_receipt_accounts,
};

// With raw account bytes:
let usdc = exchange_rate_receipt_input(
    &controller_data,    // USDC controller account bytes
    &spot_market_data,   // Drift spot market account bytes
    &user_account_data,  // Drift user account bytes
    &usdc_plus_mint_data,  // USDC+ mint account bytes
    1_000_000_000        // 1000 USDC+ (6 decimals)
)?;

// With AccountInfo (validates account addresses):
let usdc_validated = exchange_rate_receipt_accounts(
    &ctx.accounts.usdc_controller,
    &ctx.accounts.spot_market,
    &ctx.accounts.drift_user,
    &ctx.accounts.usdc_plus_mint,
    1_000_000_000        // 1000 USDC+ (6 decimals)
)?;
```

---

## Function Details

### 1. `exchange_rate_usdc_input`

Calculates how many **USDC+ tokens** you receive for a USDC deposit using raw account data.

```rust
pub fn exchange_rate_usdc_input(
    data_usdc_controller: &[u8],
    data_spot_market_usdc: &[u8],
    data_user_account: &[u8],
    data_usdc_plus_mint: &[u8],
    usdc_amount: u64,
) -> Result<u64>
```

* **Raw account data only** (faster, no address validation)
* Incorporate **pending yield**  computing the deposit exchange rate
* Returns USDC+ amount with 6 decimal places

---

### 2. `exchange_rate_usdc_accounts`

Validates accounts before calling `exchange_rate_usdc_input`.

```rust
pub fn exchange_rate_usdc_accounts(
    usdc_controller_account: &AccountInfo,
    spot_market_usdc_account: &AccountInfo,
    reflect_user_account: &AccountInfo,
    usdc_plus_mint_account: &AccountInfo,
    usdc_amount: u64,
) -> Result<u64>
```

* **Validates** each account matches Reflect Protocol addresses (`require!`)
* Prevents **account substitution attacks**
* Performs the same calculation as `exchange_rate_usdc_input` but with account address validation."

---

### 3. `exchange_rate_receipt_input`

Calculates how much **USDC** you receive for redeeming USDC+ tokens using raw account data.

```rust
pub fn exchange_rate_receipt_input(
    data_usdc_controller: &[u8],
    data_spot_market_usdc: &[u8],
    data_user_account: &[u8],
    data_usdc_plus_mint: &[u8],
    receipt_amount: u64,
) -> Result<u64>
```

* **Raw account data only** (no validation)
* Incorporates **pending yield** before computing redemption rate
* Returns USDC amount with 6 decimal places

---

### 4. `exchange_rate_receipt_accounts`

Validates accounts before calling `exchange_rate_receipt_input`.

```rust
pub fn exchange_rate_receipt_accounts(
    usdc_controller_account: &AccountInfo,
    spot_market_usdc_account: &AccountInfo,
    reflect_user_account: &AccountInfo,
    usdc_plus_mint_account: &AccountInfo,
    receipt_amount: u64,
) -> Result<u64>
```

* **Validates** all account addresses
* Performs the same calculation as `exchange_rate_receipt_input` but with account address validation."

---

## Equations

```
Deposit:  USDC+ = USDC × usdc_plus_supply / deposited_vault_value
Redeem:   USDC  = USDC+ × deposited_vault_value / usdc_plus_supply
```

Where:

* `usdc_plus_supply` = total user shares
* `deposited_vault_value` = vault’s actual USDC value

---

## Security

* Use `*_accounts` variants when running inside an Anchor program for **account validation**.
* Raw-data variants are faster but assume you **trust the account data source**.

---

## Error Handling

All functions return `Result<u64>` and may fail with:

* `InvalidAccount` – if account validation fails
* `MathError` – division by zero or overflow
* `DeserializationError` – invalid or truncated account data
* `InsufficientData` – provided account data is too short