Skip to content

Audit/v3 lp fixes - #224

Open
razww wants to merge 6 commits into
feature/v3-lpfrom
audit/v3-lp-fixes
Open

Audit/v3 lp fixes#224
razww wants to merge 6 commits into
feature/v3-lpfrom
audit/v3-lp-fixes

Conversation

@razww

@razww razww commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

📄 Description

Briefly describe the purpose of this PR. Include context and what it solves.

🧠 Rationale

Explain the motivation and necessity of the change. Why was this needed? What problem does it solve?

🧪 Example / Testing

If applicable, provide test scenarios, CLI commands, or example contract interactions.

🧬 Changes Summary

Notable changes:

  • add each change in a bullet point here
  • ...

razww and others added 5 commits July 29, 2026 16:23
Adding CLAMM liquidity is the one operation that must not be
permissionless: a manipulated pool spot lets a caller force a bad-price
re-add and sandwich it. Remove collectAndCompound from every
permissionless user flow (deposit, withdraw, withdrawShares,
supplyShares, redeemShares) and make compound() BOT-gated with a
caller-supplied slippage floor (amount0Min/amount1Min forwarded to
increaseLiquidity, previously hardcoded 0/0). Fee re-deployment now
happens only via compound() or rebalance, both BOT-gated.

No valuation regression: positionAmountsAt already simulates pending
fees, so the health-check / oracle valuation stays fee-complete without
an inline compound; removeLiquidity still collects the exiter's pro-rata
fees. Counter-tests: compound is onlyBot; a deposit no longer deploys
idle as liquidity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…comments with BOT-gating

Remove finding-ID / firm / process labels from shipped comments (no
logic change): C-1, H02/Issue_04, M01, finding C/C4/D, Codex adv, AUDIT
NOTE, "audit PR". Also correct two oracle @dev docstrings that still
claimed peek reverts on zero total value (it now floors a dust position),
and update the remaining compound comments that described the old
permissionless model (compounding is now BOT-gated; user flows no longer
compound).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ceil-round amount0Used/amount1Used in the subsequent-deposit branch so the
depositor pays >= their pro-rata share while shares still round down — every
sub-wei rounding now favors existing holders and can never dilute the pool.
Both legs stay <= the desired input (frac <= dᵢ·WAD/tᵢ), so no over-consumption.

Also strip internal finding-id / auditor-name references from the V3 provider
test comments (no behavior change; one test renamed accordingly).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The rebase onto master auto-merged two copies of deposit() into IStakeManager
(and its mock) at different line positions — no textual conflict, but a
duplicate function definition that fails to compile. Remove the redundant
declaration; the interface keeps a single deposit()/instantWithdraw().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror Liquidator.sol's fund-pool integration onto V3Liquidator:
- fundSource (LiquidationVault) + reflowBlacklist storage, appended (UUPS-safe).
- initialize takes a fundSource arg (0 = legacy); set directly (contract check only —
  vault registration necessarily happens after the proxy exists) + setFundSource for later.
- setFundSource validates the vault has registered this liquidator; setReflowBlacklist.
- withdrawERC20/ETH gate relaxed to MANAGER or fundSource so the vault's collect* pulls.
- onMoolahLiquidate pulls the exact repayment shortfall from the vault (local balance first).
- liquidate/flashLiquidate/redeemV3Shares reflow the residue (loanToken + redeemed legs +
  native) to the vault; the transfer-restricted V3 share collateral is never reflowed.
- liquidate now routes a non-redeeming callback so the pool can fund it, and emits V3Liquidation.

fundSource == 0 preserves the exact legacy pre-funded behavior. Counter-tests cover
initialize+setFundSource validation, withdraw gate, vault-funded liquidate, and residue reflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@hashdit-bot

hashdit-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

Pull Request Review

This Solidity DeFi PR integrates V3Liquidator with a shared LiquidationVault, allowing repayment funding and automatic reflow of liquidation proceeds. It also makes compounding BOT-only with caller-provided slippage bounds, removes inline compounding from user flows, adjusts deposit rounding, and adds integration/regression tests.

Sensitive Content

No sensitive content detected.

Security Issues

🟡 [MEDIUM] Withdrawal access control is relaxed

File: src/liquidator/V3Liquidator.sol
The existing withdrawERC20(address,uint256) and withdrawETH(uint256) functions previously required onlyRole(MANAGER). They now also authorize whichever address is stored in fundSource, allowing that contract to withdraw all ERC-20 or native assets held by the liquidator. This appears intentional for vault collection, but it expands a highly privileged asset-transfer boundary and makes the safety of these functions dependent on correct fundSource configuration and continued trust in that contract.
Recommendation: Confirm this relaxation is intended. Consider granting a dedicated withdrawal role to the vault, validating registration whenever fundSource changes—including deployment procedures—and ensuring revocation or replacement of a compromised vault can be performed promptly.


Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits.

…wap leg

In onMoolahLiquidate the native (BNB/ETH) leg was sold with
call{ value: actualRedeemedAmount }, but the bot builds the 1inch swapData
off-chain against a pre-estimated input. Native swaps require msg.value to
equal the amount encoded in the calldata, so the variable actual amount
mismatches and the aggregator reverts — failing the whole flash liquidation.

Send the pre-agreed minTokenNAmt (the value the swapData was built for) as
msg.value instead; redeemShares guarantees actual >= min so the balance always
covers it, and the leftover stays to be wrapped/reflowed. Mirrors the
smart-collateral path in Liquidator.sol. The ERC-20 leg is unaffected (approve
is a ceiling). Counter-test uses a strict aggregator mock (msg.value == amountIn);
V3LiquidatorEth test updated to set minToken1Amt to the native swap input.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@hashdit-bot

hashdit-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

Pull Request Review

This Solidity DeFi PR integrates V3Liquidator with a shared LiquidationVault, enabling repayment funding and residual asset reflow while correcting native-token swap value handling. It also makes LP compounding BOT-gated with caller-supplied slippage limits, removes inline compounding from user flows, and adjusts deposit rounding and related tests.

Sensitive Content

No sensitive content detected.

Security Issues

🟡 [MEDIUM] Access control is relaxed for withdrawal functions

File: src/liquidator/V3Liquidator.sol
The existing withdrawERC20(address,uint256) and withdrawETH(uint256) functions no longer use onlyRole(MANAGER). Their authorization now also permits the configured fundSource to withdraw the liquidator’s entire ERC-20 and native-asset balances. This intentionally broadens access and makes the security of liquidator funds dependent on the configured vault contract; please confirm this relaxation is intended.
Recommendation: Confirm that the fundSource must have unrestricted pull rights. Prefer a narrowly scoped vault collection interface or explicit per-token/per-amount authorization, and ensure initialization and configuration procedures only assign a fully trusted, correctly registered vault.


Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits.

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