- 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>
255 lines
8.3 KiB
Go
255 lines
8.3 KiB
Go
package internal
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// TestVectors contains all test vectors for mathematical validation
|
|
type TestVectors struct {
|
|
Version string `json:"version"`
|
|
Timestamp string `json:"timestamp"`
|
|
Exchanges map[string]*ExchangeVectors `json:"exchanges"`
|
|
}
|
|
|
|
// ExchangeVectors contains test vectors for a specific exchange
|
|
type ExchangeVectors struct {
|
|
ExchangeType string `json:"exchange_type"`
|
|
PricingTests []*PricingTest `json:"pricing_tests"`
|
|
AmountTests []*AmountTest `json:"amount_tests"`
|
|
PriceImpactTests []*PriceImpactTest `json:"price_impact_tests"`
|
|
}
|
|
|
|
// PricingTest represents a test case for price calculation
|
|
type PricingTest struct {
|
|
TestName string `json:"test_name"`
|
|
Description string `json:"description"`
|
|
Reserve0 string `json:"reserve_0"`
|
|
Reserve1 string `json:"reserve_1"`
|
|
Fee string `json:"fee,omitempty"`
|
|
SqrtPriceX96 string `json:"sqrt_price_x96,omitempty"`
|
|
Tick int `json:"tick,omitempty"`
|
|
ExpectedPrice string `json:"expected_price"`
|
|
Tolerance float64 `json:"tolerance"` // Basis points
|
|
}
|
|
|
|
// AmountTest represents a test case for amount in/out calculations
|
|
type AmountTest struct {
|
|
TestName string `json:"test_name"`
|
|
Description string `json:"description"`
|
|
Reserve0 string `json:"reserve_0"`
|
|
Reserve1 string `json:"reserve_1"`
|
|
AmountIn string `json:"amount_in"`
|
|
TokenIn string `json:"token_in"` // "0" or "1"
|
|
Fee string `json:"fee,omitempty"`
|
|
ExpectedAmountOut string `json:"expected_amount_out"`
|
|
Tolerance float64 `json:"tolerance"` // Basis points
|
|
}
|
|
|
|
// PriceImpactTest represents a test case for price impact calculations
|
|
type PriceImpactTest struct {
|
|
TestName string `json:"test_name"`
|
|
Description string `json:"description"`
|
|
Reserve0 string `json:"reserve_0"`
|
|
Reserve1 string `json:"reserve_1"`
|
|
SwapAmount string `json:"swap_amount"`
|
|
TokenIn string `json:"token_in"` // "0" or "1"
|
|
ExpectedPriceImpact string `json:"expected_price_impact"` // Percentage
|
|
Tolerance float64 `json:"tolerance"` // Basis points
|
|
}
|
|
|
|
// LoadTestVectors loads test vectors from file or preset
|
|
func LoadTestVectors(source string) (*TestVectors, error) {
|
|
switch source {
|
|
case "default":
|
|
return loadDefaultVectors()
|
|
case "comprehensive":
|
|
return loadComprehensiveVectors()
|
|
default:
|
|
// Try to load from file
|
|
return loadVectorsFromFile(source)
|
|
}
|
|
}
|
|
|
|
// GetExchangeVectors returns vectors for a specific exchange
|
|
func (tv *TestVectors) GetExchangeVectors(exchangeType string) *ExchangeVectors {
|
|
return tv.Exchanges[exchangeType]
|
|
}
|
|
|
|
// loadDefaultVectors returns a basic set of test vectors
|
|
func loadDefaultVectors() (*TestVectors, error) {
|
|
vectors := &TestVectors{
|
|
Version: "1.0.0",
|
|
Timestamp: "2024-10-08T00:00:00Z",
|
|
Exchanges: make(map[string]*ExchangeVectors),
|
|
}
|
|
|
|
// Uniswap V2 test vectors
|
|
vectors.Exchanges["uniswap_v2"] = &ExchangeVectors{
|
|
ExchangeType: "uniswap_v2",
|
|
PricingTests: []*PricingTest{
|
|
{
|
|
TestName: "ETH_USDC_Basic",
|
|
Description: "Basic ETH/USDC price calculation",
|
|
Reserve0: "1000000000000000000000", // 1000 ETH
|
|
Reserve1: "2000000000000", // 2M USDC
|
|
ExpectedPrice: "2000000000000000000000", // 2000 USDC per ETH
|
|
Tolerance: 1.0, // 1 bp
|
|
},
|
|
{
|
|
TestName: "WBTC_ETH_Basic",
|
|
Description: "Basic WBTC/ETH price calculation",
|
|
Reserve0: "50000000000", // 500 WBTC (8 decimals)
|
|
Reserve1: "10000000000000000000000", // 10000 ETH
|
|
ExpectedPrice: "20000000000000000000", // 20 ETH per WBTC
|
|
Tolerance: 1.0,
|
|
},
|
|
},
|
|
AmountTests: []*AmountTest{
|
|
{
|
|
TestName: "ETH_to_USDC_Swap",
|
|
Description: "1 ETH to USDC swap",
|
|
Reserve0: "1000000000000000000000", // 1000 ETH
|
|
Reserve1: "2000000000000", // 2M USDC
|
|
AmountIn: "1000000000000000000", // 1 ETH
|
|
TokenIn: "0",
|
|
Fee: "3000", // 0.3%
|
|
ExpectedAmountOut: "1994006985000", // ~1994 USDC after fees
|
|
Tolerance: 5.0, // 5 bp
|
|
},
|
|
},
|
|
PriceImpactTests: []*PriceImpactTest{
|
|
{
|
|
TestName: "Large_ETH_Swap_Impact",
|
|
Description: "Price impact of 100 ETH swap",
|
|
Reserve0: "1000000000000000000000", // 1000 ETH
|
|
Reserve1: "2000000000000", // 2M USDC
|
|
SwapAmount: "100000000000000000000", // 100 ETH
|
|
TokenIn: "0",
|
|
ExpectedPriceImpact: "9.09", // ~9.09% price impact
|
|
Tolerance: 10.0, // 10 bp
|
|
},
|
|
},
|
|
}
|
|
|
|
// Uniswap V3 test vectors
|
|
vectors.Exchanges["uniswap_v3"] = &ExchangeVectors{
|
|
ExchangeType: "uniswap_v3",
|
|
PricingTests: []*PricingTest{
|
|
{
|
|
TestName: "ETH_USDC_V3_Basic",
|
|
Description: "Basic ETH/USDC V3 price from sqrtPriceX96",
|
|
SqrtPriceX96: "3543191142285914327220224", // ~2000 USDC per ETH (corrected)
|
|
ExpectedPrice: "2000000000000000000000",
|
|
Tolerance: 1.0,
|
|
},
|
|
},
|
|
AmountTests: []*AmountTest{
|
|
{
|
|
TestName: "V3_Concentrated_Liquidity",
|
|
Description: "Swap within concentrated liquidity range",
|
|
Reserve0: "1000000000000000000000",
|
|
Reserve1: "2000000000000",
|
|
AmountIn: "1000000000000000000",
|
|
TokenIn: "0",
|
|
Fee: "500", // 0.05%
|
|
ExpectedAmountOut: "1999000000000",
|
|
Tolerance: 2.0,
|
|
},
|
|
},
|
|
}
|
|
|
|
// Add more exchanges...
|
|
vectors.Exchanges["curve"] = createCurveVectors()
|
|
vectors.Exchanges["balancer"] = createBalancerVectors()
|
|
|
|
return vectors, nil
|
|
}
|
|
|
|
// loadComprehensiveVectors returns extensive test vectors
|
|
func loadComprehensiveVectors() (*TestVectors, error) {
|
|
// This would load a much more comprehensive set of test vectors
|
|
// For now, return the default set
|
|
return loadDefaultVectors()
|
|
}
|
|
|
|
// loadVectorsFromFile loads test vectors from a JSON file
|
|
func loadVectorsFromFile(filename string) (*TestVectors, error) {
|
|
// Check if it's a relative path within vectors directory
|
|
if !filepath.IsAbs(filename) {
|
|
filename = filepath.Join("vectors", filename+".json")
|
|
}
|
|
|
|
data, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read vectors file %s: %w", filename, err)
|
|
}
|
|
|
|
var vectors TestVectors
|
|
if err := json.Unmarshal(data, &vectors); err != nil {
|
|
return nil, fmt.Errorf("failed to parse vectors file %s: %w", filename, err)
|
|
}
|
|
|
|
return &vectors, nil
|
|
}
|
|
|
|
// createCurveVectors creates test vectors for Curve pools
|
|
func createCurveVectors() *ExchangeVectors {
|
|
return &ExchangeVectors{
|
|
ExchangeType: "curve",
|
|
PricingTests: []*PricingTest{
|
|
{
|
|
TestName: "Stable_USDC_USDT",
|
|
Description: "Stable swap USDC/USDT pricing",
|
|
Reserve0: "1000000000000", // 1M USDC
|
|
Reserve1: "1000000000000", // 1M USDT
|
|
ExpectedPrice: "1000000000000000000", // 1:1 ratio
|
|
Tolerance: 0.5,
|
|
},
|
|
},
|
|
AmountTests: []*AmountTest{
|
|
{
|
|
TestName: "Stable_Swap_Low_Impact",
|
|
Description: "Low price impact stable swap",
|
|
Reserve0: "1000000000000",
|
|
Reserve1: "1000000000000",
|
|
AmountIn: "1000000000", // 1000 USDC
|
|
TokenIn: "0",
|
|
ExpectedAmountOut: "999000000", // ~999 USDT after fees
|
|
Tolerance: 1.0,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// createBalancerVectors creates test vectors for Balancer pools
|
|
func createBalancerVectors() *ExchangeVectors {
|
|
return &ExchangeVectors{
|
|
ExchangeType: "balancer",
|
|
PricingTests: []*PricingTest{
|
|
{
|
|
TestName: "Weighted_80_20_Pool",
|
|
Description: "80/20 weighted pool pricing",
|
|
Reserve0: "800000000000000000000", // 800 ETH (80%)
|
|
Reserve1: "400000000000", // 400k USDC (20%)
|
|
ExpectedPrice: "2000000000000000000000", // 2000 USDC per ETH (corrected)
|
|
Tolerance: 2.0,
|
|
},
|
|
},
|
|
AmountTests: []*AmountTest{
|
|
{
|
|
TestName: "Weighted_Pool_Swap",
|
|
Description: "Swap in weighted pool",
|
|
Reserve0: "800000000000000000000",
|
|
Reserve1: "400000000000",
|
|
AmountIn: "1000000000000000000", // 1 ETH
|
|
TokenIn: "0",
|
|
ExpectedAmountOut: "2475000000000", // ~2475 USDC
|
|
Tolerance: 5.0,
|
|
},
|
|
},
|
|
}
|
|
}
|