# Anyone can call LamboRebalanceOnUniwap.sol::rebalance() function with any arbitrary value, leading to rebalancing goal i.e. (1:1 peg) unsuccessful.

Permissionless rebalance() in LamboRebalanceOnUniwap accepts arbitrary directionMask/amountIn/amountOut, letting any caller unbalance the Uniswap pool instead of restoring the 1:1 peg.

- Payout: Contest reward
- Severity: high
- Program: Lambo.win
- Credited: orangesantra
- Disclosed: 2025-02-03
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2024-12-lambowin#h-04
- Library page: https://bugbountylibrary.com/r/c4%3A2024-12-lambowin%3AH-04
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** LamboRebalanceOnUniwap.sol rebalance() on Uniswap V3 pool
**Root cause:** rebalance() is externally callable and never validates that directionMask is 0 or 1<<255 nor that amountIn/amountOut match previewRebalance(), so arbitrary flashloan parameters are accepted.
**Steps:**
1. Call `previewRebalance()` to get legit directionMask, amountIn, amountOut.
2. As any EOA, call `lamboRebalance.rebalance(directionMask, amountIn + 100 ether, amountOut + 100 ether)` with inflated amounts.
3. Observe pool WETH/VETH balances diverge (350165.../552734...) instead of converging to ~1:1.
4. Call `extractProfit(address(this), WETH)` to realize profit from the mis-rebalance.
**How found:** Reading rebalance() revealed no access control or parameter validation; author hypothesized arbitrary args would cause wrong-size flashloans and tested by replaying rebalance() from a fresh signer with inflated amounts, comparing pool balances to the legit run.
**Exploitation:** Any unprivileged address calls rebalance() with arbitrary directionMask/amountIn/amountOut, triggering a flashloan of the wrong size that moves the pool away from the peg rather than toward it; caller then extracts profit via extractProfit().
**Insight:** For permissionless 'keeper' functions that take precomputed parameters, check whether the contract re-derives or validates those params on-chain; if previewRebalance() output is trusted blindly, anyone can feed skewed values to grief the invariant.
