Expand description
ยง๐งฎ Solana Fixed-Point Math Library
A high-performance, fixed-point arithmetic library optimized for Solana smart contracts. Provides safe, deterministic mathematical operations with 18 decimal places of precision, designed to minimize compute units while maximizing accuracy.
ยงโจ Features
- ๐ฏ High Precision: 18 decimal places (1e18 scale factor) for accurate financial calculations
- โก Optimized for Solana: Minimal compute units, no dynamic loops, small stack footprint
- ๐ก๏ธ Safe by Design: Comprehensive overflow/underflow protection with Anchor error handling
- ๐ข Large Number Support: U256 backing for handling massive values safely
- ๐ Advanced Math: Power functions (including fractional exponents), logarithms, square roots, and exponentials
- ๐ฏ Well-Tested: 60+ comprehensive unit tests with 100% code coverage
- ๐ Fully Documented: Complete API documentation with examples
ยง๐ฆ Installation
Add to your Cargo.toml:
[dependencies]
ra-solana-math = "0.1.0"
anchor-lang = "0.29"Or using cargo:
cargo add ra-solana-mathยง๐ Quick Start
use ra_solana_math::FixedPoint;
// Create fixed-point numbers
let price = FixedPoint::from_int(100); // 100
let fee = FixedPoint::from_percent(5)?; // 5% = 0.05
let multiplier = FixedPoint::from_ratio(3, 2)?; // 3/2 = 1.5
// Perform calculations
let fee_amount = price.mul(&fee)?; // 100 * 0.05 = 5.0
let adjusted = price.mul(&multiplier)?; // 100 * 1.5 = 150.0
// Advanced operations
let sqrt_price = price.sqrt()?; // โ100 = 10.0
let compound = price.pow(&multiplier)?; // 100^1.5 โ 1000.0
let log_price = price.ln()?; // ln(100) โ 4.605ยง๐ Usage Examples
ยงBasic Arithmetic
use ra_solana_math::FixedPoint;
let a = FixedPoint::from_int(10);
let b = FixedPoint::from_int(3);
// Addition and subtraction
let sum = a.add(&b)?; // 13.0
let diff = a.sub(&b)?; // 7.0
// Multiplication and division
let product = a.mul(&b)?; // 30.0
let quotient = a.div(&b)?; // 3.333...
// Convert back to integers
assert_eq!(sum.to_u64()?, 13);ยงFinancial Calculations
// Calculate compound interest: A = P(1 + r)^n
let principal = FixedPoint::from_int(1000); // $1000
let rate = FixedPoint::from_percent(5)?; // 5% annual
let years = FixedPoint::from_int(10); // 10 years
let one = FixedPoint::from_int(1);
let growth_factor = one.add(&rate)?.pow(&years)?; // (1.05)^10
let final_amount = principal.mul(&growth_factor)?; // โ $1628.89
println!("Final amount: ${:.2}", final_amount.to_f64()?);ยงDeFi Price Calculations
// Constant product AMM (x * y = k)
let reserve_x = FixedPoint::from_int(1_000_000); // 1M tokens
let reserve_y = FixedPoint::from_int(500_000); // 500K tokens
let k = reserve_x.mul(&reserve_y)?; // Constant product
// Calculate price impact for a swap
let amount_in = FixedPoint::from_int(10_000); // 10K tokens in
let new_x = reserve_x.add(&amount_in)?;
let new_y = k.div(&new_x)?;
let amount_out = reserve_y.sub(&new_y)?;
println!("Amount out: {}", amount_out.to_u64()?);ยงPercentage and Basis Points
// Working with percentages
let total = FixedPoint::from_int(10_000);
let fee_rate = FixedPoint::from_bps(250)?; // 250 bps = 2.5%
let fee = total.mul(&fee_rate)?; // $250
// Discounts
let discount = FixedPoint::from_percent(15)?; // 15% off
let discount_amount = total.mul(&discount)?; // $1,500
let final_price = total.sub(&discount_amount)?; // $8,500ยงAdvanced Math Operations
// Power functions
let base = FixedPoint::from_int(2);
let exp = FixedPoint::from_int(10);
let result = base.pow(&exp)?; // 2^10 = 1024
// Fractional exponents (roots)
let number = FixedPoint::from_int(27);
let cube_root_exp = FixedPoint::from_ratio(1, 3)?;
let cube_root = number.pow(&cube_root_exp)?; // 27^(1/3) โ 3
// Logarithms
let value = FixedPoint::from_int(100);
let ln_value = value.ln()?; // ln(100) โ 4.605
let log10_value = value.log10()?; // logโโ(100) = 2
let log2_value = value.log2()?; // logโ(100) โ 6.644
// Square root
let number = FixedPoint::from_int(144);
let sqrt = number.sqrt()?; // โ144 = 12ยงUtility Functions
let value = FixedPoint::from_fraction(5, 7, 10)?; // 5.7
// Floor and ceiling
let floor = value.floor(); // 5.0
let ceil = value.ceil()?; // 6.0
// Get fractional part
let frac = value.frac()?; // 0.7
// Min and max
let a = FixedPoint::from_int(5);
let b = FixedPoint::from_int(3);
let min = a.min(&b); // 3.0
let max = a.max(&b); // 5.0ยง๐๏ธ Solana Program Integration
ยงIn Your Anchor Program
use anchor_lang::prelude::*;
use ra_solana_math::FixedPoint;
#[program]
pub mod my_defi_protocol {
use super::*;
pub fn calculate_swap(
ctx: Context<Swap>,
amount_in: u64,
) -> Result<()> {
let pool = &mut ctx.accounts.pool;
// Convert to fixed-point
let amount_in_fp = FixedPoint::from_int(amount_in);
let reserve_in_fp = FixedPoint::from_int(pool.reserve_in);
let reserve_out_fp = FixedPoint::from_int(pool.reserve_out);
// Calculate constant product
let k = reserve_in_fp.mul(&reserve_out_fp)?;
// Calculate output amount with 0.3% fee
let fee = FixedPoint::from_bps(30)?; // 30 bps = 0.3%
let one = FixedPoint::from_int(1);
let amount_in_after_fee = amount_in_fp.mul(&one.sub(&fee)?)?;
let new_reserve_in = reserve_in_fp.add(&amount_in_after_fee)?;
let new_reserve_out = k.div(&new_reserve_in)?;
let amount_out = reserve_out_fp.sub(&new_reserve_out)?;
pool.reserve_in = new_reserve_in.to_u64()?;
pool.reserve_out = new_reserve_out.to_u64()?;
msg!("Swap: {} in, {} out", amount_in, amount_out.to_u64()?);
Ok(())
}
}
#[account]
pub struct Pool {
pub reserve_in: u64,
pub reserve_out: u64,
}
#[derive(Accounts)]
pub struct Swap<'info> {
#[account(mut)]
pub pool: Account<'info, Pool>,
}ยงPrecision
- Scale Factor: 10^18 (18 decimal places)
- Basic Operations: Exact (no rounding errors)
- Square Root: โ 0.01% error (Newtonโs method, 4 iterations)
- Logarithms: โ 0.1% error (Taylor series, 5 terms)
- Exponentials: โ 1% error (range reduction + Taylor series)
- Powers: โ 1-5% error (depends on base and exponent)
ยง๐งช Testing
Run the comprehensive test suite:
# Run all tests
cargo test
# Run tests with output
cargo test -- --nocapture
# Run specific test
cargo test test_compound_interest
# Run with coverage
cargo tarpaulin --out HtmlThe library includes 60+ tests covering:
- โ All constructor and conversion methods
- โ Arithmetic operations and identities
- โ Advanced mathematical functions
- โ Edge cases and error handling
- โ Complex real-world scenarios
- โ Mathematical properties (commutativity, associativity, etc.)
ยง๐ API Reference
ยงConstructors
| Method | Description | Example |
|---|---|---|
from_int(n) | Create from integer | FixedPoint::from_int(100) |
from_u128(n) | Create from u128 | FixedPoint::from_u128(1_000_000) |
from_f64(n) | Create from float (testing) | FixedPoint::from_f64(3.14)? |
from_fraction(w, n, d) | w + n/d | FixedPoint::from_fraction(5, 1, 2)? โ 5.5 |
from_ratio(n, d) | n/d | FixedPoint::from_ratio(3, 4)? โ 0.75 |
from_percent(p) | Percentage | FixedPoint::from_percent(25)? โ 0.25 |
from_bps(b) | Basis points | FixedPoint::from_bps(250)? โ 0.025 |
from_scaled(u256) | From raw scaled value | FixedPoint::from_scaled(value) |
ยงConversions
| Method | Description |
|---|---|
to_u64() | Convert to u64 (truncates decimals) |
to_u128() | Convert to u128 (truncates decimals) |
to_f64() | Convert to f64 (for testing/display) |
ยงArithmetic Operations
| Method | Description | Errors |
|---|---|---|
add(&self, other) | Addition | Overflow |
sub(&self, other) | Subtraction | Underflow |
mul(&self, other) | Multiplication | Overflow |
div(&self, other) | Division | DivisionByZero, Overflow |
ยงAdvanced Math
| Method | Description | Precision |
|---|---|---|
pow(&self, exp) | Power (x^y) | ~1-5% |
sqrt(&self) | Square root | ~0.01% |
ln(&self) | Natural logarithm | ~0.1% |
log10(&self) | Base-10 logarithm | ~0.1% |
log2(&self) | Base-2 logarithm | ~0.1% |
log(&self, base) | Custom base logarithm | ~0.1% |
exp(&self) | Exponential (e^x) | ~1% |
ยงUtility Functions
| Method | Description |
|---|---|
floor() | Round down to integer |
ceil() | Round up to integer |
frac() | Get fractional part |
abs() | Absolute value |
min(&self, other) | Minimum of two values |
max(&self, other) | Maximum of two values |
is_zero() | Check if zero |
ยงโ ๏ธ Important Notes
ยงError Handling
All fallible operations return Result<FixedPoint, MathError>:
pub enum MathError {
Overflow, // Result exceeds U256::MAX
Underflow, // Result is negative (unsigned type)
DivisionByZero, // Division by zero
InvalidInput, // Invalid input (e.g., ln(0))
}Always handle errors in your Solana programs:
let result = a.div(&b).map_err(|_| ErrorCode::MathError)?;ยงPrecision Considerations
- Basic operations (add, sub, mul, div) are exact
- Square root uses Newtonโs method (4 iterations)
- Logarithms and exponentials use Taylor series approximations
- Powers use logarithm-based computation for fractional exponents
For critical financial calculations, test edge cases thoroughly.
ยงCompute Unit Optimization
To minimize CU usage:
- Use integer operations when possible (
from_int,to_u64) - Prefer
sqrt()overpow(x, 0.5)for square roots - Cache repeated calculations
- Use
pow2_fast()for powers of 2
ยง๐ค Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for new functionality
- Ensure all tests pass (
cargo test) - Format code (
cargo fmt) - Lint code (
cargo clippy) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
ยงDevelopment Setup
# Clone the repository
git clone https://github.com/ra-sun-god/ra-solana-math.git
cd ra-solana-math
# Install dependencies
cargo build
# Run tests
cargo test
# Run clippy
cargo clippy -- -D warnings
# Format code
cargo fmtยง๐ Known Limitations
- Unsigned Only: Only handles non-negative numbers (use separate sign tracking if needed)
- Approximation Errors: Complex operations (ln, exp, pow) have ~0.1-5% error
- Range Limits: Maximum value is U256::MAX / 10^18 โ 1.15 ร 10^59
- Compute Units: Advanced operations consume more CU than basic arithmetic
ยง๐ License
This project is licensed under either of:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
ยง๐ Acknowledgments
ยง๐ Support
- Documentation: docs.rs/ra-solana-math
- Issues: GitHub Issues
Made with โค๏ธ for the Solana ecosystem
If this library helps your project, consider giving it a โญ on GitHub!
ยงSolana Fixed-Point Math Library
A high-performance fixed-point arithmetic library optimized for Solana programs. Uses 18 decimal places of precision (1e18 scale factor) with U256 for large number support.
ยงFeatures
- Fixed-point arithmetic: Add, subtract, multiply, divide with overflow protection
- Advanced math: Power (including fractional exponents), logarithms, square root, exponentials
- Optimized for Solana: Minimal compute units, no dynamic loops, small stack footprint
- Large number support: U256 backing for handling massive values safely
- Type-safe: Comprehensive error handling with Anchor integration
ยงExamples
use fixed_point_math::FixedPoint;
// Create a fixed-point number from an integer
let x = FixedPoint::from_int(5);
let y = FixedPoint::from_int(2);
// Perform arithmetic operations
let sum = x.add(&y)?; // 7.0
let product = x.mul(&y)?; // 10.0
let quotient = x.div(&y)?; // 2.5
// Advanced operations
let power = x.pow(&y)?; // 5^2 = 25.0
let sqrt = x.sqrt()?; // โ5 โ 2.236
let log = x.ln()?; // ln(5) โ 1.609Structsยง
- Fixed
Point - A fixed-point number with 18 decimal places of precision.
- U256
- Little-endian large integer type
Enumsยง
- Math
Error - Error types for fixed-point math operations.
Constantsยง
- SCALE
- Fixed-point math library optimized for Solana compute units.