Summary
In closeTroveFromCollateral(), the calculation trove.entireColl - _params.flashLoanAmount mixes 18-decimal wWBTC with 8-decimal WBTC values, causing either transaction revert or bypassed slippage protection.
Vulnerability Detail
The closeTroveFromCollateral() function calculates collLeft by subtracting flashLoanAmount (8 decimals, WBTC) from trove.entireColl (18 decimals, wWBTC). This decimal mismatch causes:
- If
entireCollis e.g.1e18(1 wWBTC) andflashLoanAmountis1e8(1 WBTC), thencollLeft = 1e18 - 1e8 ≈ 1e18- almost the entire collateral - The
minExpectedCollateralcheck becomes meaningless ascollLeftis always nearentireColl - When sending
collLeftto the user, the transaction will revert because the contract doesn't have that much wWBTC
Impact
Users cannot close their troves using the flash loan mechanism, or if the function somehow proceeds, the slippage protection is bypassed.
Code Snippet
function closeTroveFromCollateral(CloseTroveFromCollateralParams calldata _params) external {
// ...
LatestTroveData memory trove = troveManager.getLatestTroveData(_params.troveId);
// @audit - trove.entireColl is in 18 decimals (wWBTC)
// @audit - _params.flashLoanAmount is in 8 decimals (WBTC)
uint256 collLeft = trove.entireColl - _params.flashLoanAmount; // WRONG!
require(collLeft >= _params.minExpectedCollateral, "Insufficient collateral");
// ...
}Tool Used
Manual Review
Recommendation
Convert flashLoanAmount to 18 decimals before subtraction:
function closeTroveFromCollateral(CloseTroveFromCollateralParams calldata _params) external {
// ...
LatestTroveData memory trove = troveManager.getLatestTroveData(_params.troveId);
// Convert flashLoanAmount from 8 decimals to 18 decimals
uint256 flashLoanAmountWrapped = _params.flashLoanAmount * 1e10;
uint256 collLeft = trove.entireColl - flashLoanAmountWrapped;
require(collLeft >= _params.minExpectedCollateral, "Insufficient collateral");
// ...
}