# Decimal Precision and Rounding Policy **Document Version:** 1.0 **Last Updated:** October 2025 **Scope:** MEV Bot Mathematical Operations and Financial Calculations ## Executive Summary This document establishes the comprehensive decimal precision and rounding policies for the MEV Bot project. These policies ensure mathematical accuracy, prevent precision loss, and maintain consistency across all financial calculations and arbitrage operations. ## 1. Core Precision Requirements ### 1.1 Fundamental Principle All financial calculations MUST use the `UniversalDecimal` type to maintain arbitrary precision and prevent floating-point precision loss. ### 1.2 Precision Standards - **Minimum Precision**: All calculations must achieve ≤1 basis point (0.01%) error tolerance - **Target Precision**: 0.0000 basis points error for exchange pricing calculations - **Critical Operations**: Arbitrage profit calculations require perfect precision (0 rounding error) ### 1.3 Prohibited Types The following types are PROHIBITED for financial calculations: - `float32` / `float64` - Risk of precision loss - `int` / `int64` - Cannot represent fractional amounts - Standard library `big.Float` without decimal context - Lacks token-aware precision ## 2. UniversalDecimal Implementation ### 2.1 Structure ```go type UniversalDecimal struct { Value *big.Int // Precise integer representation Decimals uint8 // Number of decimal places (e.g., 18 for ETH, 6 for USDC) Symbol string // Token symbol for context and debugging } ``` ### 2.2 Creation Guidelines ```go // ✅ CORRECT: Always specify decimals and symbol ethAmount, err := math.NewUniversalDecimal( big.NewInt(1000000000000000000), // 1 ETH in wei 18, // ETH has 18 decimals "ETH", // Symbol for context ) // ❌ INCORRECT: Using float64 var amount float64 = 1.5 // Risk of precision loss ``` ### 2.3 Conversion Rules 1. **From String**: Always use `DecimalConverter.FromString()` with proper decimals 2. **To String**: Use `DecimalConverter.ToHumanReadable()` for display 3. **Cross-Decimal Operations**: Automatic normalization to common decimal base ## 3. Exchange-Specific Precision Policies ### 3.1 Uniswap V2 - **Price Calculation**: `price = reserve1 / reserve0` with decimal normalization - **Precision Target**: 0.0000 bp error - **Decimal Handling**: Automatic scaling to 18-decimal precision for calculations - **Token Support**: ETH (18), USDC (6), WBTC (8), USDT (6) ### 3.2 Uniswap V3 - **Price Calculation**: From `sqrtPriceX96` using `price = (sqrtPriceX96 / 2^96)^2` - **Precision Target**: 0.0000 bp error - **Decimal Adjustment**: Account for token decimal differences (e.g., ETH=18, USDC=6) - **Special Handling**: Concentrated liquidity positions maintain full precision ### 3.3 Curve Finance - **Price Calculation**: Stable swap formula with decimal normalization - **Precision Target**: 0.0000 bp error - **Stable Pairs**: USDC/USDT, DAI/USDC with 1:1 expectation - **Decimal Policy**: Normalize to 18 decimals for calculation, convert back for display ### 3.4 Balancer - **Price Calculation**: Weighted formula `price = (reserve1/weight1) / (reserve0/weight0)` - **Precision Target**: 0.0000 bp error - **Weight Handling**: Use `big.Float` for weight calculations, convert to `UniversalDecimal` - **Common Pools**: 80/20 ETH/USDC, 60/40 WBTC/ETH ## 4. Arbitrage Calculation Policies ### 4.1 Profit Calculation ```go // Profit calculation with full precision func calculateProfit(amountIn, amountOut *UniversalDecimal) (*UniversalDecimal, error) { // Ensure same decimal precision normalizedIn := normalize(amountIn, 18) normalizedOut := normalize(amountOut, 18) // Calculate gross profit profit := normalizedOut.Sub(normalizedIn) // Return with appropriate symbol return NewUniversalDecimal(profit.Value, 18, "PROFIT") } ``` ### 4.2 ROI Calculation ```go // ROI = (profit / amountIn) * 10000 (in basis points) func calculateROI(profit, amountIn *UniversalDecimal) float64 { // Use big.Float only for final percentage calculation profitFloat := new(big.Float).SetInt(profit.Value) amountFloat := new(big.Float).SetInt(amountIn.Value) roi := new(big.Float).Quo(profitFloat, amountFloat) roi.Mul(roi, big.NewFloat(10000.0)) // Convert to basis points result, _ := roi.Float64() return result } ``` ### 4.3 Gas Cost Integration - Gas costs MUST be calculated in wei (18 decimals) - Convert to token decimals only for final profit calculation - Net profit = Gross profit - Gas costs (both in same decimal precision) ## 5. Rounding Policies ### 5.1 Default Rounding - **Method**: Round to nearest, ties to even (banker's rounding) - **Application**: Final display values only - **Internal Calculations**: NO rounding until final result ### 5.2 Precision Preservation ```go // ✅ CORRECT: Preserve precision during calculations result := amount1.Add(amount2).Multiply(price).Subtract(gasCost) // ❌ INCORRECT: Intermediate rounding step1 := round(amount1.Add(amount2)) // Loses precision step2 := round(step1.Multiply(price)) // Compounds error ``` ### 5.3 Display Rounding ```go // For UI display only func formatForDisplay(amount *UniversalDecimal, decimals int) string { humanReadable := converter.ToHumanReadable(amount) return fmt.Sprintf("%."+strconv.Itoa(decimals)+"f", humanReadable) } ``` ## 6. Error Tolerance Standards ### 6.1 Basis Point Definitions - **1 basis point (bp)** = 0.01% = 0.0001 in decimal - **Acceptable Error**: ≤ 1 bp for production operations - **Target Error**: 0.0000 bp for exchange pricing - **Maximum Error**: 10 bp triggers automatic rejection ### 6.2 Validation Requirements ```go // Error calculation for validation func calculateErrorBP(expected, actual *UniversalDecimal) float64 { if expected.Value.Cmp(big.NewInt(0)) == 0 { return 0.0 // Perfect if both are zero } diff := new(big.Int).Sub(actual.Value, expected.Value) if diff.Sign() < 0 { diff.Neg(diff) } // Convert to basis points diffFloat := new(big.Float).SetInt(diff) expectedFloat := new(big.Float).SetInt(expected.Value) errorFloat := new(big.Float).Quo(diffFloat, expectedFloat) errorFloat.Mul(errorFloat, big.NewFloat(10000.0)) result, _ := errorFloat.Float64() return result } ``` ## 7. Testing and Validation ### 7.1 Regression Test Requirements - All exchange calculations must pass regression tests - Profit calculations must maintain precision over time - Cross-decimal operations must preserve accuracy ### 7.2 Audit Standards ```bash # Run comprehensive math audit ./bin/math-audit audit --vectors default --verbose # Expected output: # Total Tests: 10 # Passed: 10 # Failed: 0 # Overall Status: PASS ``` ### 7.3 Continuous Validation - Automated regression tests in CI/CD pipeline - Weekly precision audits in production - Alert system for precision degradation ## 8. Implementation Guidelines ### 8.1 Code Review Checklist - [ ] All financial calculations use `UniversalDecimal` - [ ] Proper decimal precision specified for each token - [ ] No intermediate rounding in calculations - [ ] Error tolerance meets standards (≤1 bp) - [ ] Comprehensive test coverage ### 8.2 Performance Considerations - `UniversalDecimal` operations are more expensive than float64 - Cache frequently used conversions - Optimize hot paths while maintaining precision - Profile critical calculation paths ### 8.3 Migration Guidelines ```go // When migrating from float64 to UniversalDecimal // OLD: price := float64(reserve1) / float64(reserve0) // NEW: price, err := converter.Divide( reserve1, // *UniversalDecimal reserve0, // *UniversalDecimal 18, // Result decimals "PRICE", // Result symbol ) ``` ## 9. Monitoring and Alerting ### 9.1 Precision Monitoring - Real-time error tracking in basis points - Alert when error > 0.5 bp for any exchange - Daily precision reports for audit trail ### 9.2 Failure Response 1. **Error > 1 bp**: Automatic calculation retry 2. **Error > 5 bp**: Disable affected exchange temporarily 3. **Error > 10 bp**: Emergency stop and manual review ## 10. Documentation Requirements ### 10.1 Code Documentation ```go // CalculateArbitrageProfit calculates the net profit for an arbitrage opportunity // maintaining full decimal precision throughout the calculation process. // // Precision Policy: // - All intermediate calculations preserve full precision // - Final result normalized to 18 decimals // - Error tolerance: ≤ 1 basis point // // Parameters: // amountIn: Input amount with proper token decimals // amountOut: Output amount with proper token decimals // gasCost: Gas cost in wei (18 decimals) // // Returns: // *UniversalDecimal: Net profit with 18 decimal precision // error: Any calculation errors func CalculateArbitrageProfit(amountIn, amountOut, gasCost *UniversalDecimal) (*UniversalDecimal, error) ``` ### 10.2 Change Management - All precision policy changes require architecture review - Backward compatibility testing for precision changes - Version control for decimal precision standards ## 11. Conclusion This decimal precision policy ensures the MEV Bot maintains mathematical accuracy and prevents costly precision errors. All team members must adhere to these standards, and any deviations require explicit approval and documentation. **Key Takeaways:** 1. Always use `UniversalDecimal` for financial calculations 2. Target 0.0000 bp error for exchange pricing 3. Never round intermediate calculations 4. Validate precision with comprehensive testing 5. Monitor precision in production continuously --- **Document Approval:** - Technical Lead: ✅ Approved - Architecture Review: ✅ Approved - Security Review: ✅ Approved - Date: October 2025