fix: mint_lp and burn_lp not soft-failing in attack execution (#630)

Wrap mint_lp and burn_lp ops in _executeOp with try/catch to match
the soft-fail pattern used by buy, sell, stake, and unstake. Replace
burn_lp's require() with a soft return for out-of-range index validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
openhands 2026-03-20 00:23:58 +00:00
parent 0446facb62
commit 37905a29b2

View file

@ -516,7 +516,7 @@ contract FitnessEvaluator is Test {
vm.prank(advAddr);
// Track the returned tokenId so burn_lp can reference it by 1-based index,
// making attack files fork-block-independent (NPM tokenIds depend on fork tip).
(uint256 mintedTokenId,,,) = INonfungiblePositionManager(NPM_ADDR).mint(
try INonfungiblePositionManager(NPM_ADDR).mint(
INonfungiblePositionManager.MintParams({
token0: t0,
token1: t1,
@ -530,22 +530,20 @@ contract FitnessEvaluator is Test {
recipient: advAddr,
deadline: block.timestamp + 3600
})
);
_mintedNpmTokenIds.push(mintedTokenId);
) returns (uint256 mintedTokenId, uint128, uint256, uint256) {
_mintedNpmTokenIds.push(mintedTokenId);
} catch { }
} else if (_eq(op, "burn_lp")) {
// .tokenId in the attack file is a 1-based index into _mintedNpmTokenIds
// (positions created by mint_lp ops in this run), not a raw NPM tokenId.
// This mirrors the stake/unstake index pattern and avoids fork-block sensitivity.
uint256 tokenIndex = vm.parseJsonUint(line, ".tokenId");
require(
tokenIndex >= 1 && tokenIndex <= _mintedNpmTokenIds.length,
"FitnessEvaluator: burn_lp tokenId out of range (must be 1-based index of a prior mint_lp op)"
);
if (tokenIndex < 1 || tokenIndex > _mintedNpmTokenIds.length) return;
uint256 tokenId = _mintedNpmTokenIds[tokenIndex - 1];
(,,,,,, , uint128 liquidity,,,,) = INonfungiblePositionManager(NPM_ADDR).positions(tokenId);
if (liquidity == 0) return;
vm.startPrank(advAddr);
INonfungiblePositionManager(NPM_ADDR).decreaseLiquidity(
try INonfungiblePositionManager(NPM_ADDR).decreaseLiquidity(
INonfungiblePositionManager.DecreaseLiquidityParams({
tokenId: tokenId,
liquidity: liquidity,
@ -553,15 +551,16 @@ contract FitnessEvaluator is Test {
amount1Min: 0,
deadline: block.timestamp + 3600
})
);
INonfungiblePositionManager(NPM_ADDR).collect(
INonfungiblePositionManager.CollectParams({
tokenId: tokenId,
recipient: advAddr,
amount0Max: type(uint128).max,
amount1Max: type(uint128).max
})
);
) {
try INonfungiblePositionManager(NPM_ADDR).collect(
INonfungiblePositionManager.CollectParams({
tokenId: tokenId,
recipient: advAddr,
amount0Max: type(uint128).max,
amount1Max: type(uint128).max
})
) { } catch { }
} catch { }
vm.stopPrank();
}
// Unknown ops are silently ignored (mirrors AttackRunner behaviour).