Settled collateral of a borrower aren't available for lenders until borrower's debt is fully cleared
Summary
ERC721Pool's settle() lacks collateral ids array rebalance when the settlement isn't full, i.e. when t0DebtRemaining > 0.
Vulnerability Detail
Auctions's settlePoolDebt() returns current state of the borrower after the settlement. If any of borrower's collateral id were removed from them it needs to be accounted for, but when t0DebtRemaining > 0 this doesn't happen, i.e. removed borrower's tokens aren't added to the buckets cumulative collateral ids array and so this collateral is still unavailable for lenders.
Impact
The settled collateral of the borrower will not be available for LP's withdrawal as the corresponding function will revert on an attempt to extract token ids from bucketTokenIds array.
The length of such freeze can vary up to be permanent, for example if there is no funds (reserves and deposits) to fully settle the borrower. This is principal fund loss scenario for the lenders, but given the prerequisite of the full default setting the severity to be medium.
Code Snippet
When a borrower has some unsettled debt, t0DebtRemaining > 0, all of their collateral remain locked with borrowerTokenIds as _rebalanceTokens() isn't called in this case:
hyh
medium
Settled collateral of a borrower aren't available for lenders until borrower's debt is fully cleared
Summary
ERC721Pool's settle() lacks collateral ids array rebalance when the settlement isn't full, i.e. when
t0DebtRemaining > 0
.Vulnerability Detail
Auctions's settlePoolDebt() returns current state of the borrower after the settlement. If any of borrower's collateral id were removed from them it needs to be accounted for, but when
t0DebtRemaining > 0
this doesn't happen, i.e. removed borrower's tokens aren't added to the buckets cumulative collateral ids array and so this collateral is still unavailable for lenders.Impact
The settled collateral of the borrower will not be available for LP's withdrawal as the corresponding function will revert on an attempt to extract token ids from
bucketTokenIds
array.The length of such freeze can vary up to be permanent, for example if there is no funds (reserves and deposits) to fully settle the borrower. This is principal fund loss scenario for the lenders, but given the prerequisite of the full default setting the severity to be medium.
Code Snippet
When a borrower has some unsettled debt,
t0DebtRemaining > 0
, all of their collateral remain locked withborrowerTokenIds
as _rebalanceTokens() isn't called in this case:https://github.com/sherlock-audit/2023-01-ajna/blob/main/contracts/src/ERC721Pool.sol#L353-L385
This can happen when settlement exits when
params_.bucketDepth == 0
:https://github.com/sherlock-audit/2023-01-ajna/blob/main/contracts/src/libraries/external/Auctions.sol#L277-L337
Tool used
Manual Review
Recommendation
Consider rebalancing each time when there is something to rebalance, for example:
https://github.com/sherlock-audit/2023-01-ajna/blob/main/contracts/src/ERC721Pool.sol#L353-L385