# `BuyUSSDSellCollateral()` always sells 0 amount if need to sell part of collateral

Rounding in BuyUSSDSellCollateral's amountToSellUnits formula truncates to 0, so partial collateral sales never execute, blocking USSD peg rebalancing.

- Payout: Contest reward
- Severity: medium
- Program: USSD
- Credited: J4de
- Disclosed: 2023-05-15
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-05-USSD-judging/issues/656
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-05-USSD%3AM-8
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:precision-loss

**Target:** USSDRebalancer.sol BuyUSSDSellCollateral / UniV3SwapInput
**Root cause:** amountToSellUnits divides by collateralval (already scaled by 1e18) and again by 1e18, so the ratio truncates to zero whenever selling only a fraction of collateral.
**Steps:**
1. Set collateral to 1 WBTC at 30_000 USD; UniV3 DAI/USSD pool (3000e6 USSD, 2000e18 DAI).
2. Call `rebalance()`; ownval < 1e6 - threshold triggers `BuyUSSDSellCollateral((3000e6 - 2000e18/1e12)/2)` = 500e6.
3. Inside loop, collateralval = 30_000e18 > amountToBuyLeftUSD = 500e18.
4. Compute `amountToSellUnits = balanceOf(USSD) * ((amountToBuyLeftUSD*1e18/collateralval)/1e18)/1e18` = 1e8 * 0 / 1e18 = 0.
5. `UniV3SwapInput(pathsell, 0)` executes a zero-amount swap; amountToBuyLeftUSD and DAItosell stay 0.
**How found:** Code reading of the rebalance path; noticed the double 1e18 division in amountToSellUnits and traced the arithmetic with concrete pool/collateral numbers to show truncation to zero.
**Insight:** When a formula scales a value by 1e18 and then divides by an already-1e18-scaled quantity, check the intermediate truncation: partial-sale branches are where integer division silently yields 0 and the swap becomes a no-op.
