eeyore - Borrower will overcollateralize the loan when the last lender fulfills a partially fulfilled borrow request, in a case where the borrow request was initially matched and partially fulfilled with a loan offer. #254
Borrower will overcollateralize the loan when the last lender fulfills a partially fulfilled borrow request, in a case where the borrow request was initially matched and partially fulfilled with a loan offer.
Summary
When a borrower creates a borrow request, they specify the collateralAmount they are willing to provide in exchange for the loanAmount. These values together act as the collateralization ratio. For example, collateralAmount == 150 and loanAmount == 100 results in a 150% collateral ratio.
Once the borrow request is created, any lender can accept the request via the acceptBorrowRequest() function. After execution, the appropriate collateralization ratio is applied, and the loan is created. There is an edge case when using acceptBorrowRequest() where the last lender will have slightly more collateralization due to rounding errors, but this will result in only a few wei at most.
However, if a borrow request is matched with a loan offer via the matchProposals() function, the collateralization ratio used for both proposals is based on the loan offer proposal. This collateral ratio cannot exceed the borrow request collateral ratio. In short, the borrower will need to provide an equal or lesser amount of collateral than specified in the request but must meet the collateral required by the loan offer.
This functionality benefits the borrower and matches the loan offer creator expectations, so everything seems correct.
But there is an edge case where the borrower ends up providing more collateral than expected, breaking their anticipated collateralization ratio. This scenario could also be exploited by malicious actors to farm overcollateralized loans for profit.
A borrow request with a high collateralization ratio is matched with a loan offer with a low collateralization ratio.
External pre-conditions
None.
Attack Path
Preconditions:
There is a borrow request with collateralAmount == 200 and loanAmount == 100.
There is a loan offer with collateralAmount == 75 and loanAmount == 50.
Attack:
Malicious actors match the borrow request with the loan offer.
Malicious actors fulfill the borrower request for the remaining (50).
Impact
The borrower’s collateralization ratio is significantly higher than expected for the last lender.
Malicious actors can exploit this by crafting overcollateralized loans, by matching proposals and taking more favorable hedge positions.
PoC
Using the data from the Attack Path, the collateralization ratio will be:
Collateralization ratio used is 250%, which is unacceptable as it exceeds the 200% borrower request collateralization ratio. The difference is more than the acceptable few wei described in the README.
Mitigation
When updating the fulfillment data of the borrow request, update collateralAmount as if the borrower request collateralization ratio was used for loan creation:
eeyore
Medium
Borrower will overcollateralize the loan when the last lender fulfills a partially fulfilled borrow request, in a case where the borrow request was initially matched and partially fulfilled with a loan offer.
Summary
When a borrower creates a borrow request, they specify the
collateralAmount
they are willing to provide in exchange for theloanAmount
. These values together act as the collateralization ratio. For example,collateralAmount
== 150 andloanAmount
== 100 results in a 150% collateral ratio.Once the borrow request is created, any lender can accept the request via the
acceptBorrowRequest()
function. After execution, the appropriate collateralization ratio is applied, and the loan is created. There is an edge case when usingacceptBorrowRequest()
where the last lender will have slightly more collateralization due to rounding errors, but this will result in only a few wei at most.However, if a borrow request is matched with a loan offer via the
matchProposals()
function, the collateralization ratio used for both proposals is based on the loan offer proposal. This collateral ratio cannot exceed the borrow request collateral ratio. In short, the borrower will need to provide an equal or lesser amount of collateral than specified in the request but must meet the collateral required by the loan offer.This functionality benefits the borrower and matches the loan offer creator expectations, so everything seems correct.
But there is an edge case where the borrower ends up providing more collateral than expected, breaking their anticipated collateralization ratio. This scenario could also be exploited by malicious actors to farm overcollateralized loans for profit.
Root Cause
The root cause is using the
collateralAmountRequired
calculated with loan offer data: https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L395-L399When updating the
fulfillment
data of the borrow request, this leads to a situation where the collateral amount is undervalued compared to the loan amount in the borrower's fulfillment data: https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L401-L406This results in overcollateralization for the last lender of the borrow request: https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L983 https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L1166-L1167
Internal pre-conditions
External pre-conditions
None.
Attack Path
Preconditions:
collateralAmount
== 200 andloanAmount
== 100.collateralAmount
== 75 andloanAmount
== 50.Attack:
Impact
The borrower’s collateralization ratio is significantly higher than expected for the last lender. Malicious actors can exploit this by crafting overcollateralized loans, by matching proposals and taking more favorable hedge positions.
PoC
Using the data from the Attack Path, the collateralization ratio will be:
Collateralization ratio used is 150%, which is acceptable as it is below the 200% borrower request collateralization ratio.
fulfillment.loanAmount + fulfillAmount == proposal.loanAmount
):Collateralization ratio used is 250%, which is unacceptable as it exceeds the 200% borrower request collateralization ratio. The difference is more than the acceptable few wei described in the README.
Mitigation
When updating the
fulfillment
data of the borrow request, updatecollateralAmount
as if the borrower request collateralization ratio was used for loan creation: