Liquidation attempts against an undercollateralized user with many NFTs deposited is impossible. This is due to gas-heavy collateral calculations in getUserCollateralValue()::LendingPool.sol.
Specifcally, gas consumption can grow excessively in the unbounded loop in getUserCollateralValue() leading to a denial-of-service (DOS) when initiateLiquidation() is called. Note that initiateLiquidation() calls calculateHealthFactor() which in turn
calls getUserCollateralValue(). These calls would revert, preventing liquidation of a liquidatable position. The result is bad debt creation and severe undercollateralization against the protocol.
Root Cause: There is no cap on the number of NFTs a user can deposit. Every deposit appends the token ID to an unbounded array (user.nftTokenIds) in getUserCollateralValue()::LendingPool.sol, which is later iterated over in functions such as getUserCollateralValue().
The collateral calculation function (getUserCollateralValue()) iterates over the entire unbounded array, leading to linear gas consumption that could eventually exceed block limits. These issues together expose the protocol to potential DOS attacks.
The same root cause of this bug can also be exploited after the initial liquidation period has begun.
If, during the grace period, a user legitimately mints and deposits a large amount of NFTs, the same bug will prevent the liquidation from being finalized.
Due to the for loop that sends the NFTs to the stability pool LendingPool.sol::514-518.
Step 1: Please add a realistic block gas limit to hardhat.config.cjs file:
Step 2: Paste the following describe block into LendingPool.test.js:
Step 3: Run with the following command:
An attacker or even a legitimate user who legitimately mints and then deposits a large number of NFTs to the lending pool can prevent himself from being liquidated.
This results in the protocol absorbing bad debt and being undercollateralized. The issue is compounded by the fact that the amount of bad debt will necessarily be very large as the issue only arises when many NFTs are deposited.
Prevents initiated liquidations from being finalized if large number of NFTs are minted and deposited during the grace period.
Undercollateralizes the system and creates bad debt.
Although adding NFTs to RAAC is semi-permissioned process, requiring price setting (RAACHousePrices.sol::setHousePrice()) prior to minting. There is no reason why large real estate holders would effectively be denied to add all their holdings initially. In fact, RAAC would be incentivized to tokenize exactly this class of user. The issue arises when there is a price drop of the collateral for such large institutional holders. They, by definition, would have large amounts of NFTs on RAAC. By extension, they would have potentially very large borrow positions too. The bug is thus very likely to occur and presents critical systemic risks for protocol health and solvency. The largest borrowers will be un-liquidatable creating the maximum damage and largest amounts of bad debt.
Note that many institutional entities own more than 5,000 real estate units:
Greystar Real Estate Partners – 108,566+ units
Blackstone Group – 300,000+ units
Starwood Capital – 115,000+ units
Tricon Residential – 31,000+ units
Starlight Investments – 70,000+ units
CAPREIT – 67,000+ units
Kushner Real Estate Group (KRE Group) – 9,000+ units
Bozzuto Group – 70,000+ units
Equity Residential – 80,000+ units
Mid-America Apartment Communities (MAA) – 100,000+ units
An additional impact is that despite liquidation concerns, a user with many NFTs deposited may deplete the available liquidity on the protocol given their significant borrowing power on RAAC. This is a result of the same root cause (not limiting the number of NFTs that can be deposited).
Manual Review, Hardhat
Introduce a limit on the number of NFTs that can be deposited per user to control the size of the array. Additionally, refactor collateral value computations to either handle large arrays more efficiently or to use off-chain or batched processing methods, thereby mitigating the risk of excessive gas consumption.
LightChaser L-36 and M-02 covers it.
LightChaser L-36 and M-02 covers it.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.