fix: fix: il-crystallization-80 attack times out (153 steps) (#597)
Add `buy_recenter_loop` batch op to AttackRunner — executes N×(buy→recenter) cycles in a single Solidity loop, emitting snapshots after each recenter. Rewrite il-crystallization-80.jsonl from 153 individual JSONL steps to 2 lines using the new op with count=80, matching the intended attack name. Also corrects the cycle count from 76 (previous file) to the intended 80. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4258045c8c
commit
fe385fb010
2 changed files with 56 additions and 158 deletions
|
|
@ -127,9 +127,12 @@ interface IUniswapV3Factory {
|
|||
* DEPLOYMENTS_FILE Path to deployments JSON (default: deployments-local.json)
|
||||
*
|
||||
* Supported operations:
|
||||
* buy Swap WETH→KRK via SwapRouter. Fields: amount (wei string), token (ignored, WETH assumed)
|
||||
* sell Swap KRK→WETH via SwapRouter. Fields: amount (wei string or "all"), token (ignored)
|
||||
* recenter Call LM.recenter() via recenterAccess account. Emits a snapshot.
|
||||
* buy Swap WETH→KRK via SwapRouter. Fields: amount (wei string), token (ignored, WETH assumed)
|
||||
* sell Swap KRK→WETH via SwapRouter. Fields: amount (wei string or "all"), token (ignored)
|
||||
* recenter Call LM.recenter() via recenterAccess account. Emits a snapshot.
|
||||
* buy_recenter_loop Batch N×(buy→recenter) cycles in a single op. Fields: count (uint), amount (wei string).
|
||||
* Emits a snapshot after each successful recenter. Avoids per-step forge overhead for
|
||||
* high-cycle attacks that would otherwise time out (e.g. il-crystallization-80).
|
||||
* stake Call Stake.snatch(). Fields: amount (wei string), taxRateIndex (raw taxRate value passed to Stake.snatch)
|
||||
* unstake Call Stake.exitPosition(). Fields: positionId
|
||||
* mint_lp Add LP via NPM. Fields: tickLower, tickUpper, amount0 (wei string), amount1 (wei string)
|
||||
|
|
@ -179,6 +182,9 @@ contract AttackRunner is Script {
|
|||
/// recenter_is_up=null on the initial snapshot (before any recenter has occurred)
|
||||
/// rather than the ambiguous false default.
|
||||
bool internal _hasRecentered;
|
||||
/// @dev Snapshot sequence counter. Shared between run() and batch ops like
|
||||
/// buy_recenter_loop that emit their own snapshots internally.
|
||||
uint256 internal _seq;
|
||||
|
||||
// ─── Entry point ─────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -207,18 +213,18 @@ contract AttackRunner is Script {
|
|||
|
||||
// Execute attack operations, snapshotting after each recenter.
|
||||
string memory attackFile = vm.envString("ATTACK_FILE");
|
||||
uint256 seq = 1;
|
||||
_seq = 1;
|
||||
string memory line = vm.readLine(attackFile);
|
||||
while (bytes(line).length > 0) {
|
||||
bool isRecenter = _execute(line);
|
||||
if (isRecenter) {
|
||||
_logSnapshot(seq++);
|
||||
_logSnapshot(_seq++);
|
||||
}
|
||||
line = vm.readLine(attackFile);
|
||||
}
|
||||
|
||||
// Final state snapshot.
|
||||
_logSnapshot(seq);
|
||||
_logSnapshot(_seq);
|
||||
}
|
||||
|
||||
// ─── Setup ────────────────────────────────────────────────────────────────
|
||||
|
|
@ -272,6 +278,8 @@ contract AttackRunner is Script {
|
|||
_executeMintLp(line);
|
||||
} else if (_eq(op, "burn_lp")) {
|
||||
_executeBurnLp(line);
|
||||
} else if (_eq(op, "buy_recenter_loop")) {
|
||||
_executeBuyRecenterLoop(line);
|
||||
} else if (_eq(op, "mine")) {
|
||||
uint256 blocks = vm.parseJsonUint(line, ".blocks");
|
||||
vm.roll(block.number + blocks);
|
||||
|
|
@ -298,6 +306,47 @@ contract AttackRunner is Script {
|
|||
vm.stopBroadcast();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Batch buy→recenter loop. Executes `count` cycles of (buy `amount` WETH → recenter),
|
||||
* emitting a snapshot after each successful recenter. Using a single op instead of
|
||||
* individual JSONL lines eliminates per-step forge-script dispatch overhead, allowing
|
||||
* high-cycle attacks (e.g. 80 cycles) to complete within the fitness evaluation budget.
|
||||
*
|
||||
* Fields: count (uint), amount (wei string)
|
||||
*/
|
||||
function _executeBuyRecenterLoop(string memory line) internal {
|
||||
uint256 count = vm.parseJsonUint(line, ".count");
|
||||
uint256 amount = vm.parseUint(vm.parseJsonString(line, ".amount"));
|
||||
|
||||
for (uint256 i = 0; i < count; i++) {
|
||||
// Buy WETH→KRK.
|
||||
vm.startBroadcast(ADV_PK);
|
||||
ISwapRouter02(SWAP_ROUTER).exactInputSingle(
|
||||
ISwapRouter02.ExactInputSingleParams({
|
||||
tokenIn: WETH,
|
||||
tokenOut: krkAddr,
|
||||
fee: POOL_FEE,
|
||||
recipient: advAddr,
|
||||
amountIn: amount,
|
||||
amountOutMinimum: 0,
|
||||
sqrtPriceLimitX96: 0
|
||||
})
|
||||
);
|
||||
vm.stopBroadcast();
|
||||
|
||||
// Recenter.
|
||||
vm.startBroadcast(RECENTER_PK);
|
||||
try ILM(lmAddr).recenter() returns (bool isUp) {
|
||||
_lastRecenterIsUp = isUp;
|
||||
_hasRecentered = true;
|
||||
_logSnapshot(_seq++);
|
||||
} catch {
|
||||
console.log("recenter: skipped (amplitude not reached)");
|
||||
}
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Swap KRK→WETH via SwapRouter02. amount="all" uses full adversary KRK balance.
|
||||
function _executeSell(string memory line) internal {
|
||||
string memory amtStr = vm.parseJsonString(line, ".amount");
|
||||
|
|
|
|||
|
|
@ -1,153 +1,2 @@
|
|||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy","amount":"100000000000000000000","token":"WETH"}
|
||||
{"op":"recenter"}
|
||||
{"op":"buy_recenter_loop","count":80,"amount":"100000000000000000000"}
|
||||
{"op":"sell","amount":"all","token":"KRK"}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue