# The last borrowed asset will not be collateralized and the user may be liquidated due to insufficient collateral

Rubicon Position leverage loop leaves the final swapped asset uncollateralized, so a small price move liquidates the user despite their collateral.

- Payout: Contest reward
- Severity: high
- Program: Rubicon
- Credited: cccz
- Disclosed: 2025-02-17
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-04-rubicon-findings/issues/423
- Library page: https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AH-15
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:liquidation

**Target:** Position.sol leverage openPosition/_borrowLoop
**Root cause:** The recursive borrow loop supplies collateral then borrows/swaps, but the asset bought in the final iteration is never supplied back as collateral, so it sits uncollateralized in the contract.
**Steps:**
1. Call `Position.buyAllAmountWithLeverage(asset, quote, amount, leverage)` with 1e8 WBTC and 1.7x leverage.
2. `_borrowLoop` supplies 1e8 WBTC, borrows USDC worth 0.7e8 WBTC, swaps to 0.7e8 WBTC.
3. Loop ends without supplying the 0.7e8 WBTC back as collateral.
4. Observe `borrowedAmount1 = 630000` while `testCoin balance in position = 692923770693000000` remains uncollateralized.
**How found:** Code reading of the recursive borrow loop: noticed the loop supplies collateral at the start of each iteration but the last iteration's swapped asset is never re-supplied before the loop exits.
**Exploitation:** User opens a leveraged long; the final swapped asset is not collateralized, so a slight adverse price move triggers liquidation of the position.
**Insight:** In recursive leverage loops, check whether the output of the final iteration is re-collateralized; the loop boundary is where accounting gaps hide.
