# Operation residual is lost for the user of BBLeverage's and SGLLeverage's `sellCollateral()`

BBLeverage/SGLLeverage sellCollateral leaves excess sale proceeds on the contract instead of refunding the user, letting any attacker skim the residual.

- Payout: Contest reward
- Severity: medium
- Program: Tapioca
- Credited: cergyk
- Disclosed: 2024-02-14
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-02-tapioca-judging/issues/144
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-33
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:access-control vuln:accounting-error vuln:business-logic

**Target:** BBLeverage/SGLLeverage sellCollateral in Tapioca-bar
**Root cause:** sellCollateral deposits all swap proceeds back into the market contract but only repays the debt, never refunding the shareOut-shareOwed residual to `from`; the excess is unaccounted in system accounting.
**Steps:**
1. Call `sellCollateral(from, share, data)` on BBLeverage/SGLLeverage with a share large enough that swap output exceeds debt.
2. Observe `leverageExecutor.getAsset` returns full proceeds to the market contract.
3. Contract deposits proceeds via `yieldBox.depositAsset(collateralId, address(this), address(this), 0, shareOut)` and repays only `partOwed`.
4. Residual `shareOut - shareOwed` remains on contract balance, unaccounted.
5. Attacker back-runs and calls `_addTokens` with `skim=true` to withdraw the stranded balance.
**How found:** Code review of sellCollateral flow: noticed proceeds are deposited to `address(this)` rather than `from` (differs from old AssetToRethLeverageExecutor snapshot), and that no refund of shareOut-shareOwed occurs, then connected to the existing skim mechanism.
**Exploitation:** Back-run the victim's sellCollateral transaction and invoke the skim path (`_addTokens` with skim=true) to pull the unaccounted residual asset balance from the market contract.
**Insight:** When a function swaps and repays in one call, check whether the surplus output is refunded to the caller or left on contract balance; any stranded balance becomes skimmable if the protocol exposes a skim/donate path.
