sherlock-audit / 2023-01-ajna-judging

1 stars 0 forks source link

Jeiwan - Missing bankruptcy detection when removing NFT collateral lets bad debt accumulate #142

Closed github-actions[bot] closed 1 year ago

github-actions[bot] commented 1 year ago

Jeiwan

high

Missing bankruptcy detection when removing NFT collateral lets bad debt accumulate

Summary

When removing NFT collateral from an ERC721 pool, there's no detection whether the pool is bankrupt after the removal. As a result, the outstanding balance of LP tokens may be added to new deposits or moved to a different bucket. When added to new deposits, it may be redeemed for the newly deposited funds, causing a loss of funds for the depositors. When moved to a different bucket, it may be redeemed for that bucket's quote tokens, which will result in a loss of funds for the depositors of the bucket.

Vulnerability Detail

Pool can end up in a bankrupt state: a situation when there's no collateral or quote tokens in a pool, but there's still a positive number of LP tokens. Currently, the protocol detects pool bankruptcy in three cases:

  1. when removing quote token;
  2. when removing ERC20 collateral (ERC20Pool.sol#L329, LenderActions.sol#L623-L629);
  3. when calling ERC721Pool.mergeOrRemoveCollateral (LenderActions.sol#L471).

However, there's no bankruptcy check when removing collateral via the ERC721Pool.removeCollateral function: the function calls LenderActions.removeCollateral, which doesn't have the bankruptcy check.

Impact

If, as a result of removing liquidity from a pool via a call to ERC721Pool.removeCollateral, the pool ends up with 0 collateral, 0 quote tokens, and with a positive number of LP tokens, the bad debt won't be removed. The LP tokens can then be moved to a different bucket (using the moveQuoteToken function; the bankruptcy check will pass) and redeemed for quote tokens or collateral NFTs. Alternatively, the owner of the LPs may leave then in the bucket, wait for new collateral and/or quote tokens to be deposited by other lenders, and redeem the LPs for the new funds: the bankruptcy checks in LenderActions.removeQuoteToken, LenderActions.removeCollateral, and LenderActions._removeMaxCollateral will also pass.

Code Snippet

LenderActions.sol#L379

Tool used

Manual Review

Recommendation

Consider adding the pool bankruptcy check to the LenderActions.removeCollateral function, similarly to how it's implemented in the LenderActions._removeMaxCollateral function.

Duplicate of #133