An Elegant Alternative to Floating Point Operations on Solana
Catalin Neagu·July 31, 2025·15 min read
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.
| Operation | u64 Instructions | f32 Instructions | Cost Multiplier |
|---|---|---|---|
| Multiply | 8 | 176 | 22x |
| Divide | 9 | 219 | ~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:
- A position with 1,000,000 lamports of collateral needs liquidation
- One validator calculates penalty = 47,829 lamports
- 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:
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:
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.