Files
mev-beta/pkg/math/precision_test.go
Krypto Kajun 850223a953 fix(multicall): resolve critical multicall parsing corruption issues
- Added comprehensive bounds checking to prevent buffer overruns in multicall parsing
- Implemented graduated validation system (Strict/Moderate/Permissive) to reduce false positives
- Added LRU caching system for address validation with 10-minute TTL
- Enhanced ABI decoder with missing Universal Router and Arbitrum-specific DEX signatures
- Fixed duplicate function declarations and import conflicts across multiple files
- Added error recovery mechanisms with multiple fallback strategies
- Updated tests to handle new validation behavior for suspicious addresses
- Fixed parser test expectations for improved validation system
- Applied gofmt formatting fixes to ensure code style compliance
- Fixed mutex copying issues in monitoring package by introducing MetricsSnapshot
- Resolved critical security vulnerabilities in heuristic address extraction
- Progress: Updated TODO audit from 10% to 35% complete

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 00:12:55 -05:00

294 lines
7.8 KiB
Go

package math
import (
"math/big"
"math/rand"
"testing"
"time"
)
// TestDecimalPrecisionPreservation tests that decimal operations preserve precision
func TestDecimalPrecisionPreservation(t *testing.T) {
dc := NewDecimalConverter()
testCases := []struct {
name string
value string
decimals uint8
symbol string
}{
{"ETH precision", "1000000000000000000", 18, "ETH"}, // 1 ETH
{"USDC precision", "1000000", 6, "USDC"}, // 1 USDC
{"WBTC precision", "100000000", 8, "WBTC"}, // 1 WBTC
{"Small amount", "1", 18, "ETH"}, // 1 wei
{"Large amount", "1000000000000000000000", 18, "ETH"}, // 1000 ETH
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Create decimal from string
decimal, err := dc.FromString(tc.value, tc.decimals, tc.symbol)
if err != nil {
t.Fatalf("Failed to create decimal: %v", err)
}
// Convert to string and back
humanReadable := dc.ToHumanReadable(decimal)
backToDecimal, err := dc.FromString(humanReadable, tc.decimals, tc.symbol)
if err != nil {
t.Fatalf("Failed to convert back from string: %v", err)
}
// Compare values
if decimal.Value.Cmp(backToDecimal.Value) != 0 {
t.Errorf("Precision lost in round-trip conversion")
t.Errorf("Original: %s", decimal.Value.String())
t.Errorf("Round-trip: %s", backToDecimal.Value.String())
t.Errorf("Human readable: %s", humanReadable)
}
})
}
}
// TestArithmeticOperations tests basic arithmetic with different decimal precisions
func TestArithmeticOperations(t *testing.T) {
dc := NewDecimalConverter()
// Create test values with different precisions
eth1, _ := dc.FromString("1000000000000000000", 18, "ETH") // 1 ETH
eth2, _ := dc.FromString("2000000000000000000", 18, "ETH") // 2 ETH
tests := []struct {
name string
op string
a, b *UniversalDecimal
expected string
}{
{
name: "ETH addition",
op: "add",
a: eth1,
b: eth2,
expected: "3000000000000000000", // 3 ETH
},
{
name: "ETH subtraction",
op: "sub",
a: eth2,
b: eth1,
expected: "1000000000000000000", // 1 ETH
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var result *UniversalDecimal
var err error
switch test.op {
case "add":
result, err = dc.Add(test.a, test.b)
case "sub":
result, err = dc.Subtract(test.a, test.b)
default:
t.Fatalf("Unknown operation: %s", test.op)
}
if err != nil {
t.Fatalf("Operation failed: %v", err)
}
if result.Value.String() != test.expected {
t.Errorf("Expected %s, got %s", test.expected, result.Value.String())
}
})
}
}
// TestPercentageCalculations tests percentage calculations for precision
func TestPercentageCalculations(t *testing.T) {
dc := NewDecimalConverter()
testCases := []struct {
name string
numerator string
denominator string
decimals uint8
expectedRange [2]float64 // [min, max] acceptable range
}{
{
name: "1% calculation",
numerator: "10000000000000000", // 0.01 ETH
denominator: "1000000000000000000", // 1 ETH
decimals: 18,
expectedRange: [2]float64{0.99, 1.01}, // 1% ± 0.01%
},
{
name: "50% calculation",
numerator: "500000000000000000", // 0.5 ETH
denominator: "1000000000000000000", // 1 ETH
decimals: 18,
expectedRange: [2]float64{49.9, 50.1}, // 50% ± 0.1%
},
{
name: "Small percentage",
numerator: "1000000000000000", // 0.001 ETH
denominator: "1000000000000000000", // 1 ETH
decimals: 18,
expectedRange: [2]float64{0.099, 0.101}, // 0.1% ± 0.001%
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
num, err := dc.FromString(tc.numerator, tc.decimals, "ETH")
if err != nil {
t.Fatalf("Failed to create numerator: %v", err)
}
denom, err := dc.FromString(tc.denominator, tc.decimals, "ETH")
if err != nil {
t.Fatalf("Failed to create denominator: %v", err)
}
percentage, err := dc.CalculatePercentage(num, denom)
if err != nil {
t.Fatalf("Failed to calculate percentage: %v", err)
}
percentageFloat, _ := percentage.Value.Float64()
// Convert from raw value to actual percentage (divide by 10^decimals)
// Since percentage has 4 decimals, divide by 10000 to get actual percentage value
actualPercentage := percentageFloat / 10000.0
t.Logf("Calculated percentage: %.6f%%", actualPercentage)
if actualPercentage < tc.expectedRange[0] || actualPercentage > tc.expectedRange[1] {
t.Errorf("Percentage %.6f%% outside expected range [%.3f%%, %.3f%%]",
actualPercentage, tc.expectedRange[0], tc.expectedRange[1])
}
})
}
}
// PropertyTest tests mathematical properties like commutativity, associativity
func TestMathematicalProperties(t *testing.T) {
dc := NewDecimalConverter()
rand.Seed(time.Now().UnixNano())
// Generate random test values
for i := 0; i < 100; i++ {
// Generate random big integers
val1 := big.NewInt(rand.Int63n(1000000000000000000)) // Up to 1 ETH
val2 := big.NewInt(rand.Int63n(1000000000000000000))
val3 := big.NewInt(rand.Int63n(1000000000000000000))
a, _ := NewUniversalDecimal(val1, 18, "ETH")
b, _ := NewUniversalDecimal(val2, 18, "ETH")
c, _ := NewUniversalDecimal(val3, 18, "ETH")
// Test commutativity: a + b = b + a
ab, err1 := dc.Add(a, b)
ba, err2 := dc.Add(b, a)
if err1 != nil || err2 != nil {
t.Fatalf("Addition failed: %v, %v", err1, err2)
}
if ab.Value.Cmp(ba.Value) != 0 {
t.Errorf("Addition not commutative: %s + %s = %s, %s + %s = %s",
a.Value.String(), b.Value.String(), ab.Value.String(),
b.Value.String(), a.Value.String(), ba.Value.String())
}
// Test associativity: (a + b) + c = a + (b + c)
ab_c, err1 := dc.Add(ab, c)
bc, err2 := dc.Add(b, c)
a_bc, err3 := dc.Add(a, bc)
if err1 != nil || err2 != nil || err3 != nil {
continue // Skip this iteration if any operation fails
}
if ab_c.Value.Cmp(a_bc.Value) != 0 {
t.Errorf("Addition not associative")
}
}
}
// BenchmarkDecimalOperations benchmarks decimal operations
func BenchmarkDecimalOperations(b *testing.B) {
dc := NewDecimalConverter()
val1, _ := dc.FromString("1000000000000000000", 18, "ETH")
val2, _ := dc.FromString("2000000000000000000", 18, "ETH")
b.Run("Addition", func(b *testing.B) {
for i := 0; i < b.N; i++ {
dc.Add(val1, val2)
}
})
b.Run("Subtraction", func(b *testing.B) {
for i := 0; i < b.N; i++ {
dc.Subtract(val2, val1)
}
})
b.Run("Percentage", func(b *testing.B) {
for i := 0; i < b.N; i++ {
dc.CalculatePercentage(val1, val2)
}
})
}
// FuzzDecimalOperations fuzzes decimal operations for edge cases
func FuzzDecimalOperations(f *testing.F) {
// Seed with known values
f.Add(int64(1000000000000000000), int64(2000000000000000000)) // 1 ETH, 2 ETH
f.Add(int64(1), int64(1000000000000000000)) // 1 wei, 1 ETH
f.Add(int64(0), int64(1000000000000000000)) // 0, 1 ETH
f.Fuzz(func(t *testing.T, val1, val2 int64) {
// Ensure positive values
if val1 < 0 {
val1 = -val1
}
if val2 <= 0 {
return // Skip zero/negative denominators
}
dc := NewDecimalConverter()
a, err := NewUniversalDecimal(big.NewInt(val1), 18, "ETH")
if err != nil {
return
}
b, err := NewUniversalDecimal(big.NewInt(val2), 18, "ETH")
if err != nil {
return
}
// Test addition doesn't panic
_, err = dc.Add(a, b)
if err != nil {
t.Errorf("Addition failed: %v", err)
}
// Test subtraction doesn't panic (if a >= b)
if val1 >= val2 {
_, err = dc.Subtract(a, b)
if err != nil {
t.Errorf("Subtraction failed: %v", err)
}
}
// Test percentage calculation doesn't panic
_, err = dc.CalculatePercentage(a, b)
if err != nil {
t.Errorf("Percentage calculation failed: %v", err)
}
})
}