Skip to content

fix(L3): cap composition slippage + freshness gate (L7 analyzed) - #19

Merged
jayeshy14 merged 1 commit into
mainfrom
fix/execution-mev-bounds
Jul 20, 2026
Merged

fix(L3): cap composition slippage + freshness gate (L7 analyzed)#19
jayeshy14 merged 1 commit into
mainfrom
fix/execution-mev-bounds

Conversation

@jayeshy14

Copy link
Copy Markdown
Owner

Category PR for the audit's execution MEV/slippage bounds (L3, L7). Branched off main, targets main.

L3 — rebalanceComposition

  • The caller-supplied maxSlippageBps is clamped to a 5% ceiling (MAX_COMPOSITION_SLIPPAGE_BPS), so a keeper can no longer drive minOut toward zero.
  • The whole function is gated on wstethBuyAllowed(): the buy branch already required it; the sell branch did not and could trim at a mispriced/stale mark. Composition maintenance now pauses during a depeg or feed outage; the keeper retries when healthy.

L7 — analyzed, already mitigated (no code change beyond documentation)

The audit suggested a sqrtPriceLimitX96 pool-impact cap on the emergency swap. On analysis, for an exact-input single-hop swap the oracle-anchored amountOutMinimum already bounds the output, and therefore the extractable sandwich value, to the slippage bound: the swap delivers >= minOut or reverts. A price limit would only introduce exact-input partial-fill semantics (leftover tokenIn to account for) without tightening that bound, and a mis-set limit could brick swaps. So it is intentionally omitted; the _swap comment records the reasoning. (Chunked/partial-fill execution for large deltas remains the deferred L6 item.)

Tests

2 regressions: 100%-slippage ask still misses minOut on both tiers (clamp works); sell branch no-ops during a depeg. Suite 134 -> 136; 9/9 fork tests green.

- L3: rebalanceComposition clamps the caller-supplied maxSlippageBps to
  a 5% ceiling so a keeper can no longer drive minOut toward zero, and
  the whole function is gated on wstethBuyAllowed() so neither branch
  trims at a mispriced/stale mark (the buy branch already required it;
  the sell branch did not). Composition maintenance pauses during a
  depeg/outage and the keeper retries when healthy.
- L7: assessed and documented as already-mitigated. For an exact-input
  single-hop swap the oracle-anchored amountOutMinimum already bounds
  the output (hence extractable sandwich value) to the slippage bound;
  a sqrtPriceLimitX96 would only add partial-fill semantics without
  tightening that bound, so it is intentionally omitted. Comment on
  _swap records the reasoning.

2 regression tests (slippage clamp misses on both tiers; sell branch
no-ops during depeg). 134 -> 136; 9 fork tests green.
@jayeshy14
jayeshy14 merged commit 2bf2ded into main Jul 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant