package checks import ( "fmt" "math" "math/big" "math/rand" "github.com/fraktal/mev-beta/pkg/uniswap" "github.com/fraktal/mev-beta/tools/math-audit/internal/audit" ) // Run executes deterministic property/fuzz-style checks reused from the unit test suites. func Run() []audit.TestResult { return []audit.TestResult{ runPriceConversionRoundTrip(), runTickConversionRoundTrip(), runPriceMonotonicity(), runPriceSymmetry(), } } func newResult(name string) audit.TestResult { return audit.TestResult{ Name: name, Type: "property", } } func runPriceConversionRoundTrip() audit.TestResult { res := newResult("price_conversion_round_trip") rng := rand.New(rand.NewSource(1337)) const tolerance = 0.001 // 0.1% failures := 0 for i := 0; i < 256; i++ { exponent := rng.Float64()*12 - 6 price := math.Pow(10, exponent) if price <= 0 { continue } priceBig := new(big.Float).SetFloat64(price) sqrt := uniswap.PriceToSqrtPriceX96(priceBig) converted := uniswap.SqrtPriceX96ToPrice(sqrt) convertedFloat, _ := converted.Float64() if price == 0 { continue } relErr := math.Abs(price-convertedFloat) / price if relErr > tolerance { failures++ if failures >= 3 { break } } } if failures == 0 { res.Passed = true res.Details = "all samples within 0.1% tolerance" } else { res.Passed = false res.Details = fmt.Sprintf("%d samples exceeded tolerance", failures) } return res } func runTickConversionRoundTrip() audit.TestResult { res := newResult("tick_conversion_round_trip") rng := rand.New(rand.NewSource(4242)) failures := 0 for i := 0; i < 256; i++ { tick := rng.Intn(1774544) - 887272 sqrt := uniswap.TickToSqrtPriceX96(tick) convertedTick := uniswap.SqrtPriceX96ToTick(sqrt) if diff := absInt(tick - convertedTick); diff > 1 { failures++ if failures >= 3 { break } } } if failures == 0 { res.Passed = true res.Details = "ticks round-trip within ±1" } else { res.Passed = false res.Details = fmt.Sprintf("%d tick samples exceeded tolerance", failures) } return res } func runPriceMonotonicity() audit.TestResult { res := newResult("price_monotonicity") rng := rand.New(rand.NewSource(9001)) const tickStep = 500 failures := 0 for i := 0; i < 128; i++ { base := rng.Intn(1774544) - 887272 tick1 := base tick2 := base + tickStep if tick2 > 887272 { tick2 = 887272 } sqrt1 := uniswap.TickToSqrtPriceX96(tick1) sqrt2 := uniswap.TickToSqrtPriceX96(tick2) price1 := uniswap.SqrtPriceX96ToPrice(sqrt1) price2 := uniswap.SqrtPriceX96ToPrice(sqrt2) p1, _ := price1.Float64() p2, _ := price2.Float64() if p2 <= p1 { failures++ if failures >= 3 { break } } } if failures == 0 { res.Passed = true res.Details = "higher ticks produced higher prices" } else { res.Passed = false res.Details = fmt.Sprintf("%d monotonicity violations detected", failures) } return res } func runPriceSymmetry() audit.TestResult { res := newResult("price_symmetry") rng := rand.New(rand.NewSource(2025)) const tolerance = 0.001 failures := 0 for i := 0; i < 128; i++ { price := math.Pow(10, rng.Float64()*6-3) // range around 0.001 - 1000 if price <= 0 { continue } inverse := 1.0 / price priceBig := new(big.Float).SetFloat64(price) invBig := new(big.Float).SetFloat64(inverse) sqrtPrice := uniswap.PriceToSqrtPriceX96(priceBig) sqrtInverse := uniswap.PriceToSqrtPriceX96(invBig) convertedPrice := uniswap.SqrtPriceX96ToPrice(sqrtPrice) convertedInverse := uniswap.SqrtPriceX96ToPrice(sqrtInverse) p, _ := convertedPrice.Float64() inv, _ := convertedInverse.Float64() if math.Abs(p*inv-1) > tolerance { failures++ if failures >= 3 { break } } } if failures == 0 { res.Passed = true res.Details = "price * inverse remained within 0.1%" } else { res.Passed = false res.Details = fmt.Sprintf("%d symmetry samples exceeded tolerance", failures) } return res } func absInt(v int) int { if v < 0 { return -v } return v }