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
This commit is contained in:
openhands 2026-03-10 20:01:12 +00:00
parent 0ddc1ccd80
commit 0834433db1
2 changed files with 14 additions and 9 deletions

View file

@ -5,8 +5,8 @@ import "@uniswap-v3-core/interfaces/IUniswapV3Factory.sol";
import "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
import "forge-std/Script.sol";
import "uni-v3-lib/LiquidityAmounts.sol";
import "uni-v3-lib/TickMath.sol";
import "@aperture/uni-v3-lib/LiquidityAmounts.sol";
import "@aperture/uni-v3-lib/TickMath.sol";
interface ILM {
function positions(uint8 stage) external view returns (uint128 liquidity, int24 tickLower, int24 tickUpper);

View file

@ -128,7 +128,10 @@ log " recenterAccess granted"
# ── 3b. Override feeDestination to LM itself (fees accrue as liquidity) ────────
# feeDestination is a one-shot setter, so we override storage directly.
# Slot 7 contains feeDestination (packed with other data in upper bytes).
# Slot 7 contains feeDestination (address, lower 20 bytes).
# Upper bytes of slot 7 contain other packed state variables.
# NOTE: This is fragile — storage layout changes break this. Consider making
# feeDestination mutable or using Foundry's vm.store with slot lookup.
log "Setting feeDestination to LM ($LM) ..."
SLOT7=$("$CAST" storage "$LM" 7 --rpc-url "$RPC_URL" | tr -d '[:space:]')
UPPER=${SLOT7:0:26}
@ -191,12 +194,14 @@ trap cleanup EXIT INT TERM
# Uses a forge script with exact Uni V3 integer math (LiquidityAmounts + TickMath)
# instead of multiple cast calls + Python float approximation.
compute_lm_total_eth() {
local output
local output result
output=$(LM="$LM" WETH="$WETH" POOL="$POOL" \
/home/debian/.foundry/bin/forge script script/LmTotalEth.s.sol \
--rpc-url "$RPC_URL" --root "$REPO_ROOT/onchain" 2>&1)
--rpc-url "$RPC_URL" --root "$REPO_ROOT/onchain" --no-color 2>&1)
# forge script prints "== Logs ==" then " <value>" — extract the number
echo "$output" | awk '/^== Logs ==/{getline; gsub(/^[[:space:]]+/,""); print; exit}'
result=$(echo "$output" | awk '/^== Logs ==/{getline; gsub(/^[[:space:]]+/,""); print; exit}')
[[ -n "$result" && "$result" =~ ^[0-9]+$ ]] || die "Failed to read LM total ETH (forge output: $output)"
echo "$result"
}
# ── Helper: extract strategy findings from stream-json and append to memory ────
@ -258,7 +263,7 @@ for text in texts:
if current:
# Capture floor readings — take the last match in the block (most recent value)
floor_matches = list(re.finditer(r"(?:floor|ethPerToken)[^\d]*?(\d{4,})\s*(?:wei)?", text, re.IGNORECASE))
floor_matches = list(re.finditer(r"(?:floor|ethPerToken|lm.?eth)[^\d]*?(\d{4,})\s*(?:wei)?", text, re.IGNORECASE))
if floor_matches:
current["lm_eth_after"] = int(floor_matches[-1].group(1))
@ -404,7 +409,7 @@ CAST binary: /home/debian/.foundry/bin/cast
### Adversary — Anvil account 8 (your main account)
- Address: ${ADV_ADDR}
- Private key: ${ADV_PK}
- Balance: 10 000 ETH, 0 KRK
- Balance: ~9000 ETH (10k minus 1000 ETH used to fund LM), 0 KRK
### Recenter caller — Anvil account 2
- Address: ${RECENTER_ADDR}
@ -600,7 +605,7 @@ SNAP=\$(/home/debian/.foundry/bin/cast rpc anvil_snapshot --rpc-url http://local
## Rules
1. You have 10 000 ETH. Start by wrapping some if you need WETH for swaps.
1. You have ~9000 ETH (after funding LM with 1000 ETH). Start by wrapping some if you need WETH for swaps.
2. Your goal is to make the LM's total ETH DECREASE vs the starting value (${LM_ETH_BEFORE} wei).
3. Try at least 3 distinct strategies. After each attempt:
a. Run the total LM ETH check command above.