Summary
During settling vault debt we call the settlevaultdebt and when the contract has some credit we swap usdc for Vault assets but the vault asset amount used is not correctly calculated leading to some issues like the failure to actually settle the vault debt as expected.
Vulnerability Details
The amount taken in as the Vault asset amount is totally wrong and is in usdc value instead of vault asset value.
function settleVaultsDebt(uint256[] calldata vaultsIds) external onlyRegisteredSystemKeepers {
Vault.recalculateVaultsCreditCapacity(vaultsIds);
SettleVaultDebtContext memory ctx;
ctx.usdc = MarketMakingEngineConfiguration.load().usdc;
@audit>> Collateral.Data storage usdcCollateralConfig = Collateral.load(ctx.usdc);
@audit>> ctx.usdcIn = calculateSwapAmount(
dexSwapStrategy.dexAdapter,
ctx.vaultAsset,
ctx.usdc,
@audit>> usdc amount passed for vault asset >> usdcCollateralConfig.convertSd59x18ToTokenAmount(ctx.vaultUnsettledRealizedDebtUsdX18.abs())
);
@audit>> ctx.vaultUsdcBalance = usdcCollateralConfig.convertUd60x18ToTokenAmount(ud60x18(vault.depositedUsdc));
@audit>> Good control but lessser values will not be accurate >> ctx.usdcIn = (ctx.usdcIn <= ctx.vaultUsdcBalance) ? ctx.usdcIn : ctx.vaultUsdcBalance;
Instead of passing the Value of the vault asset we use usdc amount without ever converting it
function calculateSwapAmount(
address dexAdapter,
address assetIn,
address assetOut,
@audit>> uint256 vaultUnsettledDebtUsdAbs
)
public
view
returns (uint256 amount)
{
@audit>> amount = IDexAdapter(dexAdapter).getExpectedOutput(assetIn, assetOut, @audit >> vaultUnsettledDebtUsdAbs);
}
The amount in passed is the usdc amount in value and not the vault token amount in actually required .
Wrong equation will lead to = (usdcamount * collateral price) / usdc price
instead of = (collateral amount * collateral price) /usdc price
function getExpectedOutput(
address tokenIn,
address tokenOut,
@audit>> uint256 amountIn
)
public
view
returns (uint256 expectedAmountOut)
{
if (amountIn == 0) revert Errors.ZeroExpectedSwapOutput();
UD60x18 priceTokenInX18 = IPriceAdapter(swapAssetConfigData[tokenIn].priceAdapter).getPrice();
UD60x18 priceTokenOutX18 = IPriceAdapter(swapAssetConfigData[tokenOut].priceAdapter).getPrice();
@audit>> UD60x18 amountInX18 = Math.convertTokenAmountToUd60x18(swapAssetConfigData[tokenIn].decimals, amountIn);
@audit>> expectedAmountOut = Math.convertUd60x18ToTokenAmount(
@audit>> swapAssetConfigData[tokenOut].decimals, amountInX18.mul(priceTokenInX18).div(priceTokenOutX18)
);
if (expectedAmountOut == 0) revert Errors.ZeroExpectedSwapOutput();
}
Impact
Incorrect accounting and inability to settle the vaults debt for some vaults,or over settlement as total balance can be used when it shouldn't.
Tools Used
Manual review
Recommendations
Convert the usdc amount straight to collateral amount first and then pass it into the function to calculate usdc in.