harb/onchain/analysis/run-recorded-fuzzing.sh
johba 27a8998a82 feat: Add buy bias parameter to fuzzing analysis
- Added BUY_BIAS environment variable (0-100%) to control trading direction
- Implemented biased trading logic in all strategies (Random, Whale, Volatile, etc.)
- Created run-improved-fuzzing.sh script with buy bias support
- Fixed memory issues in CSV generation by simplifying string concatenation
- Fixed console.log parameter issues in staking functions
- Updated run-recorded-fuzzing.sh to accept buybias parameter
- Testing shows up to 99% of authorized stake reached with 100% buy bias

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-19 14:02:11 +02:00

256 lines
No EOL
8.6 KiB
Bash
Executable file

#!/bin/bash
# Usage: ./run-recorded-fuzzing.sh [optimizer] [runs=N] [trades=N] [staking=on|off] [buybias=N]
# Examples:
# ./run-recorded-fuzzing.sh BullMarketOptimizer runs=50
# ./run-recorded-fuzzing.sh WhaleOptimizer runs=20 trades=30 staking=off
# ./run-recorded-fuzzing.sh ExtremeOptimizer runs=100 trades=default staking=on buybias=80
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
BOLD='\033[1m'
# Configuration
OPTIMIZER=${1:-BullMarketOptimizer}
RUNS=${2:-runs=20}
TRADES=${3:-trades=default}
STAKING=${4:-staking=on}
BUYBIAS=${5:-buybias=50}
# Parse runs parameter
if [[ $RUNS == runs=* ]]; then
RUNS_VALUE=${RUNS#runs=}
else
RUNS_VALUE=$RUNS
RUNS="runs=$RUNS"
fi
# Parse trades parameter (for future use)
TRADES_VALUE=""
if [[ $TRADES == trades=* ]]; then
TRADES_VALUE=${TRADES#trades=}
fi
# Parse staking parameter
STAKING_ENABLED="true"
if [[ $STAKING == staking=* ]]; then
STAKING_VALUE=${STAKING#staking=}
if [[ $STAKING_VALUE == "off" ]] || [[ $STAKING_VALUE == "false" ]] || [[ $STAKING_VALUE == "0" ]]; then
STAKING_ENABLED="false"
fi
elif [[ $STAKING == "nostaking" ]]; then
STAKING_ENABLED="false"
fi
# Parse buy bias parameter
BUYBIAS_VALUE="50"
if [[ $BUYBIAS == buybias=* ]]; then
BUYBIAS_VALUE=${BUYBIAS#buybias=}
fi
# Generate unique run ID (6 chars from timestamp + random)
RUN_ID=$(date +%y%m%d)-$(head /dev/urandom | tr -dc A-Z0-9 | head -c 4)
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTPUT_DIR="fuzzing_results_recorded_${OPTIMIZER}_${TIMESTAMP}"
echo -e "${GREEN}=== Recorded Fuzzing Campaign ===${NC}"
echo -e "Run ID: ${BOLD}${RUN_ID}${NC}"
echo "Optimizer: $OPTIMIZER"
echo "Total runs: $RUNS_VALUE"
echo "Staking: $([ "$STAKING_ENABLED" = "true" ] && echo "enabled" || echo "disabled")"
echo "Buy bias: $BUYBIAS_VALUE%"
echo "Output directory: $OUTPUT_DIR"
echo ""
# Validate optimizer
case $OPTIMIZER in
BullMarketOptimizer|BearMarketOptimizer|NeutralMarketOptimizer|WhaleOptimizer|ExtremeOptimizer|MaliciousOptimizer)
echo "Optimizer validation passed"
;;
*)
echo -e "${RED}Error: Invalid optimizer class${NC}"
echo "Valid options: BullMarketOptimizer, BearMarketOptimizer, NeutralMarketOptimizer, WhaleOptimizer, ExtremeOptimizer, MaliciousOptimizer"
exit 1
;;
esac
# Create output directory
mkdir -p $OUTPUT_DIR
# Run the recorded fuzzing
echo -e "${YELLOW}Starting recorded fuzzing analysis...${NC}"
FUZZING_RUNS=$RUNS_VALUE \
OPTIMIZER_CLASS=$OPTIMIZER \
ENABLE_STAKING=$STAKING_ENABLED \
BUY_BIAS=$BUYBIAS_VALUE \
RUN_ID=$RUN_ID \
forge script analysis/RecordedFuzzingAnalysis.s.sol:RecordedFuzzingAnalysis --gas-limit 1000000000 -vv 2>&1 | tee $OUTPUT_DIR/fuzzing.log
# Check for generated scenario files (check for summaries, they're always generated)
SCENARIO_COUNT=$(ls -1 scenario_summary_seed*.txt 2>/dev/null | wc -l)
if [ $SCENARIO_COUNT -gt 0 ]; then
echo ""
echo -e "${GREEN}=== INVARIANT VIOLATIONS FOUND! ===${NC}"
echo -e "${BOLD}Found $SCENARIO_COUNT profitable scenarios${NC}"
echo ""
# Move recording files to output directory with run ID
for file in recorded_scenario_seed*.json; do
if [ -f "$file" ]; then
SEED=$(echo $file | sed 's/recorded_scenario_seed\(.*\)\.json/\1/')
NEW_NAME="scenario_${RUN_ID}_seed${SEED}.json"
mv "$file" "$OUTPUT_DIR/$NEW_NAME"
echo -e " Scenario JSON: ${BLUE}$OUTPUT_DIR/$NEW_NAME${NC}"
fi
done
for file in replay_script_seed*.sol; do
if [ -f "$file" ]; then
SEED=$(echo $file | sed 's/replay_script_seed\(.*\)\.sol/\1/')
NEW_NAME="replay_${RUN_ID}_seed${SEED}.sol"
mv "$file" "$OUTPUT_DIR/$NEW_NAME"
echo -e " Replay script: ${BLUE}$OUTPUT_DIR/$NEW_NAME${NC}"
fi
done
for file in scenario_summary_seed*.txt; do
if [ -f "$file" ]; then
SEED=$(echo $file | sed 's/scenario_summary_seed\(.*\)\.txt/\1/')
NEW_NAME="summary_${RUN_ID}_seed${SEED}.txt"
mv "$file" "$OUTPUT_DIR/$NEW_NAME"
echo -e " Summary: ${BLUE}$OUTPUT_DIR/$NEW_NAME${NC}"
# Display summary preview
echo ""
echo -e "${YELLOW}--- Preview of $NEW_NAME ---${NC}"
head -n 15 "$OUTPUT_DIR/$NEW_NAME"
echo "..."
fi
done
# Move position CSVs if they exist
if ls improved_positions_*.csv 1> /dev/null 2>&1; then
mv improved_positions_*.csv $OUTPUT_DIR/
echo -e "\n Position CSVs for visualization moved to: ${BLUE}$OUTPUT_DIR/${NC}"
fi
# Create index file
cat > $OUTPUT_DIR/index.txt << EOF
Recorded Fuzzing Results
========================
Run ID: $RUN_ID
Date: $(date)
Optimizer: $OPTIMIZER
Total Runs: $RUNS_VALUE
Profitable Scenarios: $SCENARIO_COUNT
Files:
------
EOF
for file in $OUTPUT_DIR/*; do
echo "- $(basename $file)" >> $OUTPUT_DIR/index.txt
done
echo ""
echo -e "${GREEN}=== NEXT STEPS ===${NC}"
echo "1. Review summaries:"
echo " cat $OUTPUT_DIR/summary_${RUN_ID}_seed*.txt"
echo ""
echo "2. Replay a specific scenario:"
echo " ./analysis/replay-scenario.sh ${RUN_ID} <seed_number>"
echo ""
echo "3. Visualize positions (if CSV tracking enabled):"
echo " ./analysis/view-scenarios.sh $OUTPUT_DIR"
echo ""
echo "4. Share with team:"
echo -e " ${BOLD}Reference ID: ${RUN_ID}${NC}"
echo " \"Found exploit ${RUN_ID} with ${SCENARIO_COUNT} profitable scenarios\""
else
echo ""
echo -e "${YELLOW}=== No Profitable Scenarios Found ===${NC}"
echo "This could mean the protocol is secure under these conditions."
echo ""
echo "Try adjusting parameters:"
echo " - Increase runs: ./analysis/run-recorded-fuzzing.sh $OPTIMIZER runs=100"
echo " - Try different optimizer: ./analysis/run-recorded-fuzzing.sh WhaleOptimizer"
echo " - Use extreme optimizer: ./analysis/run-recorded-fuzzing.sh ExtremeOptimizer"
echo " - Disable staking: ./analysis/run-recorded-fuzzing.sh $OPTIMIZER runs=$RUNS_VALUE trades=default staking=off"
fi
echo ""
echo -e "${GREEN}Results saved to: $OUTPUT_DIR/${NC}"
echo -e "Run ID: ${BOLD}${RUN_ID}${NC}"
# Launch visualizer if position CSVs were generated
POSITION_CSV_COUNT=$(ls -1 $OUTPUT_DIR/improved_positions_*.csv 2>/dev/null | wc -l)
if [ $POSITION_CSV_COUNT -gt 0 ] && [ $SCENARIO_COUNT -gt 0 ]; then
echo ""
echo -e "${GREEN}=== Launching Scenario Visualizer ===${NC}"
# Get the first position CSV for visualization
FIRST_CSV=$(ls -1 $OUTPUT_DIR/improved_positions_*.csv 2>/dev/null | head -1)
echo "CSV file: $FIRST_CSV"
# Create a temporary symlink to the CSV for the viewer in the analysis directory
TEMP_LINK="analysis/profitable_scenario.csv"
if [ -f "$TEMP_LINK" ] || [ -L "$TEMP_LINK" ]; then
rm -f "$TEMP_LINK"
fi
# Use absolute path for the symlink
ln -s "$(realpath $FIRST_CSV)" "$TEMP_LINK"
echo "Created symlink: $TEMP_LINK -> $FIRST_CSV"
# Check if server is already running on common ports
SERVER_RUNNING=false
EXISTING_PORT=""
for PORT in 8000 8001 8002; do
if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null 2>&1; then
# Check if it's a python http server in our analysis directory
if lsof -Pi :$PORT -sTCP:LISTEN 2>/dev/null | grep -q "python.*http.server"; then
SERVER_RUNNING=true
EXISTING_PORT=$PORT
break
fi
fi
done
if [ "$SERVER_RUNNING" = true ]; then
echo -e "${YELLOW}Server already running on port $EXISTING_PORT${NC}"
echo -e "${GREEN}Open browser to: http://localhost:$EXISTING_PORT/scenario-visualizer.html${NC}"
echo ""
echo -e "${YELLOW}Press Enter to exit (server will keep running)...${NC}"
read -r
else
# Start the viewer in background
./analysis/view-scenarios.sh &
VIEWER_PID=$!
# Give the server time to start
sleep 2
echo ""
echo -e "${GREEN}Browser should open to: http://localhost:8000/scenario-visualizer.html${NC}"
echo ""
echo -e "${YELLOW}Press Enter to stop the viewer and exit...${NC}"
read -r
# Kill the viewer process
if [ -n "$VIEWER_PID" ]; then
pkill -P $VIEWER_PID 2>/dev/null || true
kill $VIEWER_PID 2>/dev/null || true
fi
echo -e "${GREEN}Viewer stopped.${NC}"
fi
# Clean up the symlink
rm -f "$TEMP_LINK"
fi