264 lines
10 KiB
Bash
Executable file
264 lines
10 KiB
Bash
Executable file
#!/bin/bash
|
|
# Parameter sweep for finding safe/unsafe optimizer parameter boundaries
|
|
#
|
|
# Usage: ./analysis/run-parameter-sweep.sh [mode]
|
|
# Modes:
|
|
# quick - Small focused grid (~5 min)
|
|
# standard - Medium grid (~30 min)
|
|
# boundary - Focused on exploitation boundary (~20 min)
|
|
#
|
|
# Run from onchain/ directory
|
|
|
|
set -euo pipefail
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
MODE=${1:-standard}
|
|
|
|
# Common: uncapped swaps for realistic exploitation testing
|
|
UNCAPPED="true"
|
|
MINBUY="20"
|
|
MAXBUY="80"
|
|
|
|
case $MODE in
|
|
quick)
|
|
CI="0,500000000000000000,1000000000000000000"
|
|
AS="100000000000000000,500000000000000000,1000000000000000000"
|
|
AW="30,50,80"
|
|
DD="200000000000000000,1000000000000000000"
|
|
BB="80,100"
|
|
RUNS=3
|
|
TRADES=20
|
|
;;
|
|
standard)
|
|
CI="0,200000000000000000,500000000000000000,800000000000000000,1000000000000000000"
|
|
AS="50000000000000000,100000000000000000,200000000000000000,500000000000000000,700000000000000000,1000000000000000000"
|
|
AW="20,50,80"
|
|
DD="200000000000000000,500000000000000000,1000000000000000000"
|
|
BB="80,100"
|
|
RUNS=5
|
|
TRADES=30
|
|
;;
|
|
boundary)
|
|
# Focused sweep around known exploitation boundary:
|
|
# Bull (exploitable): CI=0, AS=1e18, AW=50, DD=1e18
|
|
# Bear (mostly safe): CI=0.8e18, AS=0.2e18, AW=80+, DD=0.2e18
|
|
# Key: anchorShare transition between 0.2 and 0.7
|
|
CI="0,300000000000000000,500000000000000000,800000000000000000"
|
|
AS="100000000000000000,200000000000000000,300000000000000000,400000000000000000,500000000000000000,700000000000000000,1000000000000000000"
|
|
AW="30,50,80"
|
|
DD="200000000000000000,500000000000000000,1000000000000000000"
|
|
BB="80"
|
|
RUNS=5
|
|
TRADES=30
|
|
;;
|
|
*)
|
|
echo "Unknown mode: $MODE (use: quick, standard, boundary)"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo -e "${GREEN}=== KRAIKEN Parameter Sweep ($MODE mode) ===${NC}"
|
|
echo "Runs per combo: $RUNS | Trades per run: $TRADES"
|
|
echo "Uncapped: $UNCAPPED | Trade range: ${MINBUY}-${MAXBUY} ETH"
|
|
|
|
# Master results
|
|
SUMMARY_FILE="analysis/sweep-FULL-summary.csv"
|
|
echo "ci,anchor_share,anchor_width,discovery_depth,buy_bias,max_trader_pnl,min_trader_pnl,any_lm_loss,lm_eth_delta" > "$SUMMARY_FILE"
|
|
|
|
# Split into small batches: one forge call per (CI, AS, AW) triple
|
|
# Each call handles DD*BB combos to stay within gas limits
|
|
batch=0
|
|
total_combos=0
|
|
start_time=$(date +%s)
|
|
|
|
for ci_val in $(echo "$CI" | tr ',' ' '); do
|
|
for as_val in $(echo "$AS" | tr ',' ' '); do
|
|
for aw_val in $(echo "$AW" | tr ',' ' '); do
|
|
batch=$((batch + 1))
|
|
ci_pct=$(python3 -c "print(f'{int(\"$ci_val\")/1e18:.0%}')" 2>/dev/null || echo "$ci_val")
|
|
as_pct=$(python3 -c "print(f'{int(\"$as_val\")/1e18:.1%}')" 2>/dev/null || echo "$as_val")
|
|
|
|
echo -ne "\r${BLUE}[$batch] CI=$ci_pct AS=$as_pct AW=$aw_val${NC} "
|
|
|
|
CI_VALUES="$ci_val" \
|
|
AS_VALUES="$as_val" \
|
|
AW_VALUES="$aw_val" \
|
|
DD_VALUES="$DD" \
|
|
BB_VALUES="$BB" \
|
|
RUNS_PER_COMBO="$RUNS" \
|
|
TRADES_PER_RUN="$TRADES" \
|
|
UNCAPPED_SWAPS="$UNCAPPED" \
|
|
MIN_BUY_ETH="$MINBUY" \
|
|
MAX_BUY_ETH="$MAXBUY" \
|
|
SWEEP_TAG="B${batch}" \
|
|
forge script analysis/ParameterSweepFuzzing.s.sol:ParameterSweepFuzzing \
|
|
--skip-simulation --gas-estimate-multiplier 300 -vv 2>&1 | grep "UNSAFE" || true
|
|
|
|
batch_csv="analysis/sweep-B${batch}-summary.csv"
|
|
if [ -f "$batch_csv" ]; then
|
|
new_lines=$(tail -n +2 "$batch_csv" | wc -l)
|
|
total_combos=$((total_combos + new_lines))
|
|
tail -n +2 "$batch_csv" >> "$SUMMARY_FILE"
|
|
rm "$batch_csv"
|
|
fi
|
|
done
|
|
done
|
|
done
|
|
|
|
elapsed=$(($(date +%s) - start_time))
|
|
echo ""
|
|
echo ""
|
|
echo -e "${GREEN}=== ANALYSIS ===${NC}"
|
|
echo "Elapsed: ${elapsed}s"
|
|
|
|
# Analyze results
|
|
total_tested=$(tail -n +2 "$SUMMARY_FILE" | wc -l | tr -d ' ')
|
|
unsafe_combos=$(tail -n +2 "$SUMMARY_FILE" | grep -c ',true,' || true)
|
|
unsafe_combos=${unsafe_combos:-0}
|
|
safe_combos=$((total_tested - unsafe_combos))
|
|
|
|
echo "Total tested: $total_tested"
|
|
echo -e "Safe: ${GREEN}$safe_combos${NC}"
|
|
echo -e "Unsafe: ${RED}$unsafe_combos${NC}"
|
|
|
|
# Generate report
|
|
RESULTS_FILE="analysis/PARAMETER_SEARCH_RESULTS.md"
|
|
|
|
cat > "$RESULTS_FILE" << EOF
|
|
# KRAIKEN Parameter Search Results
|
|
|
|
## Objective
|
|
Find optimizer parameters where the LiquidityManager NEVER loses ETH regardless of trade sequence.
|
|
|
|
## Methodology
|
|
- **Mode**: $MODE
|
|
- **Runs per parameter combination**: $RUNS
|
|
- **Trades per run**: $TRADES
|
|
- **Uncapped swaps**: $UNCAPPED (trades push through position boundaries)
|
|
- **Trade size range**: ${MINBUY}-${MAXBUY} ETH (vs 100 ETH LM balance)
|
|
- **VWAP accumulation**: Environment reused across runs per combo
|
|
- **Buy biases tested**: $(echo $BB | tr ',' ', ')%
|
|
- **Total combinations tested**: $total_tested
|
|
- **Elapsed time**: ${elapsed}s
|
|
|
|
### Parameters Searched
|
|
| Parameter | Values | Description |
|
|
|-----------|--------|-------------|
|
|
| capitalInefficiency | $(python3 -c "print(', '.join(f'{int(x)/1e18:.0%}' for x in '$CI'.split(',')))" 2>/dev/null || echo "$CI") | Capital buffer (0=aggressive, 1e18=conservative) |
|
|
| anchorShare | $(python3 -c "print(', '.join(f'{int(x)/1e18:.1%}' for x in '$AS'.split(',')))" 2>/dev/null || echo "$AS") | ETH allocation to anchor vs floor |
|
|
| anchorWidth | $(echo $AW | tr ',' ', ') | Anchor position width (1-100) |
|
|
| discoveryDepth | $(python3 -c "print(', '.join(f'{int(x)/1e18:.0%}' for x in '$DD'.split(',')))" 2>/dev/null || echo "$DD") | Discovery liquidity density |
|
|
| buyBias | $(echo $BB | tr ',' ', ')% | Adversarial trade mix (80=buy-heavy, 100=buy-only) |
|
|
|
|
### Key Metrics
|
|
- **Trader PnL < 0**: LM gained ETH (SAFE). Trader lost money.
|
|
- **Trader PnL > 0**: LM lost ETH (UNSAFE). Trader extracted ETH.
|
|
|
|
## Results Summary
|
|
- **Safe combinations**: $safe_combos / $total_tested
|
|
- **Unsafe combinations**: $unsafe_combos / $total_tested
|
|
EOF
|
|
|
|
if [ "$unsafe_combos" -gt 0 ]; then
|
|
{
|
|
echo ""
|
|
echo "## UNSAFE Parameters (Trader Profited = LM Lost ETH)"
|
|
echo ""
|
|
echo "| CI | AnchorShare | AnchorWidth | DiscoveryDepth | BuyBias | Max Trader PnL (ETH) |"
|
|
echo "|-----|-------------|-------------|----------------|---------|----------------------|"
|
|
|
|
while IFS=, read -r ci as aw dd bb maxpnl minpnl loss lmdelta; do
|
|
if [[ "$loss" == "true" ]]; then
|
|
ci_pct=$(python3 -c "print(f'{int(\"$ci\")/1e18:.0%}')" 2>/dev/null || echo "$ci")
|
|
as_pct=$(python3 -c "print(f'{int(\"$as\")/1e18:.1%}')" 2>/dev/null || echo "$as")
|
|
dd_pct=$(python3 -c "print(f'{int(\"$dd\")/1e18:.0%}')" 2>/dev/null || echo "$dd")
|
|
maxpnl_eth=$(python3 -c "print(f'{int(\"$maxpnl\")/1e18:+.4f}')" 2>/dev/null || echo "$maxpnl")
|
|
echo "| $ci_pct | $as_pct | $aw | $dd_pct | $bb | $maxpnl_eth |"
|
|
fi
|
|
done < <(tail -n +2 "$SUMMARY_FILE")
|
|
} >> "$RESULTS_FILE"
|
|
fi
|
|
|
|
{
|
|
echo ""
|
|
echo "## SAFE Parameters"
|
|
echo ""
|
|
} >> "$RESULTS_FILE"
|
|
|
|
if [ "$safe_combos" -gt 0 ]; then
|
|
{
|
|
echo "All tested parameter combinations where the LM never lost ETH:"
|
|
echo ""
|
|
echo "### Safe Ranges by Buy Bias"
|
|
echo ""
|
|
} >> "$RESULTS_FILE"
|
|
|
|
for bb_val in $(echo "$BB" | tr ',' ' '); do
|
|
safe_at_bb=$(tail -n +2 "$SUMMARY_FILE" | grep ",$bb_val," | grep -c ',false,' || true)
|
|
safe_at_bb=${safe_at_bb:-0}
|
|
total_at_bb=$(tail -n +2 "$SUMMARY_FILE" | grep -c ",$bb_val," || true)
|
|
total_at_bb=${total_at_bb:-0}
|
|
echo "- **BuyBias=${bb_val}%**: ${safe_at_bb}/${total_at_bb} safe" >> "$RESULTS_FILE"
|
|
done
|
|
|
|
{
|
|
echo ""
|
|
echo "### Top 20 Safest Combinations (most negative max trader PnL = hardest to exploit)"
|
|
echo ""
|
|
echo "| CI | AnchorShare | AnchorWidth | DiscoveryDepth | BuyBias | Max Trader PnL (ETH) |"
|
|
echo "|-----|-------------|-------------|----------------|---------|----------------------|"
|
|
} >> "$RESULTS_FILE"
|
|
|
|
tail -n +2 "$SUMMARY_FILE" | grep ',false,' | sort -t, -k6 -n | head -20 | while IFS=, read -r ci as aw dd bb maxpnl minpnl loss lmdelta; do
|
|
ci_pct=$(python3 -c "print(f'{int(\"$ci\")/1e18:.0%}')" 2>/dev/null || echo "$ci")
|
|
as_pct=$(python3 -c "print(f'{int(\"$as\")/1e18:.1%}')" 2>/dev/null || echo "$as")
|
|
dd_pct=$(python3 -c "print(f'{int(\"$dd\")/1e18:.0%}')" 2>/dev/null || echo "$dd")
|
|
maxpnl_eth=$(python3 -c "print(f'{int(\"$maxpnl\")/1e18:+.4f}')" 2>/dev/null || echo "$maxpnl")
|
|
echo "| $ci_pct | $as_pct | $aw | $dd_pct | $bb | $maxpnl_eth |"
|
|
done >> "$RESULTS_FILE"
|
|
else
|
|
echo "No safe parameter combinations found." >> "$RESULTS_FILE"
|
|
fi
|
|
|
|
{
|
|
echo ""
|
|
echo "## Recommendations"
|
|
echo ""
|
|
} >> "$RESULTS_FILE"
|
|
|
|
if [ "$unsafe_combos" -eq 0 ]; then
|
|
cat >> "$RESULTS_FILE" << 'RECO'
|
|
**All tested parameter combinations are SAFE.** The three-position strategy's asymmetric
|
|
slippage profile effectively prevents profitable arbitrage across all tested parameters.
|
|
RECO
|
|
else
|
|
cat >> "$RESULTS_FILE" << 'RECO'
|
|
**Some parameter combinations are UNSAFE.** The exploitation boundary depends primarily on:
|
|
1. **anchorShare**: Higher values allocate more ETH to the thin anchor position, reducing floor protection
|
|
2. **capitalInefficiency**: Lower values (0%) make the floor position more aggressive, increasing exploit risk
|
|
3. **anchorWidth**: Narrower widths concentrate anchor liquidity, making it cheaper to push through
|
|
|
|
### Safe Zone
|
|
Parameters where the trader never profited across all tested scenarios.
|
|
|
|
### Unsafe Zone
|
|
Parameters where at least one test run showed trader profit (= LM ETH loss).
|
|
The exploitation pattern is: buy→recenter→sell→recenter repeated over many cycles,
|
|
where VWAP accumulates at inflated prices and the floor gets positioned too high.
|
|
RECO
|
|
fi
|
|
|
|
{
|
|
echo ""
|
|
echo "---"
|
|
echo "*Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)*"
|
|
} >> "$RESULTS_FILE"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}Report: $RESULTS_FILE${NC}"
|
|
echo -e "${GREEN}Data: $SUMMARY_FILE${NC}"
|