Completed clean root directory structure: - Root now contains only: .git, .env, docs/, orig/ - Moved all remaining files and directories to orig/: - Config files (.claude, .dockerignore, .drone.yml, etc.) - All .env variants (except active .env) - Git config (.gitconfig, .github, .gitignore, etc.) - Tool configs (.golangci.yml, .revive.toml, etc.) - Documentation (*.md files, @prompts) - Build files (Dockerfiles, Makefile, go.mod, go.sum) - Docker compose files - All source directories (scripts, tests, tools, etc.) - Runtime directories (logs, monitoring, reports) - Dependency files (node_modules, lib, cache) - Special files (--delete) - Removed empty runtime directories (bin/, data/) V2 structure is now clean: - docs/planning/ - V2 planning documents - orig/ - Complete V1 codebase preserved - .env - Active environment config (not in git) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
203 lines
7.4 KiB
Go
203 lines
7.4 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// GenerateMarkdownReport creates a comprehensive markdown report
|
|
func GenerateMarkdownReport(report *ComprehensiveAuditReport) string {
|
|
var sb strings.Builder
|
|
|
|
// Header
|
|
sb.WriteString("# MEV Bot Math Audit Report\n\n")
|
|
sb.WriteString(fmt.Sprintf("**Generated:** %s\n", report.Timestamp.Format(time.RFC3339)))
|
|
sb.WriteString(fmt.Sprintf("**Test Vectors:** %s\n", report.VectorsFile))
|
|
sb.WriteString(fmt.Sprintf("**Error Tolerance:** %.1f basis points\n\n", report.ToleranceBP))
|
|
|
|
// Executive Summary
|
|
sb.WriteString("## Executive Summary\n\n")
|
|
status := "✅ PASS"
|
|
if !report.OverallPassed {
|
|
status = "❌ FAIL"
|
|
}
|
|
sb.WriteString(fmt.Sprintf("**Overall Status:** %s\n\n", status))
|
|
|
|
sb.WriteString("### Summary Statistics\n\n")
|
|
sb.WriteString("| Metric | Value |\n")
|
|
sb.WriteString("|--------|-------|\n")
|
|
sb.WriteString(fmt.Sprintf("| Total Tests | %d |\n", report.TotalTests))
|
|
sb.WriteString(fmt.Sprintf("| Passed Tests | %d |\n", report.TotalPassed))
|
|
sb.WriteString(fmt.Sprintf("| Failed Tests | %d |\n", report.TotalFailed))
|
|
successRate := 0.0
|
|
if report.TotalTests > 0 {
|
|
successRate = float64(report.TotalPassed) / float64(report.TotalTests) * 100
|
|
}
|
|
sb.WriteString(fmt.Sprintf("| Success Rate | %.2f%% |\n", successRate))
|
|
sb.WriteString(fmt.Sprintf("| Exchanges Tested | %d |\n\n", len(report.ExchangeResults)))
|
|
|
|
// Exchange Results
|
|
sb.WriteString("## Exchange Results\n\n")
|
|
|
|
for exchangeType, result := range report.ExchangeResults {
|
|
sb.WriteString(fmt.Sprintf("### %s\n\n", strings.ToUpper(exchangeType)))
|
|
|
|
exchangeStatus := "✅ PASS"
|
|
if result.FailedTests > 0 {
|
|
exchangeStatus = "❌ FAIL"
|
|
}
|
|
sb.WriteString(fmt.Sprintf("**Status:** %s\n", exchangeStatus))
|
|
sb.WriteString(fmt.Sprintf("**Duration:** %v\n\n", result.Duration.Round(time.Millisecond)))
|
|
|
|
// Exchange statistics
|
|
sb.WriteString("#### Test Statistics\n\n")
|
|
sb.WriteString("| Metric | Value |\n")
|
|
sb.WriteString("|--------|-------|\n")
|
|
sb.WriteString(fmt.Sprintf("| Total Tests | %d |\n", result.TotalTests))
|
|
sb.WriteString(fmt.Sprintf("| Passed | %d |\n", result.PassedTests))
|
|
sb.WriteString(fmt.Sprintf("| Failed | %d |\n", result.FailedTests))
|
|
sb.WriteString(fmt.Sprintf("| Max Error | %.4f bp |\n", result.MaxErrorBP))
|
|
sb.WriteString(fmt.Sprintf("| Avg Error | %.4f bp |\n", result.AvgErrorBP))
|
|
|
|
// Failed cases
|
|
if len(result.FailedCases) > 0 {
|
|
sb.WriteString("\n#### Failed Test Cases\n\n")
|
|
sb.WriteString("| Test Name | Error (bp) | Description |\n")
|
|
sb.WriteString("|-----------|------------|-------------|\n")
|
|
|
|
for _, failure := range result.FailedCases {
|
|
sb.WriteString(fmt.Sprintf("| %s | %.4f | %s |\n",
|
|
failure.TestName, failure.ErrorBP, failure.Description))
|
|
}
|
|
}
|
|
|
|
// Test breakdown by category
|
|
sb.WriteString("\n#### Test Breakdown\n\n")
|
|
pricingTests := 0
|
|
amountTests := 0
|
|
priceImpactTests := 0
|
|
|
|
for _, testResult := range result.TestResults {
|
|
if strings.Contains(strings.ToLower(testResult.Description), "pricing") {
|
|
pricingTests++
|
|
} else if strings.Contains(strings.ToLower(testResult.Description), "amount") {
|
|
amountTests++
|
|
} else if strings.Contains(strings.ToLower(testResult.Description), "price impact") {
|
|
priceImpactTests++
|
|
}
|
|
}
|
|
|
|
sb.WriteString("| Category | Tests |\n")
|
|
sb.WriteString("|----------|-------|\n")
|
|
sb.WriteString(fmt.Sprintf("| Pricing Functions | %d |\n", pricingTests))
|
|
sb.WriteString(fmt.Sprintf("| Amount Calculations | %d |\n", amountTests))
|
|
sb.WriteString(fmt.Sprintf("| Price Impact | %d |\n", priceImpactTests))
|
|
|
|
sb.WriteString("\n")
|
|
}
|
|
|
|
// Detailed Test Results
|
|
if !report.OverallPassed {
|
|
sb.WriteString("## Detailed Failure Analysis\n\n")
|
|
|
|
for exchangeType, result := range report.ExchangeResults {
|
|
if result.FailedTests == 0 {
|
|
continue
|
|
}
|
|
|
|
sb.WriteString(fmt.Sprintf("### %s Failures\n\n", strings.ToUpper(exchangeType)))
|
|
|
|
for _, failure := range result.FailedCases {
|
|
sb.WriteString(fmt.Sprintf("#### %s\n\n", failure.TestName))
|
|
sb.WriteString(fmt.Sprintf("**Error:** %.4f basis points\n", failure.ErrorBP))
|
|
sb.WriteString(fmt.Sprintf("**Description:** %s\n", failure.Description))
|
|
|
|
if failure.Expected != "" && failure.Actual != "" {
|
|
sb.WriteString(fmt.Sprintf("**Expected:** %s\n", failure.Expected))
|
|
sb.WriteString(fmt.Sprintf("**Actual:** %s\n", failure.Actual))
|
|
}
|
|
|
|
sb.WriteString("\n")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Recommendations
|
|
sb.WriteString("## Recommendations\n\n")
|
|
|
|
if report.OverallPassed {
|
|
sb.WriteString("✅ All mathematical validations passed successfully.\n\n")
|
|
sb.WriteString("### Next Steps\n\n")
|
|
sb.WriteString("- Consider running extended test vectors for comprehensive validation\n")
|
|
sb.WriteString("- Implement continuous mathematical validation in CI/CD pipeline\n")
|
|
sb.WriteString("- Monitor for precision degradation with production data\n")
|
|
} else {
|
|
sb.WriteString("❌ Mathematical validation failures detected.\n\n")
|
|
sb.WriteString("### Critical Actions Required\n\n")
|
|
|
|
// Prioritize recommendations based on error severity
|
|
for exchangeType, result := range report.ExchangeResults {
|
|
if result.FailedTests == 0 {
|
|
continue
|
|
}
|
|
|
|
if result.MaxErrorBP > 100 { // > 1%
|
|
sb.WriteString(fmt.Sprintf("- **CRITICAL**: Fix %s calculations (max error: %.2f%%)\n",
|
|
exchangeType, result.MaxErrorBP/100))
|
|
} else if result.MaxErrorBP > 10 { // > 0.1%
|
|
sb.WriteString(fmt.Sprintf("- **HIGH**: Review %s precision (max error: %.2f basis points)\n",
|
|
exchangeType, result.MaxErrorBP))
|
|
} else {
|
|
sb.WriteString(fmt.Sprintf("- **MEDIUM**: Fine-tune %s calculations (max error: %.2f basis points)\n",
|
|
exchangeType, result.MaxErrorBP))
|
|
}
|
|
}
|
|
|
|
sb.WriteString("\n### General Recommendations\n\n")
|
|
sb.WriteString("- Review mathematical formulas against canonical implementations\n")
|
|
sb.WriteString("- Verify decimal precision handling in UniversalDecimal\n")
|
|
sb.WriteString("- Add unit tests for edge cases discovered in this audit\n")
|
|
sb.WriteString("- Consider using higher precision arithmetic for critical calculations\n")
|
|
}
|
|
|
|
// Footer
|
|
sb.WriteString("\n---\n\n")
|
|
sb.WriteString("*This report was generated by the MEV Bot Math Audit Tool*\n")
|
|
sb.WriteString(fmt.Sprintf("*Report generated at: %s*\n", time.Now().Format(time.RFC3339)))
|
|
|
|
return sb.String()
|
|
}
|
|
|
|
// GenerateJSONSummary creates a concise JSON summary for programmatic use
|
|
func GenerateJSONSummary(report *ComprehensiveAuditReport) map[string]interface{} {
|
|
summary := map[string]interface{}{
|
|
"overall_status": report.OverallPassed,
|
|
"total_tests": report.TotalTests,
|
|
"total_passed": report.TotalPassed,
|
|
"total_failed": report.TotalFailed,
|
|
"success_rate": float64(report.TotalPassed) / float64(report.TotalTests) * 100,
|
|
"timestamp": report.Timestamp,
|
|
"vectors_file": report.VectorsFile,
|
|
"tolerance_bp": report.ToleranceBP,
|
|
"exchange_count": len(report.ExchangeResults),
|
|
}
|
|
|
|
// Exchange summaries
|
|
exchanges := make(map[string]interface{})
|
|
for exchangeType, result := range report.ExchangeResults {
|
|
exchanges[exchangeType] = map[string]interface{}{
|
|
"status": result.FailedTests == 0,
|
|
"total_tests": result.TotalTests,
|
|
"passed_tests": result.PassedTests,
|
|
"failed_tests": result.FailedTests,
|
|
"max_error_bp": result.MaxErrorBP,
|
|
"avg_error_bp": result.AvgErrorBP,
|
|
"duration_ms": result.Duration.Milliseconds(),
|
|
}
|
|
}
|
|
summary["exchanges"] = exchanges
|
|
|
|
return summary
|
|
}
|