#!/bin/bash # SPEC.md Compliance Checker # Verifies code adheres to all SPEC.md requirements set -e PROJECT_ROOT="/docker/mev-beta" cd "$PROJECT_ROOT" || exit 1 # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' info() { echo -e "${BLUE}ℹ${NC} $1"; } success() { echo -e "${GREEN}✓${NC} $1"; } warn() { echo -e "${YELLOW}⚠${NC} $1"; } error() { echo -e "${RED}✗${NC} $1"; } section() { echo -e "\n${CYAN}━━━ $1 ━━━${NC}\n"; } echo "📋 SPEC.md Compliance Check" echo "===========================" echo "" VIOLATIONS=0 # Function to report violation violation() { local severity=$1 local rule=$2 local message=$3 VIOLATIONS=$((VIOLATIONS + 1)) case "$severity" in critical) error "[CRITICAL] SPEC violation: $rule" error " → $message" ;; high) error "[HIGH] SPEC violation: $rule" error " → $message" ;; medium) warn "[MEDIUM] SPEC violation: $rule" warn " → $message" ;; low) warn "[LOW] SPEC violation: $rule" warn " → $message" ;; esac } # MUST DO Requirements section "MUST DO Requirements ✅" # 1. Use Arbitrum sequencer feed as primary data source info "1. Checking sequencer feed usage..." if grep -r "wss://arb1.arbitrum.io/feed" pkg/sequencer/ --include="*.go" | grep -q "."; then success "Sequencer feed URL present" else violation "critical" "Sequencer Feed" \ "Must use wss://arb1.arbitrum.io/feed as primary data source" fi # 2. Use channels for all inter-component communication info "2. Checking channel usage..." CHAN_COUNT=$(grep -r "make(chan\|<-chan\|chan<-" pkg/ --include="*.go" | grep -v "test" | wc -l) if [ "$CHAN_COUNT" -ge 10 ]; then success "Good channel usage ($CHAN_COUNT occurrences)" else violation "high" "Channel-Based Communication" \ "SPEC requires channels for ALL inter-component communication (found only $CHAN_COUNT)" fi # 3. Derive contract ABIs from official sources info "3. Checking ABI sources..." if [ -d "contracts/lib/v2-core" ] && [ -d "contracts/lib/v3-core" ]; then success "Official contract sources present in contracts/lib/" else violation "high" "Official Contract Sources" \ "Must install official DEX contracts via Foundry" fi # 4. Generate Go bindings with abigen info "4. Checking generated bindings..." BINDING_COUNT=$(find bindings/ -name "*.go" -type f 2>/dev/null | wc -l) if [ "$BINDING_COUNT" -ge 2 ]; then success "Generated bindings present ($BINDING_COUNT files)" else violation "high" "Contract Bindings" \ "Must generate Go bindings with abigen (found only $BINDING_COUNT files)" fi # 5. Validate ALL parsed data info "5. Checking data validation..." if grep -r "validate\|Validate\|validation" pkg/sequencer/ pkg/pools/ --include="*.go" | grep -v "test" | grep -q "."; then success "Validation code present" else violation "high" "Data Validation" \ "SPEC requires validation of ALL parsed data" fi # 6. Use thread-safe concurrent data structures info "6. Checking thread safety..." MUTEX_COUNT=$(grep -r "sync.Mutex\|sync.RWMutex" pkg/ --include="*.go" | grep -v "test" | wc -l) if [ "$MUTEX_COUNT" -ge 3 ]; then success "Thread-safe structures present ($MUTEX_COUNT mutexes)" else warn "Limited mutex usage ($MUTEX_COUNT) - verify thread safety" fi # 7. Emit comprehensive metrics info "7. Checking metrics..." if grep -r "prometheus\|metrics" pkg/ --include="*.go" | grep -v "test" | grep -q "."; then success "Metrics code present" else violation "medium" "Observability" \ "SPEC requires comprehensive metrics emission" fi # 8. Run all development in containers info "8. Checking container setup..." if [ -f "scripts/dev.sh" ] && [ -f "docker-compose.yml" ]; then success "Container development environment configured" else violation "high" "Containerized Development" \ "Must run all development in containers" fi # MUST NOT DO Requirements section "MUST NOT DO Requirements ❌" # 1. Use HTTP RPC as primary data source info "1. Checking for HTTP RPC in sequencer..." if grep -r "http://\|https://" pkg/sequencer/ --include="*.go" | grep -v "test" | grep -v "wss://" | grep "rpc" | grep -q "."; then violation "critical" "No HTTP RPC in Sequencer" \ "SPEC forbids HTTP RPC in sequencer (use sequencer feed only)" else success "No HTTP RPC in sequencer" fi # 2. Write manual ABI JSON files info "2. Checking for manual ABI files..." MANUAL_ABIS=$(find bindings/ -name "*.json" -type f 2>/dev/null | grep -v "_abi.json" | wc -l) if [ "$MANUAL_ABIS" -gt 0 ]; then violation "high" "No Manual ABIs" \ "SPEC forbids manual ABI files (use Foundry builds only)" find bindings/ -name "*.json" | grep -v "_abi.json" | head -3 else success "No manual ABI files" fi # 3. Hardcode function selectors info "3. Checking for hardcoded selectors..." if grep -r "selector.*0x[0-9a-f]\{8\}" pkg/ --include="*.go" | grep -v "test" | grep -q "."; then violation "high" "No Hardcoded Selectors" \ "SPEC forbids hardcoded function selectors (use ABI lookups)" grep -r "selector.*0x[0-9a-f]\{8\}" pkg/ --include="*.go" | grep -v "test" | head -3 else success "No hardcoded function selectors" fi # 4. Allow zero addresses/amounts to propagate info "4. Checking for zero address validation..." if ! grep -r "IsZero()\|== common.Address{}" pkg/sequencer/ pkg/pools/ --include="*.go" | grep -q "."; then violation "medium" "Zero Address Check" \ "SPEC requires rejecting zero addresses immediately" fi # 5. Use blocking operations in hot paths info "5. Checking for blocking operations..." if grep -r "time.Sleep\|<-time.After" pkg/sequencer/ pkg/pools/ --include="*.go" | grep -v "test" | grep -q "."; then violation "medium" "No Blocking Operations" \ "SPEC forbids blocking operations in hot paths" grep -r "time.Sleep" pkg/sequencer/ pkg/pools/ --include="*.go" | grep -v "test" | head -3 else success "No blocking operations in hot paths" fi # 6. Modify shared state without locks info "6. Checking for unprotected state..." # This is a heuristic check - find maps/slices without nearby mutex if grep -r "map\[.*\]" pkg/ --include="*.go" | grep -v "test" | head -20 | grep -q "."; then warn "Found map usage - verify all are protected by mutexes" fi # 7. Silent failures info "7. Checking for silent failures..." IGNORED_ERRORS=$(grep -r "_ =" pkg/ --include="*.go" | grep -v "test" | grep "err" | wc -l) if [ "$IGNORED_ERRORS" -gt 5 ]; then violation "medium" "No Silent Failures" \ "Found $IGNORED_ERRORS ignored errors (SPEC requires logging all errors)" else success "Minimal ignored errors ($IGNORED_ERRORS)" fi # Architecture Requirements section "Architecture Requirements 🏗️" # 1. Channel-based concurrency info "Verifying channel-based architecture..." BUFFERED_CHANS=$(grep -r "make(chan.*," pkg/ --include="*.go" | grep -v "test" | wc -l) WORKERS=$(grep -r "go func()" pkg/ --include="*.go" | grep -v "test" | wc -l) info "Buffered channels: $BUFFERED_CHANS" info "Worker goroutines: $WORKERS" if [ "$BUFFERED_CHANS" -lt 3 ]; then violation "high" "Buffered Channels" \ "SPEC requires buffered channels to prevent backpressure" fi # 2. Sequencer isolation info "Checking sequencer isolation..." if [ -d "pkg/sequencer" ]; then success "Sequencer package exists" # Check for sequencer channel output if grep -r "swapCh\|messageCh\|eventCh" pkg/sequencer/ --include="*.go" | grep "chan" | grep -q "."; then success "Sequencer uses channels for output" else violation "high" "Sequencer Isolation" \ "Sequencer must pass data via channels, not direct calls" fi else violation "critical" "Sequencer Package" \ "pkg/sequencer/ directory missing" fi # 3. Pool cache info "Checking pool cache implementation..." if [ -f "pkg/pools/cache.go" ] || [ -f "pkg/pools/pool_cache.go" ]; then success "Pool cache implementation exists" if grep -r "sync.RWMutex" pkg/pools/ --include="*.go" | grep -q "."; then success "Pool cache is thread-safe (uses RWMutex)" else violation "high" "Thread-Safe Cache" \ "Pool cache must use sync.RWMutex" fi else violation "high" "Pool Cache" \ "Pool cache implementation missing (pkg/pools/cache.go)" fi # Foundry Integration section "Foundry Integration 🔨" if [ -f "contracts/foundry.toml" ]; then success "Foundry configuration exists" # Check Solidity version SOLC_VERSION=$(grep "solc_version" contracts/foundry.toml | cut -d'"' -f2) info "Solidity version: $SOLC_VERSION" if [ "$SOLC_VERSION" != "0.8.24" ]; then warn "Solidity version is $SOLC_VERSION (recommended: 0.8.24)" fi else violation "high" "Foundry Setup" \ "contracts/foundry.toml missing" fi # Development Scripts section "Development Scripts 🛠️" REQUIRED_SCRIPTS=("dev.sh" "audit.sh" "test.sh" "check-docs.sh" "check-compliance.sh") for script in "${REQUIRED_SCRIPTS[@]}"; do if [ -f "scripts/$script" ] && [ -x "scripts/$script" ]; then success "scripts/$script exists and is executable" else violation "medium" "Development Scripts" \ "scripts/$script missing or not executable" fi done # Summary section "Compliance Summary" echo "Total violations: $VIOLATIONS" echo "" if [ "$VIOLATIONS" -eq 0 ]; then success "✅ 100% SPEC.md compliant!" exit 0 elif [ "$VIOLATIONS" -le 5 ]; then warn "⚠️ Minor compliance issues ($VIOLATIONS violations)" echo "Review and address violations above." exit 0 else error "❌ Significant compliance issues ($VIOLATIONS violations)" echo "SPEC.md compliance is mandatory. Address all violations." exit 1 fi