# The repaying action in `BBLeverage.sellCollateral` function pulls YieldBox shares of asset from wrong address

BBLeverage.sellCollateral passes the user as the repayer to _repay, pulling the user's YieldBox shares again while the contract's already-collected shares stay stuck.

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

**Target:** BBLeverage.sellCollateral / BBLendingCommon._repay (Solidity, YieldBox)
**Root cause:** sellCollateral deposits collateral into YieldBox and receives the shares itself, but calls _repay(from, from, ...) with the user as the withdraw source instead of address(this), so _repay withdraws the user's shares a second time.
**Steps:**
1. User calls BBLeverage.sellCollateral; contract sells collateral and deposits asset into YieldBox, receiving shares.
2. Code path: `if (shareOwed <= shareOut) _repay(from, from, partOwed); else _repay(from, from, partOut);`
3. _repay executes `yieldBox.withdraw(assetId, from, address(this), amount, 0)`, pulling the user's shares again.
4. Contract's own collected shares remain stranded; user loses funds up to their balance/allowance.
**How found:** Manual code review of sellCollateral's repayment path, noticing the from parameter passed to _repay despite the contract already holding the asset shares from the preceding deposit.
**Exploitation:** Any user invoking sellCollateral with sufficient YieldBox share balance and allowance to the market has their shares withdrawn twice: once implicitly via the contract's collected shares (stuck) and once directly from their account by _repay.
**Insight:** In leverage/collateral-sale flows, trace who actually holds the shares after the deposit step and verify the repayer argument matches that holder; a mismatched `from` silently double-charges users.
