# 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