harb/onchain/analysis/run-fuzzing.sh

206 lines
7 KiB
Bash
Raw Normal View History

2025-08-09 18:03:31 +02:00
#!/bin/bash
set -euo pipefail
# Usage: ./analysis/run-fuzzing.sh [--help] <optimizer> [runs=N] [buybias=N] [trades=N] [uncapped=bool] [ci=N] [as=N] [aw=N] [dd=N] [debugCSV]
show_help() {
cat <<'EOF'
Usage: ./analysis/run-fuzzing.sh [--help] <optimizer> [runs=N] [buybias=N] [trades=N] [uncapped=bool] [ci=N] [as=N] [aw=N] [dd=N] [debugCSV]
Run StreamlinedFuzzing against a named optimizer. Each run generates a CSV file
with per-trade position snapshots for analysis. Includes random stake/unstake
actions (~10% of trades).
Arguments:
optimizer Required. One of: BullMarketOptimizer, BearMarketOptimizer,
NeutralMarketOptimizer, WhaleOptimizer, ExtremeOptimizer,
MaliciousOptimizer, ConfigurableOptimizer
runs=N Number of fuzzing runs (default: 20)
buybias=N Buy probability 0-100% (default: 50)
trades=N Trades per run (default: 15)
uncapped=true Enable uncapped swaps (default: false)
debugCSV Run 3 short runs and launch the HTML visualizer
ConfigurableOptimizer params (only used when optimizer=ConfigurableOptimizer):
ci=N Capital inefficiency (uint256, default: 0)
as=N Anchor share (uint256, default: 100000000000000000)
aw=N Anchor width in ticks (uint24, default: 20, max 100)
dd=N Discovery depth (uint256, default: 500000000000000000)
Examples:
./analysis/run-fuzzing.sh BullMarketOptimizer
./analysis/run-fuzzing.sh WhaleOptimizer runs=100 trades=50
./analysis/run-fuzzing.sh BearMarketOptimizer buybias=80
./analysis/run-fuzzing.sh BullMarketOptimizer debugCSV
./analysis/run-fuzzing.sh ConfigurableOptimizer ci=0 as=100000000000000000 aw=20 dd=500000000000000000 runs=200 trades=100 uncapped=true
EOF
exit 0
}
2025-08-09 18:03:31 +02:00
2025-08-19 17:35:43 +02:00
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Handle --help
if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then
show_help
fi
2025-08-19 17:35:43 +02:00
# Configuration
2025-08-19 17:35:43 +02:00
OPTIMIZER=${1:-BullMarketOptimizer}
# Check if second parameter is debugCSV
DEBUG_CSV=false
if [[ "${2:-}" == "debugCSV" ]]; then
DEBUG_CSV=true
RUNS_VALUE=3
BUYBIAS_VALUE=50
TRADES_VALUE=5
UNCAPPED_VALUE=false
CI_VALUE=0
AS_VALUE=100000000000000000
AW_VALUE=20
DD_VALUE=500000000000000000
else
# Parse key=value parameters from remaining args
RUNS_VALUE=20
BUYBIAS_VALUE=50
TRADES_VALUE=15
UNCAPPED_VALUE=false
CI_VALUE=0
AS_VALUE=100000000000000000
AW_VALUE=20
DD_VALUE=500000000000000000
shift || true # skip optimizer arg
for arg in "$@"; do
case "$arg" in
runs=*) RUNS_VALUE=${arg#runs=} ;;
buybias=*) BUYBIAS_VALUE=${arg#buybias=} ;;
trades=*) TRADES_VALUE=${arg#trades=} ;;
uncapped=*) UNCAPPED_VALUE=${arg#uncapped=} ;;
ci=*) CI_VALUE=${arg#ci=} ;;
as=*) AS_VALUE=${arg#as=} ;;
aw=*) AW_VALUE=${arg#aw=} ;;
dd=*) DD_VALUE=${arg#dd=} ;;
debugCSV) DEBUG_CSV=true; RUNS_VALUE=3; TRADES_VALUE=5 ;;
*) echo -e "${RED}Unknown parameter: $arg${NC}"; show_help ;;
esac
done
fi
2025-08-19 17:35:43 +02:00
# Ensure we're in the onchain directory
cd "$(dirname "$0")/.."
2025-08-19 17:35:43 +02:00
echo -e "${GREEN}=== Fuzzing Analysis ===${NC}"
echo "Optimizer: $OPTIMIZER"
echo "Total runs: $RUNS_VALUE"
echo "Trades per run: $TRADES_VALUE"
echo "Buy bias: $BUYBIAS_VALUE%"
echo "Uncapped: $UNCAPPED_VALUE"
if [ "$OPTIMIZER" = "ConfigurableOptimizer" ]; then
echo "CI: $CI_VALUE AS: $AS_VALUE AW: $AW_VALUE DD: $DD_VALUE"
fi
2025-08-19 17:35:43 +02:00
echo ""
# Validate optimizer
case $OPTIMIZER in
BullMarketOptimizer|BearMarketOptimizer|NeutralMarketOptimizer|WhaleOptimizer|ExtremeOptimizer|MaliciousOptimizer|ConfigurableOptimizer)
2025-08-19 17:35:43 +02:00
;;
*)
echo -e "${RED}Error: Invalid optimizer class '$OPTIMIZER'${NC}"
echo "Valid: BullMarketOptimizer, BearMarketOptimizer, NeutralMarketOptimizer, WhaleOptimizer, ExtremeOptimizer, MaliciousOptimizer, ConfigurableOptimizer"
2025-08-19 17:35:43 +02:00
exit 1
;;
esac
# Record existing CSV files before running
EXISTING_CSVS=$(ls -1 analysis/fuzz-????-???.csv 2>/dev/null | sort || true)
2025-08-19 17:35:43 +02:00
echo -e "${YELLOW}Starting fuzzing analysis...${NC}"
2025-08-09 18:03:31 +02:00
echo ""
2025-08-09 19:17:46 +02:00
2025-08-19 17:35:43 +02:00
FUZZING_RUNS=$RUNS_VALUE \
OPTIMIZER_CLASS=$OPTIMIZER \
BUY_BIAS=$BUYBIAS_VALUE \
TRADES_PER_RUN=$TRADES_VALUE \
UNCAPPED_SWAPS=$UNCAPPED_VALUE \
CI_VALUE=$CI_VALUE \
AS_VALUE=$AS_VALUE \
AW_VALUE=$AW_VALUE \
DD_VALUE=$DD_VALUE \
2025-08-23 22:32:41 +02:00
forge script analysis/StreamlinedFuzzing.s.sol:StreamlinedFuzzing --skip-simulation --gas-estimate-multiplier 300 -vv 2>&1
2025-08-19 17:35:43 +02:00
echo ""
echo -e "${GREEN}=== ANALYSIS COMPLETE ===${NC}"
# Find newly generated CSV files
NEW_CSVS=$(ls -1 analysis/fuzz-????-???.csv 2>/dev/null | sort || true)
2025-08-23 22:32:41 +02:00
if [ "$EXISTING_CSVS" != "$NEW_CSVS" ]; then
SCENARIO_CODE=$(echo "$NEW_CSVS" | grep -v -F "$EXISTING_CSVS" 2>/dev/null | head -1 | sed 's|.*/fuzz-\(....\).*|\1|' || echo "UNKN")
2025-08-19 17:35:43 +02:00
else
2025-08-23 22:32:41 +02:00
SCENARIO_CODE="UNKN"
2025-08-19 17:35:43 +02:00
fi
CSV_COUNT=$(ls -1 analysis/fuzz-${SCENARIO_CODE}-*.csv 2>/dev/null | wc -l || true)
2025-08-23 22:32:41 +02:00
echo "Generated $CSV_COUNT CSV files with scenario ID: ${SCENARIO_CODE}"
2025-08-19 17:35:43 +02:00
# Check for profitable scenarios
2025-08-23 22:32:41 +02:00
echo ""
echo -e "${YELLOW}=== Checking for Profitable Scenarios ===${NC}"
PROFITABLE_COUNT=0
for csv in analysis/fuzz-${SCENARIO_CODE}-*.csv; do
if [ -f "$csv" ]; then
INIT_ETH=$(grep "^INIT," "$csv" | cut -d',' -f13 || true)
FINAL_ETH=$(grep "^FINAL," "$csv" | cut -d',' -f13 || true)
if [ -n "$INIT_ETH" ] && [ -n "$FINAL_ETH" ]; then
if [ "$FINAL_ETH" -gt "$INIT_ETH" ] 2>/dev/null; then
PROFIT_PCT=$(echo "scale=1; ($FINAL_ETH - $INIT_ETH) * 100 / $INIT_ETH" | bc -l 2>/dev/null || echo "?")
2025-08-23 22:32:41 +02:00
echo -e "${GREEN} $csv: PROFITABLE (+${PROFIT_PCT}%)${NC}"
((PROFITABLE_COUNT++)) || true
2025-08-23 22:32:41 +02:00
fi
fi
fi
done
if [ $PROFITABLE_COUNT -eq 0 ]; then
echo " No profitable scenarios found"
else
echo -e "${GREEN}Found $PROFITABLE_COUNT profitable scenarios${NC}"
2025-08-19 17:35:43 +02:00
fi
echo ""
2025-08-23 22:32:41 +02:00
echo -e "${GREEN}CSV files generated with scenario ID: ${SCENARIO_CODE}${NC}"
# Launch HTML visualizer if debugCSV mode
if [ "$DEBUG_CSV" = true ]; then
echo ""
echo -e "${YELLOW}Launching HTML visualizer...${NC}"
2025-08-23 22:32:41 +02:00
if command -v python3 &> /dev/null; then
echo "Starting local server at http://localhost:8000"
2025-08-23 22:32:41 +02:00
echo "Open http://localhost:8000/run-visualizer.html to view results"
cd analysis
python3 -m http.server 8000 --bind 127.0.0.1 &
SERVER_PID=$!
2025-08-23 22:32:41 +02:00
sleep 1
if command -v open &> /dev/null; then
open "http://localhost:8000/run-visualizer.html"
elif command -v xdg-open &> /dev/null; then
xdg-open "http://localhost:8000/run-visualizer.html"
fi
2025-08-23 22:32:41 +02:00
echo ""
echo "Press Ctrl+C to stop the server"
wait $SERVER_PID
else
echo "Python3 not found. To view results:"
echo " cd analysis && python3 -m http.server 8000"
echo " Then open http://localhost:8000/run-visualizer.html"
2025-08-23 22:32:41 +02:00
fi
fi