Isolated Margin Lending the BendDAO protocol will calculate the heath factor based on a single collateral (one NFT), the liquidation of collateral will be achieved by selling the NFT through an auction mechanism.
However, the borrower who gets liquidated (his NFT is in the auction state) still able to repay his loan and close the auction, by triggering IsolateLiquidation.sol#isolateRedeem().
Each asset has a redemption threshold redeemThreshold to define the minimum debt repayment amount by the borrower
The redeemThreshold is updateable from Configurator.sol#setAssetAuctionParams() with a max value of 10_000
In case the user calls IsolateLiquidation.sol#isolateRedeem()
and nftAssetData.redeemThreshold is 10_000 (MAX_REDEEM_THRESHOLD)
this will be set scaledAmount to zero
This means the debt is fully paid
However,
1- the loanData.loanStatus will still be in active state Constants.LOAN_STATUS_ACTIVE
2- the erc721TokenData.LockerAddr is not updated to address(0),
So, the user is not able to withdraw his NFT from BVault.sol or even update the loan state and LockerAddr values through IsolateLending.sol#isolateRepay() due to this check
Note: the only way the user can unlock his NFT is by borrowing again, this will increase loanData.scaledAmount again to greater than zero, and then he needs to repay that loan IsolateLending.sol#isolateRepay() to update the erc721TokenData.LockerAddr to address(0).
and this will expose the user to the unnecessary risk of being liquidated again.
Impact
Users are forced to borrow again to unlock their NFTs After Isolate Redeem
Proof of Concept
Foundry PoC:
Please copy the following POC in TestIntIsolateRedeem.t.sol
Lines of code
https://github.com/code-423n4/2024-07-benddao/blob/main/src/libraries/logic/IsolateLogic.sol#L356-L357
Vulnerability details
Description
Isolated Margin Lending the BendDAO protocol will calculate the heath factor based on a single collateral (one NFT), the liquidation of collateral will be achieved by selling the NFT through an auction mechanism.
However, the borrower who gets liquidated (his NFT is in the auction state) still able to repay his loan and close the auction, by triggering
IsolateLiquidation.sol#isolateRedeem()
.Each asset has a redemption threshold
redeemThreshold
to define the minimum debt repayment amount by the borrowerThe
redeemThreshold
is updateable fromConfigurator.sol#setAssetAuctionParams()
with a max value of 10_000In case the user calls
IsolateLiquidation.sol#isolateRedeem()
andnftAssetData.redeemThreshold
is 10_000 (MAX_REDEEM_THRESHOLD) this will be setscaledAmount
to zeroThis means the debt is fully paid However, 1- the
loanData.loanStatus
will still be in active stateConstants.LOAN_STATUS_ACTIVE
2- theerc721TokenData.LockerAddr
is not updated to address(0),So, the user is not able to withdraw his NFT from
BVault.sol
or even update the loan state andLockerAddr
values throughIsolateLending.sol#isolateRepay()
due to this checkNote: the only way the user can unlock his NFT is by borrowing again, this will increase
loanData.scaledAmount
again to greater than zero, and then he needs to repay that loanIsolateLending.sol#isolateRepay()
to update theerc721TokenData.LockerAddr
to address(0).and this will expose the user to the unnecessary risk of being liquidated again.
Impact
Users are forced to borrow again to unlock their NFTs After Isolate Redeem
Proof of Concept
Foundry PoC: Please copy the following POC in
TestIntIsolateRedeem.t.sol
Tools Used
Manual Review - Foundry
Recommended Mitigation Steps
In case
loanData.scaledAmount == 0
callVaultLogic.erc721SetTokenLockerAddr(nftAssetData, params.nftTokenIds[vars.nidx], address(0));
Assessed type
Other