HIGH severity: `TroveManager::redeemCollateral` can return less collateral tokens than expected due to rounding down to zero precision loss. **Description:** When a user calls `TroveManager::redeemCollateral` with a large enough debt amount such that the:
* first trove is completely exhausted and closed
* remaining debt amount used in the second trove is small

A [rounding down to zero precision...

Vulnerable code:
singleRedemption.collateralLot = (singleRedemption.debtLot * BIMA_DECIMAL_PRECISION) / _price;

function test_redeemCollateral_noCollateralForRemainingAmount() external {
    // fast forward time to after bootstrap period
    vm.warp(stakedBTCTroveMgr.systemDeploymentTime() + stakedBTCTroveMgr.BOOTSTRAP_PERIOD());

    // update price oracle response to prevent stale revert
    mockOracle.setResponse(mockOracle.roundId() + 1,
                           mockOracle.answer(),
                           mockOracle.startedAt(),
                           block.timestamp,
                           mockOracle.answeredInRound() + 1);

    // user1 opens a trove with 2 BTC collateral for their max borrowing power
    uint256 collateralAmount = 1e18;

    uint256 debtAmountMax
        = ((collateralAmount * _getScaledOraclePrice() / borrowerOps.CCR())
          - INIT_GAS_COMPENSATION);

    _openTrove(users.user1, collateralAmount, debtAmountMax);

    // user2 opens a trove with 2 BTC collateral for their max borrowing power
    _openTrove(users.user2, collateralAmount, debtAmountMax);

    // mint user3 enough debt tokens such that they will close
    // user1's trove and attempt to redeem part of user2's trove,
    // but the second amount is small enough to trigger a rounding
    // down to zero precision loss in the `singleRedemption.collateralLot`
    // calculation
    uint256 debtToSend = debtAmountMax + 59_999;

    // save a snapshot state before redeem
    uint256 snapshotPreRedeem = vm.snapshot();

    vm.prank(address(borrowerOps));
    debtToken.mint(users.user3, debtToSend);
    assertEq(debtToken.balanceOf(users.user3), debtToSend);
    assertEq(stakedBTC.balanceOf(users.user3), 0);

    // user3 exchanges their debt tokens for collateral
    uint256 maxFeePercent = stakedBTCTroveMgr.maxRedemptionFee();

    vm.prank(users.user3);
    stakedBTCTroveMgr.redeemCollateral(debtToSend,
                                       users.user1, address(0), address(0), 3750000000000000, 0,
                                       maxFeePercent);

    // verify user3 has no debt tokens
    assertEq(debtToken.balanceOf(users.user3), 0);

    // verify user3 received some collateral tokens
    uint256 user3ReceivedCollateralFirst = stakedBTC.balanceOf(users.user3);
    assertTrue(user3ReceivedCollateralFirst > 0);

    // now rewind to snapshot before redeem
    vm.revertTo(snapshotPreRedeem);

    // this time do just enough to close the first trove, without the excess 59_999
    debtToSend = debtAmountMax;

    vm.prank(address(borrowerOps));
    debtToken.mint(users.user3, debtToSend);
    assertEq(debtToken.balanceOf(users.user3), debtToSend);
    assertEq(stakedBTC.balanceOf(users.user3), 0);

    vm.prank(users.user3);
    stakedBTCTroveMgr.redeemCollateral(debtToSend,
                                       users.user1, address(0), address(0), 3750000000000000, 0,
                                       maxFeePercent);

    // verify user3 has no debt tokens
    assertEq(debtToken.balanceOf(users.user3), 0);

    // verify user3 received some collateral tokens
    uint256 user3ReceivedCollateralSecond = stakedBTC.balanceOf(users.user3);
    assertTrue(user3ReceivedCollateralSecond > 0);

    // user3 received the same amount of collateral tokens, even though
    // they redeemed less debt tokens than the first time
    assertEq(user3ReceivedCollateralSecond, user3ReceivedCollateralFirst);
}

if (
                    icrError > 5e14 ||
+                   singleRedemption.collateralLot == 0 ||
                    _getNetDebt(newDebt) < IBorrowerOperations(borrowerOperationsAddress).minNetDebt()
                ) {
                    singleRedemption.cancelledPartial = true;
                    return singleRedemption;
                }