fix: bootstrap-light.sh lacks Push3 candidate injection (#999)
Add CANDIDATE env var support to bootstrap-light.sh. When set to a .push3 file path, the script: 1. Invokes push3-transpiler to regenerate OptimizerV3Push3.sol 2. Extracts the function body into OptimizerV3Push3Lib.sol 3. Deploys contracts normally via DeployLocal.sol 4. Deploys OptimizerV3 and upgrades the UUPS proxy via upgradeTo() Also updates formulas/run-red-team.toml to reflect the implementation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
29b8f7d426
commit
349bd2c2c6
2 changed files with 134 additions and 17 deletions
|
|
@ -55,9 +55,9 @@ description = "Timeout in seconds for the adversarial agent run (maps to CLAUDE_
|
||||||
# → promote-attacks (if floor broken) → deliver → teardown.
|
# → promote-attacks (if floor broken) → deliver → teardown.
|
||||||
#
|
#
|
||||||
# CANDIDATE_NAME and OPTIMIZER_PROFILE label the evidence record and attack
|
# CANDIDATE_NAME and OPTIMIZER_PROFILE label the evidence record and attack
|
||||||
# filenames; they do not select which optimizer is deployed — bootstrap-light
|
# filenames. To deploy a specific Push3 candidate, set the CANDIDATE env var
|
||||||
# always deploys via DeployLocal.sol. Per-candidate Push3 injection is planned
|
# (path to a .push3 file) — bootstrap-light.sh will transpile, recompile, and
|
||||||
# but not yet wired (see notes.candidate_injection).
|
# upgrade the Optimizer proxy to OptimizerV3 (see notes.candidate_injection).
|
||||||
|
|
||||||
[execution]
|
[execution]
|
||||||
script = "scripts/harb-evaluator/red-team.sh"
|
script = "scripts/harb-evaluator/red-team.sh"
|
||||||
|
|
@ -81,9 +81,9 @@ scripts/harb-evaluator/bootstrap-light.sh:
|
||||||
liquidity into positions — establishing a realistic baseline.
|
liquidity into positions — establishing a realistic baseline.
|
||||||
- Verifies Anvil responds and all contract addresses are present in
|
- Verifies Anvil responds and all contract addresses are present in
|
||||||
onchain/deployments-local.json before proceeding.
|
onchain/deployments-local.json before proceeding.
|
||||||
Note: the deployed optimizer is always the default from DeployLocal.sol.
|
When the CANDIDATE env var is set (path to a .push3 file), bootstrap-light.sh
|
||||||
Per-candidate Push3 transpilation is not yet implemented here; see
|
transpiles the candidate and upgrades the Optimizer proxy to OptimizerV3.
|
||||||
notes.candidate_injection.
|
See notes.candidate_injection for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[[steps]]
|
[[steps]]
|
||||||
|
|
@ -242,13 +242,14 @@ rediscoveries are silently dropped and the step exits 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
candidate_injection = """
|
candidate_injection = """
|
||||||
Push3 candidate injection is not yet implemented: bootstrap-light.sh always
|
Push3 candidate injection is supported via the CANDIDATE env var in
|
||||||
deploys the default optimizer via DeployLocal.sol and does not read the
|
bootstrap-light.sh. When CANDIDATE points to a .push3 file the script:
|
||||||
CANDIDATE env var. The candidate_name and optimizer_profile inputs are used
|
1. Invokes push3-transpiler to regenerate OptimizerV3Push3.sol.
|
||||||
only for labelling (evidence records, attack filenames, PR titles); they do not
|
2. Extracts the function body into OptimizerV3Push3Lib.sol (shared library).
|
||||||
affect which optimizer is deployed.
|
3. Deploys contracts normally via DeployLocal.sol (Optimizer v1 behind UUPS proxy).
|
||||||
Wiring CANDIDATE → push3-transpiler → forge compile → bootstrap-light is
|
4. Deploys a fresh OptimizerV3 implementation and upgrades the proxy via upgradeTo().
|
||||||
tracked as a follow-up issue.
|
The candidate_name and optimizer_profile inputs remain metadata-only (evidence
|
||||||
|
records, attack filenames, PR titles).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
run_attack_suite_gap = """
|
run_attack_suite_gap = """
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,21 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Lightweight bootstrap for red-team / evaluator use.
|
# Lightweight bootstrap for red-team / evaluator use.
|
||||||
# Starts only Anvil + deploys contracts. No ponder, no webapp, no txnbot.
|
# Starts only Anvil + deploys contracts. No ponder, no webapp, no txnbot.
|
||||||
|
#
|
||||||
|
# Environment overrides:
|
||||||
|
# CANDIDATE Path to a .push3 file. When set, the push3-transpiler is
|
||||||
|
# invoked to regenerate OptimizerV3Push3Lib.sol, then the
|
||||||
|
# deployed Optimizer UUPS proxy is upgraded to OptimizerV3
|
||||||
|
# (which delegates to the regenerated lib).
|
||||||
|
# RPC_URL Anvil RPC endpoint (default: http://localhost:8545)
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
ONCHAIN_DIR="$REPO_ROOT/onchain"
|
ONCHAIN_DIR="$REPO_ROOT/onchain"
|
||||||
RPC_URL="http://localhost:8545"
|
RPC_URL="${RPC_URL:-http://localhost:8545}"
|
||||||
CAST="$HOME/.foundry/bin/cast"
|
CAST="$HOME/.foundry/bin/cast"
|
||||||
FORGE="$HOME/.foundry/bin/forge"
|
FORGE="$HOME/.foundry/bin/forge"
|
||||||
|
CANDIDATE="${CANDIDATE:-}"
|
||||||
|
|
||||||
log() { echo "[bootstrap-light] $*"; }
|
log() { echo "[bootstrap-light] $*"; }
|
||||||
die() { log "ERROR: $*" >&2; exit 1; }
|
die() { log "ERROR: $*" >&2; exit 1; }
|
||||||
|
|
@ -30,7 +38,85 @@ log "Clearing code from deployer ($DEPLOYER) + feeDest"
|
||||||
$CAST rpc --rpc-url "$RPC_URL" anvil_setCode "$DEPLOYER" "0x" 2>/dev/null || true
|
$CAST rpc --rpc-url "$RPC_URL" anvil_setCode "$DEPLOYER" "0x" 2>/dev/null || true
|
||||||
$CAST rpc --rpc-url "$RPC_URL" anvil_setCode "0xf6a3eef9088A255c32b6aD2025f83E57291D9011" "0x" 2>/dev/null || true
|
$CAST rpc --rpc-url "$RPC_URL" anvil_setCode "0xf6a3eef9088A255c32b6aD2025f83E57291D9011" "0x" 2>/dev/null || true
|
||||||
|
|
||||||
# 3. Deploy contracts — capture output for addresses
|
# 3. Push3 candidate injection (optional)
|
||||||
|
# When CANDIDATE is set, transpile the .push3 file into OptimizerV3Push3.sol,
|
||||||
|
# then regenerate OptimizerV3Push3Lib.sol so that OptimizerV3 (which delegates
|
||||||
|
# to the lib) will use the candidate logic after the proxy upgrade in step 6.
|
||||||
|
if [[ -n "$CANDIDATE" ]]; then
|
||||||
|
[[ -f "$CANDIDATE" ]] || die "CANDIDATE file not found: $CANDIDATE"
|
||||||
|
log "Transpiling candidate: $CANDIDATE"
|
||||||
|
|
||||||
|
TRANSPILER_DIR="$REPO_ROOT/tools/push3-transpiler"
|
||||||
|
TRANSPILER_OUT="$ONCHAIN_DIR/src/OptimizerV3Push3.sol"
|
||||||
|
|
||||||
|
# Ensure transpiler deps are installed
|
||||||
|
if [[ ! -d "$TRANSPILER_DIR/node_modules" ]]; then
|
||||||
|
(cd "$TRANSPILER_DIR" && npm install --silent) || die "transpiler npm install failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Transpile Push3 → standalone OptimizerV3Push3.sol
|
||||||
|
(cd "$TRANSPILER_DIR" && npx tsx src/index.ts "$CANDIDATE" "$TRANSPILER_OUT") \
|
||||||
|
|| die "push3-transpiler failed"
|
||||||
|
|
||||||
|
# Regenerate OptimizerV3Push3Lib.sol from the transpiler output.
|
||||||
|
# Extracts the calculateParams function body and wraps it in a library.
|
||||||
|
python3 - "$TRANSPILER_OUT" "$ONCHAIN_DIR/src/OptimizerV3Push3Lib.sol" <<'PYEOF' || die "lib generation failed"
|
||||||
|
import sys
|
||||||
|
|
||||||
|
with open(sys.argv[1]) as f:
|
||||||
|
push3 = f.read()
|
||||||
|
|
||||||
|
# Extract function body (everything between the first { after calculateParams and its closing })
|
||||||
|
fn_start = push3.find("function calculateParams")
|
||||||
|
if fn_start == -1:
|
||||||
|
sys.exit("calculateParams not found in transpiler output")
|
||||||
|
brace_start = push3.find("{", fn_start)
|
||||||
|
sig_end = push3.index("\n", brace_start) + 1
|
||||||
|
|
||||||
|
lines = push3[sig_end:].split("\n")
|
||||||
|
body_lines = []
|
||||||
|
depth = 1
|
||||||
|
for line in lines:
|
||||||
|
depth += line.count("{") - line.count("}")
|
||||||
|
if depth <= 0:
|
||||||
|
break
|
||||||
|
body_lines.append(line)
|
||||||
|
else:
|
||||||
|
sys.exit("closing brace not found")
|
||||||
|
|
||||||
|
body = "\n".join(body_lines)
|
||||||
|
|
||||||
|
lib = f"""// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
|
import {{OptimizerInput}} from "./IOptimizer.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title OptimizerV3Push3Lib
|
||||||
|
* @notice Shared library containing the canonical Push3 transpiler output for
|
||||||
|
* OptimizerV3 parameter calculation. Used by both OptimizerV3Push3
|
||||||
|
* (standalone) and OptimizerV3 (UUPS-upgradeable Optimizer) so that
|
||||||
|
* future transpiler changes require only one edit.
|
||||||
|
* @dev Auto-regenerated by bootstrap-light.sh from CANDIDATE env var.
|
||||||
|
*/
|
||||||
|
library OptimizerV3Push3Lib {{
|
||||||
|
function calculateParams(OptimizerInput[8] memory inputs)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (uint256 ci, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth)
|
||||||
|
{{
|
||||||
|
{body}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
with open(sys.argv[2], "w") as f:
|
||||||
|
f.write(lib)
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
log "OptimizerV3Push3Lib.sol regenerated from candidate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Deploy contracts — capture output for addresses
|
||||||
log "Deploying contracts..."
|
log "Deploying contracts..."
|
||||||
cd "$ONCHAIN_DIR"
|
cd "$ONCHAIN_DIR"
|
||||||
# Fix ownership of forge artifacts (docker creates root-owned files)
|
# Fix ownership of forge artifacts (docker creates root-owned files)
|
||||||
|
|
@ -39,7 +125,7 @@ rm -f deployments-local.json # force fresh
|
||||||
DEPLOY_OUT=$($FORGE script script/DeployLocal.sol --rpc-url "$RPC_URL" --broadcast 2>&1)
|
DEPLOY_OUT=$($FORGE script script/DeployLocal.sol --rpc-url "$RPC_URL" --broadcast 2>&1)
|
||||||
echo "$DEPLOY_OUT" | grep -E "^\[|deployed|complete|Summary" || true
|
echo "$DEPLOY_OUT" | grep -E "^\[|deployed|complete|Summary" || true
|
||||||
|
|
||||||
# 4. Extract addresses from output and write deployments-local.json
|
# 5. Extract addresses from output and write deployments-local.json
|
||||||
KRK=$(echo "$DEPLOY_OUT" | grep -oP 'Kraiken deployed: \K0x[a-fA-F0-9]+')
|
KRK=$(echo "$DEPLOY_OUT" | grep -oP 'Kraiken deployed: \K0x[a-fA-F0-9]+')
|
||||||
[[ -n "$KRK" ]] || die "Could not extract Kraiken address from deploy output"
|
[[ -n "$KRK" ]] || die "Could not extract Kraiken address from deploy output"
|
||||||
STAKE=$(echo "$DEPLOY_OUT" | grep -oP 'Stake deployed: \K0x[a-fA-F0-9]+')
|
STAKE=$(echo "$DEPLOY_OUT" | grep -oP 'Stake deployed: \K0x[a-fA-F0-9]+')
|
||||||
|
|
@ -74,7 +160,37 @@ cat > "$ONCHAIN_DIR/deployments-local.json" << EOF
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 5. Verify
|
# 6. Upgrade Optimizer proxy to OptimizerV3 (candidate injection)
|
||||||
|
# DeployLocal deploys Optimizer (v1) behind a UUPS proxy. When a Push3
|
||||||
|
# candidate was transpiled in step 3, we deploy a fresh OptimizerV3
|
||||||
|
# implementation (which delegates to the regenerated OptimizerV3Push3Lib)
|
||||||
|
# and upgrade the proxy so the candidate logic is live on-chain.
|
||||||
|
if [[ -n "$CANDIDATE" ]]; then
|
||||||
|
log "Upgrading Optimizer proxy to OptimizerV3 (candidate: $(basename "$CANDIDATE" .push3))..."
|
||||||
|
# Deployer PK — Anvil account 0 (same key DeployLocal.sol uses via .secret.local)
|
||||||
|
DEPLOYER_PK=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
|
||||||
|
|
||||||
|
# Deploy OptimizerV3 implementation
|
||||||
|
V3_DEPLOY_OUT=$($FORGE create --rpc-url "$RPC_URL" --private-key "$DEPLOYER_PK" \
|
||||||
|
src/OptimizerV3.sol:OptimizerV3 2>&1) \
|
||||||
|
|| die "OptimizerV3 deployment failed: $V3_DEPLOY_OUT"
|
||||||
|
V3_IMPL=$(echo "$V3_DEPLOY_OUT" | grep -oP 'Deployed to: \K0x[a-fA-F0-9]+')
|
||||||
|
[[ -n "$V3_IMPL" ]] || die "Could not extract OptimizerV3 address from forge create output"
|
||||||
|
log "OptimizerV3 implementation: $V3_IMPL"
|
||||||
|
|
||||||
|
# Upgrade the UUPS proxy
|
||||||
|
$CAST send --rpc-url "$RPC_URL" --private-key "$DEPLOYER_PK" \
|
||||||
|
"$OPT" "upgradeTo(address)" "$V3_IMPL" >/dev/null 2>&1 \
|
||||||
|
|| die "upgradeTo failed"
|
||||||
|
log "Proxy upgraded to OptimizerV3"
|
||||||
|
|
||||||
|
# Verify the upgrade by calling getLiquidityParams through the proxy
|
||||||
|
VERIFY_OUT=$($CAST call --rpc-url "$RPC_URL" "$OPT" \
|
||||||
|
"getLiquidityParams()(uint256,uint256,uint24,uint256)" 2>/dev/null) || true
|
||||||
|
log "Post-upgrade getLiquidityParams: $VERIFY_OUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7. Verify
|
||||||
VWAP=$($CAST call --rpc-url "$RPC_URL" "$LM" "cumulativeVolume()(uint256)" 2>/dev/null || echo "0")
|
VWAP=$($CAST call --rpc-url "$RPC_URL" "$LM" "cumulativeVolume()(uint256)" 2>/dev/null || echo "0")
|
||||||
log "LiquidityManager: $LM"
|
log "LiquidityManager: $LM"
|
||||||
log "cumulativeVolume: $VWAP"
|
log "cumulativeVolume: $VWAP"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue