Production-grade · Solana sBPF · no_std

Panic-Free
Fixed-Point Arithmetic
for Solana sBPF

fermat-math is a 128-bit fixed-point decimal library that eliminates overflow bugs, enforces explicit rounding, and compiles to bare-metal sBPF with zero dependencies. Built for DeFi protocols where math errors cost millions.

228Test cases
17Bytes on-chain
7Rounding modes
0Dependencies
Installation

Get started in seconds

Published on crates.io. Add to your project with a single command.

Terminal
# Core library (no_std, zero deps)
cargo add fermat-core

# Solana/Anchor integration (optional)
cargo add fermat-solana
Cargo.toml
[dependencies]
fermat-core   = "0.1"
fermat-solana = "0.1"  # optional
Core Features

Every edge case, handled

Built from first principles for consensus-critical DeFi arithmetic. No shortcuts, no hidden panics.

#![forbid(unsafe_code)]

Panic-Free by Design

Every arithmetic operation returns a Result<T, ArithmeticError>. No .unwrap(), no implicit panics. Your validator node never crashes from bad on-chain math.

zero deps

no_std Compatible

fermat-core has zero external dependencies and compiles to bare-metal sBPF. No alloc, no std — just pure integer arithmetic that fits the Solana runtime.

U256 arithmetic

256-Bit Intermediate (U256)

checked_mul_div uses a 256-bit intermediate product — no unsafe, no external bignum crate. Prevents the silent i128 overflow that caused the Balancer/Mango incidents.

IEEE 754-2008

7 Rounding Modes

All IEEE 754-2008 modes: Down, Up, TowardZero, AwayFromZero, HalfUp, HalfDown, HalfEven. Every rounding operation requires an explicit RoundingMode argument — no silent precision loss.

Borsh-safe

17 Bytes On-Chain

Compact Borsh encoding: 16-byte LE i128 mantissa + 1-byte u8 scale. DecimalBorsh validates scale ≤ 28 on deserialization, blocking adversarial account injection attacks.

proptest

228 Tests

Comprehensive unit tests, property-based tests via proptest, and bit-for-bit determinism checks. Includes SPL token conversion tests and adversarial Borsh fuzzing.

Why fermat-math?

The Solana DeFi stack needs better math

Silent overflows and unchecked rounding have caused hundreds of millions in DeFi losses. fermat-math closes these gaps at the library level.

The Problem
fermat-math's Answer
Solana sBPF has no hardware float
Pure integer fixed-point (i128 mantissa)
(a×b)/c silently wraps in i128
checked_mul_div uses 256-bit intermediate (U256)
Silent precision loss from rounding
All rounding requires an explicit RoundingMode
Panics crash validators
#![forbid(unsafe_code)] + every op returns Result
On-chain Borsh scale injection
BorshDeserialize validates scale ≤ MAX_SCALE
Code Example

Write DeFi math that can't panic

The health-factor check is the most security-critical computation in any lending protocol. With fermat-math, every multiplication uses a U256 intermediate and every rounding is explicit.

checked_mul_div prevents i128 overflow on large collateral positions

HalfEven banker's rounding eliminates statistical bias across many operations

Result propagation — the ? operator means no hidden panics

lending_protocol.rs
Rust
// fermat-core: 128-bit fixed-point for Solana sBPF
use fermat_core::{Decimal, RoundingMode};

// Build a health-factor check — the DeFi-critical operation
pub fn is_solvent(
    collateral_usd: Decimal,
    threshold:       Decimal,
    total_debt_usd:  Decimal,
) -> Result<bool, ArithmeticError> {
    // U256 intermediate prevents i128 overflow on large positions
    let adjusted = collateral_usd.checked_mul_div(
        threshold,
        total_debt_usd,
    )?;

    // Explicit rounding mode — no silent precision loss
    let health = adjusted.round(6, RoundingMode::HalfEven)?;

    Ok(health >= Decimal::ONE)
}
No panicsU256 overflow-safeExplicit rounding
sBPF

Cargo.toml

[dependencies]
fermat-core   = "0.1"
fermat-solana = "0.1"  # optional
Crate Structure

Two crates, clear separation

The core library has zero dependencies. Solana integration is opt-in. Use only what you need.

fermat-core

no_std · zero deps
decimalDecimal struct, ZERO, ONE, MAX, MIN constants
arithmeticchecked_add/sub/mul/div, checked_mul_div (U256)
rounding7 IEEE 754-2008 modes
convertfrom_u64/i64/u128, from_str_exact, to_token_amount
compareOrd/PartialOrd with scale normalisation
errorArithmeticError: Overflow, DivisionByZero, ScaleExceeded

fermat-solana

Anchor + SPL
borsh_implDecimalBorsh — 17-byte on-chain encoding, scale validation
tokentoken_amount_to_decimal, decimal_to_token_amount, align_to_mint
accountDECIMAL_SPACE = 17, DecimalBorsh::zero_with_scale for init
Security Model

10 threat vectors, 10 mitigations

Every known arithmetic attack vector in Solana DeFi is documented and mitigated. The audit trail is baked into the source.

All 10 security controls verified — S-01 through S-10
ID
Threat
Mitigation
S-01
(a×b) overflows i128 in mul_div
U256::mul + checked_div in checked_mul_div
S-02
Scale creep in checked_mul
Reject if a.scale + b.scale > MAX_SCALE
S-03
Scale overflow in align
pow10 uses const table, Err(ScaleExceeded) on bounds
S-04
Division by zero
Explicit zero check before every division
S-05
Borsh injection of scale = 255
scale > MAX_SCALE check in BorshDeserialize
S-06
Panic in sBPF program
#![no_std] + #![forbid(unsafe_code)] + no .unwrap() in lib
S-07
Negative scale
u8 type makes negative scale impossible at the type level
S-08
Comparing different-scale values
align_scales normalises before comparison in Ord
S-09
Silent precision loss
All rounding requires explicit RoundingMode argument
S-10
i128::MIN.abs() panic
Uses .unsigned_abs() (returns u128) in checked_mul_div
#![no_std]
Bare-metal sBPF compatible
#![forbid(unsafe_code)]
No unsafe blocks anywhere
Result<T, E>
Every op is fallible
no .unwrap()
Zero panic paths in lib

Stop gambling on unchecked math

The Balancer and Mango exploits could have been prevented with overflow-safe arithmetic. fermat-math makes the correct path the easy path.

Published on crates.ioMIT / Apache-2.0No unsafe code228 testsZero dependenciesCopyright 2026 XXIX Labs