Commit graph

111 commits

Author SHA1 Message Date
openhands
a2f89968db fix: fix: red-team.sh V3_FACTORY hardcodes Base mainnet address instead of Sepolia (#854)
bootstrap-light.sh now extracts the Uniswap V3 pool address from
DeployLocal.sol deploy output and writes both Pool and V3Factory
(Base Sepolia: 0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24) into
deployments-local.json alongside the existing contract addresses.

red-team.sh now reads V3_FACTORY and POOL from deployments-local.json
instead of hardcoding the Base mainnet factory address
(0x33128a8fC17869897dcE68Ed026d694621f6FDfD), and removes the getPool()
RPC call that always failed with "contract does not have any code" on
the Sepolia fork.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:02:17 +00:00
openhands
91e4bdf926 fix: red-team-program.md taxRate naming inconsistency (pre-existing) (#835) 2026-03-16 09:46:55 +00:00
openhands
cb305b8c81 fix: MEMORY_FILE parent directory ($REPO_ROOT/tmp/) also not guaranteed to exist (#844)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 07:57:20 +00:00
openhands
8986154d8f fix: sleep 5 at teardown violates AGENTS.md engineering principles (#845) 2026-03-16 07:06:57 +00:00
openhands
ac2fa16e2e fix: ATTACKS_OUT directory not guaranteed to exist (#816) 2026-03-15 22:36:51 +00:00
openhands
ae3eb14833 fix: address review findings for sweep-results.tsv (#818)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 20:48:33 +00:00
openhands
3c6be7d86f fix: feat: structured sweep-results.tsv for red-team sweep (#818)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 20:20:13 +00:00
openhands
0d09f598d9 fix: Hardcoded TWAP/cooldown values not documented (#825)
Document MIN_RECENTER_INTERVAL (60 s, LiquidityManager.sol:61) and
PRICE_STABILITY_INTERVAL (300 s, PriceOracle.sol:14) in
docs/ARCHITECTURE.md and docs/PRODUCT-TRUTH.md so that agent-facing
and product-facing copy stays traceable to source constants.

Add an inline HTML comment in red-team-program.md next to the
hardcoded 60s/300s sentence pointing to the two source constants,
making drift detectable during code review.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 19:51:52 +00:00
openhands
2293ece915 fix: 'Trigger recenter (account 2 only)' label contradicts public recenter comment (#826)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 19:17:16 +00:00
openhands
13d5b40564 fix: Kraiken.sol and Stake.sol absent from agent context across all runs (#829)
Inject Kraiken.sol (outstandingSupply, mint/burn mechanics) and Stake.sol
(snatch, withdrawal, KRK exclusion from floor denominator) into the red-team
agent prompt so agents can reason from actual source rather than guesses.

- red-team.sh: read SOL_KRAIKEN and SOL_STAKE from onchain/src/ alongside
  the other six contracts already injected
- red-team-program.md: add ### Kraiken.sol and ### Stake.sol sections in the
  Source Code reference block (after PriceOracle.sol)
- AGENTS.md: document the full list of injected contracts in a new
  "Red-team Agent Context" section; both files are now listed as in-scope

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 18:41:57 +00:00
openhands
012b31056e fix: refactor: extract red-team prompt to red-team-program.md (#819)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 17:54:33 +00:00
openhands
4d0390c4fa fix: address review findings for cross-candidate red-team sweep (#822)
- red-team-sweep.sh: reset CROSS_PATTERNS_FILE at sweep start to prevent
  stale patterns from prior invocations contaminating a fresh run
- red-team-sweep.sh: wrap pattern-extraction Python in set +e/set -e and
  capture output so log() prefix is applied; move memory truncation outside
  the if-block so it runs unconditionally even if Python fails
- red-team.sh: filter entries where candidate == current_candidate before
  grouping, removing self-referential cross-candidate evidence
- red-team.sh: skip entries with empty pattern key (both pattern and
  strategy fields empty) to prevent spurious bucket merging

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 17:02:19 +00:00
openhands
9ee1429604 fix: feat: red-team sweep should seed each candidate with cross-candidate attack patterns (#822)
- red-team-sweep.sh: after each candidate completes, extract all memory
  entries into /tmp/red-team-cross-patterns.jsonl (append), then clear
  the raw memory file so the next candidate starts with a fresh state
- red-team.sh: define CROSS_PATTERNS_FILE; before building the prompt,
  read the cross-patterns file and generate a "Cross-Candidate
  Intelligence" section grouped by abstract op pattern — universal
  patterns (broke 2+ candidates), candidate-specific wins, and patterns
  that held everywhere — each annotated with optimizer profiles
- The new section is injected into the Claude prompt above the existing
  Previous Findings block, satisfying all acceptance criteria

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 16:30:54 +00:00
openhands
7950608179 fix: address review findings for red-team memory tracking (#820)
- make_pattern: replace text.find('stake')/find('unstake') with
  re.search(r'\bstake\b')/re.search(r'\bunstake\b') so 'stake' is never
  found as a substring of 'unstake' (bug #1)
- make_pattern: track first-occurrence position of each op and sort by
  position before building the sequence string, preserving actual
  execution order instead of a hardcoded canonical order (bug #2)
- insight capture: track insight_pri on the current dict; only overwrite
  stored insight when new match has strictly higher priority (lower index),
  preventing a late 'because...' clause from silently replacing an earlier
  'Key Insight:' capture (warning #3)
- run_num: compute max(run)+1 from JSON entries instead of wc -l so run
  numbers stay monotonically increasing after memory trim (info #4)
- red-team-sweep.sh: also set adaptive flag when any r37-r40 register has
  a variable-form assignment (r40 = uint256(someVar)), catching candidates
  where only one branch uses constants (warning #5)
- red-team-sweep.sh: remove unnecessary 'import sys as _sys' in except
  block; sys is already in scope (nit #6)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 15:54:01 +00:00
openhands
e7c60edeb6 fix: feat: red-team memory should track candidate + abstract learnings (#820)
- Add CANDIDATE_NAME and OPTIMIZER_PROFILE env vars to red-team.sh
  (defaults to "unknown" for standalone runs)
- Update extract_memory Python: new fields candidate, optimizer_profile,
  pattern (abstract op sequence via make_pattern()), and improved insight
  extraction that also captures WHY explanations (because/since/due to)
- Update MEMORY_SECTION Python: entries now grouped by candidate;
  universal patterns (DECREASED across multiple candidates) surfaced first
- Update prompt: add "Current Attack Target" table with candidate/profile,
  optimizer parameter explanations (CI/AW/AS/DD behavioral impact),
  Rule 9 requiring pattern+insight per strategy, updated report format
  with Pattern/Insight fields and universal-pattern conclusion field
- Update red-team-sweep.sh: after inject, parse OptimizerV3Push3.sol for
  r40/r39/r38/r37 constants to build OPTIMIZER_PROFILE string; pass
  CANDIDATE_NAME and OPTIMIZER_PROFILE as env vars to red-team.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 15:23:43 +00:00
openhands
4779749f2b fix: feat: red-team agent should read LM and optimizer Solidity source (#821)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 14:18:10 +00:00
openhands
7d0473ade7 fix: fix: red-team prompt missing evm_increaseTime for TWAP-enforced recenter (#823)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 10:47:36 +00:00
johba
ff86b3691d chore: extract shared inject.sh, add red-team-sweep.sh (#806)
## What
- `tools/push3-transpiler/inject.sh` — shared transpile+inject logic used by both batch-eval and red-team-sweep
- `batch-eval.sh` — replaced inline 60-line Python block with `inject.sh` call
- `scripts/harb-evaluator/red-team-sweep.sh` — red-teams each kindergarten seed using existing `red-team.sh`, with random smoke test gate

## Why
Sweep script kept breaking because I rewrote the injection logic instead of reusing batch-eval's proven Python. Now there's one copy.

## Testing
- inject.sh tested manually on DO box with optimizer_v3 seed
- Smoke test picks random seed, injects + compiles before starting sweep

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/806
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-15 10:24:03 +01:00
openhands
7618309db5 fix: red-team.sh and export-attacks.py use Base Sepolia addresses labeled as mainnet (#794)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 06:48:16 +00:00
openhands
0e33d6cbba fix: DeployLocal.sol feeDest 0xf6a3... may have code on Base Sepolia fork (#760) 2026-03-14 20:58:34 +00:00
openhands
e9397891ed fix: remove setRecenterAccess from red-team.sh — recenter() is now public 2026-03-14 15:10:59 +00:00
openhands
2cdc1f7234 fix: restore bootstrap_vwap from master 2026-03-14 13:31:23 +00:00
openhands
ab800d07f6 fix: fund FEE_DEST before impersonation in grant_recenter_access
FEE_DEST is now a keccak-derived address with zero ETH balance.
anvil_impersonateAccount succeeds but cast send fails on gas deduction.
Add anvil_setBalance before impersonation, matching the same fix
already applied in red-team.sh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 13:31:23 +00:00
openhands
130e22d189 fix: sync FEE_DEST in bootstrap-common.sh with DeployLocal.sol feeDest
DeployLocal.sol changed feeDest to keccak256('harb.local.feeDest') =
0x8A9145E1Ea4C4d7FB08cF1011c8ac1F0e10F9383 but bootstrap-common.sh
still had the old address 0xf6a3eef9088A255c32b6aD2025f83E57291D9011.
Mismatch caused setRecenterAccess to revert (impersonating wrong address).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 13:31:23 +00:00
openhands
dbf78de793 fix: bootstrap + red-team on forked networks
Bootstrap fixes:
- Idempotency check: skip if Kraiken already deployed on Anvil
- anvil_setCode to strip ERC-4337 code from deployer + feeDest
- DeployLocal.sol: feeDest derived from keccak256('harb.local.feeDest')

Red-team fixes:
- New bootstrap-light.sh: Anvil-only, ~30s deploy
- red-team.sh uses bootstrap-light instead of full docker compose
- anvil_setBalance for feeDest before impersonation
- forge --color never, path resolution, docker chown

Address fixes (all Base mainnet, in both FitnessEvaluator + AttackRunner):
- V3_FACTORY: 0x33128a8fC17869897dcE68Ed026d694621f6FDfD
- SWAP_ROUTER: 0x2626664c2603336E57B271c5C0b26F421741e481
- NPM_ADDR: 0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1
2026-03-14 13:31:23 +00:00
johba
6ff8282a7e Merge pull request 'fix: Remove recenterAccess — make recenter() public with TWAP enforcement (#706)' (#713) from fix/issue-706 into master 2026-03-14 10:48:59 +01:00
openhands
0d3aee15b4 fix: address AI review findings for #706 recenterAccess removal
- DeployBase.sol: remove broken inline second recenter() (would always
  revert with 'recenter cooldown' in same Forge broadcast); replace with
  operator instructions to run the new BootstrapVWAPPhase2.s.sol script
  at least 60 s after deployment
- BootstrapVWAPPhase2.s.sol: new script for the second VWAP bootstrap
  recenter on Base mainnet deployments
- StrategyExecutor.sol: update stale docstring that still described the
  removed recenterAccess bypass; reflect permissionless model with vm.warp
- TestBase.sol: remove vestigial recenterCaller parameter from all four
  setupEnvironment* functions (parameter was silently ignored after
  setRecenterAccess was removed); update all callers across six test files
- bootstrap-common.sh: fix misleading retry recenter in
  seed_application_state() — add evm_increaseTime 61 before evm_mine so
  the recenter cooldown actually clears and the retry can succeed

All 210 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 09:15:48 +00:00
openhands
52ed8ef233 fix: red-team.sh sudo strips FORK_URL before docker compose sees it (#729)
red-team.sh called bare `sudo docker compose up/down` which applies
env_reset and drops FORK_URL before anvil-entrypoint.sh can read it.
Change both calls to `sudo -E` so the caller's FORK_URL override is
propagated to docker-compose and into the anvil container.

Update ENVIRONMENT.md to reflect that a plain `FORK_URL=... bash
red-team.sh` invocation now works correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 08:30:49 +00:00
openhands
44df166b73 fix: Bare integer interpolation in agent-prompt heredoc at line 494 (#671)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 03:07:55 +00:00
openhands
cbab4c36da fix: NPM_ADDR may be Base Sepolia address in both files (#686)
Replace 0x27F971cb582BF9E50F397e4d29a5C7A34f11faA2 (Base Sepolia
NonfungiblePositionManager) with the correct Base mainnet address
0x03a520B32c04bf3beef7BEb72E919cF822Ed34F3 in all four files that
referenced it, and add an inline comment citing the chain and source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 02:22:51 +00:00
openhands
02b055ceb9 fix: move VWAP bootstrap from forge script to bootstrap-common.sh
vm.warp in forge script --broadcast only affects the local simulation
phase, not the actual Anvil node.  The pool.observe([300,0]) call in
recenter() therefore reverted with OLD when Forge pre-flighted the
broadcast transactions on Anvil.

Fix:
- Remove the vm.warp + 2-recenter + SeedSwapper VWAP bootstrap from
  DeployLocal.sol (only contract deployment now, simpler and reliable).
- Add bootstrap_vwap() to bootstrap-common.sh that uses Anvil RPC
  evm_increaseTime + evm_mine to advance chain time before each recenter,
  then executes a 0.5 ETH WETH->KRK seed swap between them.
- Call bootstrap_vwap() before fund_liquidity_manager() in both
  containers/bootstrap.sh and ci-bootstrap.sh so the LM is seeded with
  thin positions (1 ETH) during bootstrap, ensuring the 0.5 ETH swap
  moves the price >400 ticks (amplitude gate).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 23:28:52 +00:00
openhands
1a410a30b7 fix: Remove recenterAccess — make recenter() public with TWAP enforcement (#706) 2026-03-13 22:32:53 +00:00
openhands
a18512a644 fix: Stale JSDoc in navigateToStakePage refers to '/stake' not '/app/stake' (#509) 2026-03-13 10:37:14 +00:00
openhands
659044e2d1 fix: claude subprocess not killed on INT/TERM in cleanup trap (#530)
Track CLAUDE_PID before launching the claude subprocess so cleanup()
can kill it before reverting Anvil state. Running claude via `&` +
`wait` lets the trap fire immediately on INT/TERM, killing the
subprocess and preventing it from making calls against an
already-reverted chain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:48:34 +00:00
openhands
2ae07e7a49 fix: $FLOOR_BEFORE/$FLOOR_AFTER unquoted inside python3 -c string (#531) 2026-03-13 08:28:26 +00:00
openhands
6924cb03f3 fix: Protocol Mechanics section in agent prompt still exposes ethPerToken formula (#550) 2026-03-13 07:47:35 +00:00
openhands
85503f9c5c fix: remove cast to-dec that broke cumulativeVolume check in call_recenter
cast call with a typed '(uint256)' selector returns output like
'140734553600000 [1.407e14]' — the numeric value followed by a
bracketed scientific-notation annotation.  The cast to-dec added in the
previous review-fix commit failed on this annotated string and fell back
to echo "0", making call_recenter() always skip the VWAP-already-
bootstrapped guard and attempt the real recenter() call, which then
reverted with "amplitude not reached".

Fix: drop the cast to-dec normalisation.  A plain != "0" string check
is sufficient because cast returns "0" (no annotation) for the zero
case and any non-zero annotated string is also != "0".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 01:48:58 +00:00
openhands
38bc0f7057 fix: address AI review findings on VWAP bootstrap PR
SPDX license:
- Restore GPL-3.0-or-later SPDX header to DeployBase.sol (removed by
  the em-dash sed fix in an earlier commit).

SeedSwapper deduplication:
- Extract SeedSwapper into onchain/script/DeployCommon.sol — a single
  canonical definition shared by both deploy scripts.  This eliminates
  duplicate Foundry artifacts (previously both DeployLocal.sol and
  DeployBase.sol produced a SeedSwapper artifact, causing ambiguity for
  verification and coverage tools).
- Remove inline SeedSwapper and redundant IWETH9 import from
  DeployLocal.sol and DeployBase.sol; add `import "./DeployCommon.sol"`.

SeedSwapper hardening (in DeployCommon.sol):
- Replace magic-literal price sentinels with named constants
  SQRT_PRICE_LIMIT_MIN / SQRT_PRICE_LIMIT_MAX.
- Wrap both weth.transfer() calls with require() so a non-standard
  WETH9 false-return is caught rather than silently ignored.
- Add post-swap WETH sweep in executeSeedBuy(): if the price limit is
  reached before the full input is spent, the residual WETH balance is
  returned to `recipient` instead of being stranded in the contract.

bootstrap-common.sh:
- Normalise cumulativeVolume output through `cast to-dec` before the
  string comparison, guarding against a future change in cast output
  format (decimal vs hex).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 00:12:39 +00:00
openhands
e0b61c1b88 fix: surface forge script errors in CI bootstrap log
run_forge_script() was piping all output to LOG_FILE (which is /dev/null
in CI), so forge failures were completely silent.  Capture output to a
temp file and print to stderr on failure so the CI log shows the actual
error message.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:27:23 +00:00
openhands
73a80ead0b fix: add --tc DeployLocal to forge script invocations
Adding SeedSwapper alongside DeployLocal in the same .sol file caused
forge to error "Multiple contracts in the target path" when no --tc flag
was specified, silently failing the CI bootstrap step.

Add --tc DeployLocal to all forge script invocations of DeployLocal.sol:
  - scripts/bootstrap-common.sh  (CI / local bootstrap)
  - tools/deploy-optimizer.sh    (manual deploy tool)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:12:25 +00:00
openhands
3a17404529 fix: skip CI bootstrap recenter when VWAP already seeded by deploy script
DeployLocal.sol now calls recenter() twice during the VWAP bootstrap
sequence (issue #567 fix).  The second recenter leaves ANCHOR positions
at the post-seed-buy tick, so the CI bootstrap's subsequent call_recenter()
failed with "amplitude not reached" (currentTick == anchorCenterTick,
amplitude = 0 < 400).

Fix: before calling recenter(), check cumulativeVolume().  If it is
already > 0, the deploy script has placed positions and bootstrapped
VWAP -- skip the redundant recenter rather than failing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 21:46:00 +00:00
openhands
b902b89e3b fix: address review findings — CREATE2 guard, transition test, docs
- LiquidityManager.setFeeDestination: add CREATE2 bypass guard — also
  blocks re-assignment when the current feeDestination has since acquired
  bytecode (was a plain address when set, contract deployed to it later)
- LiquidityManager.setFeeDestination: expand NatSpec to document the
  EOA-mutability trade-off and the CREATE2 guard explicitly
- Test: add testSetFeeDestinationEOAToContract_Locks covering the
  realistic EOA→contract transition (the primary lock-activation path)
- red-team.sh: add comment that DEPLOYER_PK is Anvil account-0 and must
  only be used against a local ephemeral Anvil instance
- ARCHITECTURE.md: document feeDestination conditional-lock semantics and
  contrast with Kraiken's strictly set-once liquidityManager/stakingPool

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:13:50 +00:00
openhands
512640226b fix: fix: Conditional lock on feeDestination — lock when set to contract (#580) (#580)
- Add `feeDestinationLocked` bool to LiquidityManager
- Replace one-shot setter with conditional trapdoor: EOAs may be set
  repeatedly, but setting a contract address locks permanently
- Remove `AddressAlreadySet` error (superseded by the new lock mechanic)
- Replace fragile SLOT7 storage hack in red-team.sh with a proper
  `setFeeDestination()` call using the deployer key
- Update tests: replace AddressAlreadySet test with three new tests
  covering EOA multi-set, contract lock, and locked revert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 16:13:44 +00:00
johba
514a55a1ac Merge pull request 'fix: Backtesting: replay red-team attack sequences against optimizer candidates (#536)' (#565) from fix/issue-536 into master 2026-03-11 19:24:27 +01:00
openhands
58729b98b4 fix: fix: strip cast formatted annotations from red-team.sh (#577)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 10:19:14 +00:00
openhands
0834433db1 Fix PR #540 review findings
Critical fixes:
- LmTotalEth.s.sol: Fix imports to use @aperture/uni-v3-lib/ (lines 8-9)
- red-team.sh: Update memory regex to match lm.?eth pattern (line 266)

Additional improvements:
- red-team.sh: Update adversary balance claim to ~9000 ETH (after funding LM)
- red-team.sh: Add --no-color to forge invocation + emptiness guard
- red-team.sh: Document feeDestination storage slot 7 fragility

Tested:
- Regex pattern matches all expected formats (lm_eth, lmeth, LM-ETH, etc.)
- Import paths align with remappings.txt
2026-03-11 06:28:02 +00:00
openhands
0ddc1ccd80 fix: Red-team: replace ethPerToken with exact total-LM-ETH metric (#539)
Replace the ethPerToken metric (free balance / adjusted supply) with total
LM ETH (free + WETH + position-locked) using a forge script with exact
Uni V3 integer math. Collapses 4+ RPC calls and Python float approximation
into a single forge script call using LiquidityAmounts + TickMath.

Also updates red-team prompt, report format, memory extraction, and adds
roadmap items for #536-#538 (backtesting pipeline, Push3 evolution).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 06:28:02 +00:00
openhands
c8453f6a33 fix: Backtesting: replay red-team attack sequences against optimizer candidates (#536)
- Add AttackRunner.s.sol: structured forge script that reads attack ops from a
  JSONL file (ATTACK_FILE env), executes them against the local Anvil deployment,
  and emits full state snapshots (tick, positions, VWAP, optimizer output,
  adversary balances) as JSON lines after every recenter and at start/end.

- Add 5 canonical attack files in onchain/script/backtesting/attacks/:
  * il-crystallization-15.jsonl  — 15 buy-recenter cycles + sell (extraction)
  * il-crystallization-80.jsonl  — 80 buy-recenter cycles + sell (extraction)
  * fee-drain-oscillation.jsonl  — buy-recenter-sell-recenter oscillation
  * round-trip-safe.jsonl        — 20 full round-trips (regression: safe)
  * staking-safe.jsonl           — staking manipulation (regression: safe)

- Add scripts/harb-evaluator/export-attacks.py: parses red-team-stream.jsonl
  for tool_use Bash blocks containing cast send commands and converts them to
  AttackRunner-compatible JSONL (buy/sell/recenter/stake/unstake/mint_lp/burn_lp).

- Update scripts/harb-evaluator/red-team.sh: after each agent run, automatically
  exports the attack sequence via export-attacks.py and replays it with
  AttackRunner to capture structured snapshots in tmp/red-team-snapshots.jsonl.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 02:08:06 +00:00
openhands
816b211c2b fix: address review findings in red-team memory (#528)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 10:00:56 +00:00
openhands
c1db4cb93e fix: Red-team memory: persistent cross-run learning for adversarial agent (#528)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 09:23:37 +00:00