BACK TO BLOG

An Elegant Alternative to Floating Point Operations on Solana

Catalin NeaguCatalin Neagu·July 31, 2025·15 min read
Share X LinkedIn
An Elegant Alternative to Floating Point Operations on Solana

When building DeFi protocols on Solana, developers often face a challenging dilemma: how to implement sophisticated financial calculations without using floating-point operations. While Solana's runtime does not explicitly forbid floating-point instructions, their use is discouraged. This constraint can be particularly challenging when implementing fee models that traditionally rely on exponential calculations.

The Scenario: SolVault's Collateral Risk Pricing

Imagine you're building SolVault, a decentralized lending protocol on Solana. Your protocol needs to calculate liquidation penalties that scale with the risk of different collateral types.

The challenge comes in calculating the liquidation penalty using a risk-based model:

liquidation_penalty = min_penalty × risk_multiplier^(volatility_score)

When risk_multiplier is 1.5 and volatility_score is 3.0, the penalty multiplier would be 1.5^3.0 = 3.375×, making the penalty 3.375 times the minimum.

The Floating-Point Dilemma

The natural implementation would use Rust's powf function. While this works perfectly in tests, it has a subtle issue: the powf function may return slightly different results on different hardware architectures. The Rust documentation notes that the precision can vary by approximately 10^-16, which might seem negligible but can violate Solana's requirement for deterministic execution.

Determinism: The Unbreakable Covenant of Blockchain

A powerful mental model for a blockchain is that of a distributed, deterministic state machine. A transaction is an input that causes the machine to transition to a new state. For the network to maintain consensus, every node must independently compute this state transition and arrive at an identical result. If one node calculates a new account balance of 100 and another calculates 101, the consensus is broken.

Why Floating-Point Numbers Break the Covenant

Floating-point numbers are the antithesis of determinism. The IEEE 754 standard for floating-point arithmetic does not guarantee bit-for-bit identical results across different hardware architectures or even different versions of the same compiler or software library.

A calculation that produces 1.000000001 on one validator's Intel CPU and 1.000000002 on another's AMD CPU represents a consensus failure.

Solana's Official Stance and the Performance Penalty

The Solana documentation warns against the use of floating-point numbers. Even supported float operations come with a significant performance penalty - they must be emulated in software and consume far more compute units than integer-based counterparts.

Operationu64 Instructionsf32 InstructionsCost Multiplier
Multiply817622x
Divide9219~24x

The DeFi Dilemma: Death by a Single Lamport

Here is where non-determinism of powf creates a disaster. Consider a volatile asset with risk_multiplier = 1.8 and volatility_score = 3.2.

When different validators compute 1.8^3.2, some might arrive at 4.7829672...8 while others calculate 4.7829672...9 (note: one ends with 8, the other with 9).

Now imagine a critical liquidation scenario:

  1. A position with 1,000,000 lamports of collateral needs liquidation
  2. One validator calculates penalty = 47,829 lamports
  3. Another validator calculates penalty = 47,830 lamports (1 lamport higher)

When the liquidator attempts to seize exactly 747,829 lamports, the transaction succeeds on some validators but fails on others - breaking consensus.

The Solution: Fixed-Point Arithmetic

The elegant solution is to represent all values as integers with an implied decimal point.

Taylor Series Approximation

For exponential calculations like e^x, we can use the Taylor series expansion:

e^x ≈ 1 + x + x²/2! + x³/3! + x⁴/4! + ...

By computing this with integer arithmetic (multiplying by a large constant like 10^9 to preserve precision), we get deterministic results across all hardware.

Lookup Tables

For fee models with a limited set of risk scores, precomputed lookup tables are both gas-efficient and perfectly deterministic:

rust
const PENALTY_TABLE: &[u64] = &[
    1_000,  // risk score 0: 0.1% penalty
    1_050,  // risk score 1: 0.105% penalty
    1_102,  // risk score 2: 0.1102% penalty
    // ...
];

Fractional Approximation (Continued Fractions)

For values like 1.5^n, you can express 1.5 as the fraction 3/2, then use integer exponentiation:

rust
fn pow_fraction(numerator: u64, denominator: u64, exp: u64) -> u64 {
    let mut result = 1u64;
    for _ in 0..exp {
        result = result.checked_mul(numerator).unwrap() / denominator;
    }
    result
}

Conclusion

Floating-point operations in Solana programs are a hidden danger: they appear to work correctly in development but can cause subtle consensus failures in production. The right approach is integer-based arithmetic using fixed-point representation, lookup tables, or rational approximations.

The compute unit savings are substantial - up to 22x for multiplication - and the determinism guarantee is absolute. When building DeFi protocols on Solana, treat every floating-point operation as a potential bug waiting to happen.

SHIP SAFELY

Ready to secure your protocol?

BOOK A FREE CONSULTATION