Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crazy Cyan Worm - Missing collateral health checks in LeverageManager.withdrawAssets will cause bad debt accumulation as users withdraw below liquidation thresholds #559

Open
sherlock-admin3 opened this issue Feb 17, 2025 · 0 comments

Comments

@sherlock-admin3
Copy link
Contributor

Crazy Cyan Worm

High

Missing collateral health checks in LeverageManager.withdrawAssets will cause bad debt accumulation as users withdraw below liquidation thresholds

Summary

The lack of post-withdrawal collateral validation in LeverageManager.withdrawAssets will lead to protocol insolvency as attackers withdraw collateral from positions with insufficient safety margins. This allows strategic removal of collateral assets even when positions are near liquidation levels, creating systemic undercollateralization that liquidation mechanisms cannot resolve, ultimately resulting in unrecoverable lender funds.

Root Cause

In function LeverageManager.withdrawAssets(LeverageManager.sol#L199-L204) the withdrawal function lacks collateral health validation before allowing asset removal. The withdrawAssets function calls LeveragePositionCustodian.withdraw which transfers collateral tokens without checking if the position remains sufficiently collateralized after withdrawal. This allows position owners to drain collateral even when their debt-to-collateral ratio exceeds safe thresholds, bypassing liquidation protections.

contract LeverageManager is ILeverageManager, IFlashLoanRecipient, Context, LeverageManagerAccessControl {
		// ...
		
    function withdrawAssets(uint256 _positionId, address _token, address _recipient, uint256 _amount)
        external
        onlyPositionOwner(_positionId)
    {
        LeveragePositionCustodian(positionProps[_positionId].custodian).withdraw(_token, _recipient, _amount);
    }
    
    // ...
}
contract LeveragePositionCustodian is Context, Ownable {
		// ...
		
    function withdraw(address _token, address _recipient, uint256 _amount) external onlyOwner {
        _amount = _amount == 0 ? IERC20(_token).balanceOf(address(this)) : _amount;
        IERC20(_token).safeTransfer(_recipient, _amount);
    }
}

The missing health factor check creates a protocol-level vulnerability where undercollateralized positions could accumulate bad debt that cannot be liquidated. Proper lending protocols should validate collateral ratios remain above liquidation thresholds during any asset removal operations.

Internal Pre-conditions

  1. Protocol allows direct collateral withdrawals without checking debt-to-collateral ratios
  2. Leveraged positions maintain debt obligations separate from collateral tracking
  3. No minimum collateral threshold enforcement during asset removal operations

External Pre-conditions

  1. Existence of leveraged positions with collateral value barely above liquidation thresholds
  2. Market conditions where collateral assets experience price volatility (e.g. ETH drops 5% daily)
  3. Custodian contracts hold sufficient liquid collateral assets (e.g. $500k USDC in custody)

Attack Path

  1. Attacker opens leveraged position with $100k collateral supporting $80k debt (125% collateral ratio)
  2. Market dip reduces collateral value to $85k (106% ratio, near 100% liquidation threshold)
  3. Attacker withdraws $10k collateral via withdrawAssets without repayment
  4. Position collateral drops to $75k against $80k debt (93% ratio - undercollateralized)
  5. Protocol liquidation mechanisms fail to recover full debt due to insufficient collateral
  6. Repeat across multiple positions to create systemic undercollateralization

Impact

Protocol lenders face direct financial loss from unrecoverable debt. For example:

  • Total protocol TVL: $10M with $8M borrowed
  • Attacker drains 15% collateral ($1.5M) from leveraged positions
  • Creates $1.2M bad debt (15% of $8M loans) that cannot be liquidated
  • Lenders lose 12% of deposited funds ($1.2M/$10M)
  • Protocol becomes insolvent requiring emergency shutdown

PoC

No response

Mitigation

Implement collateral health checks before allowing withdrawals:

  1. Add debt-to-collateral ratio validation in LeverageManager.withdrawAssets
  2. Require post-withdrawal collateral ratio ≥ liquidation threshold (e.g. 110%)
  3. Integrate with existing liquidation system to calculate remaining collateral value
  4. Revert transaction if withdrawal would push position below safe collateral levels

Example modification flow:

  • Calculate current collateral value and debt obligations
  • Subtract withdrawal amount from collateral value
  • Verify (collateral - withdrawal) / debt ≥ minimum ratio
  • Only proceed with transfer if validation passes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant