C-1: Protocol can be drained by renewing already repaid or liquidated loans
Summary:
When a user repays a loan completely, the collateral NFT is returned and the loan is marked as repaid. However, renew() does not check if the loan has been repaid, allowing users to receive new funds without providing any collateral.
Description:
A user can repay a loan completely with repay() in both BeraBondGoldilend and RebaseGoldilend contracts. When the loan is fully repaid, the collateral NFT is transferred back to the user and repaid is set to true.
However, renew() does not verify if the loan has been repaid or if the collateral still exists, allowing users to exploit this vulnerability.
The exploit works as follows:
- User borrows funds with NFT collateral
- User repays the loan completely receiving back the NFT
- User calls
renew()on the sameloanId - User receives new funds without providing any collateral
- Repeat
This also apply for liquidation flow.
Impact:
Critical. Attacker can steal all funds by renewing already repaid or liquidated loans without providing any collateral.
Recommendation:
Verify in renew() that userLoan.repaid == false and userLoan.liquidated == false.
Developer Response:
Fixed in commit 32980ec965b9a3e23d3631adf34c227f1e766066.