Closed howlbot-integration[bot] closed 1 month ago
This is a valid comment, but it isn't something we're even able to include in this function due to size limits.
I consider this low/informational as it doesn't impact the functionality of the protocol in any way (other than to make this function not very useful in a lot of cases). If the borrower has unpaid batches they need to pay off, they'll use the repayAndProcess function. Also even without any unpaid or pending withdrawal batches, if the APR is >0 the market will immediately go into delinquency one second after repayDelinquentDebt
if even 1 wei of interest accrues. To me this is more an argument to just delete these functions than a vulnerability.
Appreciate the notes!
Marking as QA because the reported scenario assumes the borrower calls the wrong function - repayOutstandingDebt
instead of repayAndProcess
3docSec changed the severity to QA (Quality Assurance)
3docSec marked the issue as grade-b
Lines of code
https://github.com/code-423n4/2024-08-wildcat/blob/fe746cc0fbedc4447a981a50e6ba4c95f98b9fe1/src/market/WildcatMarket.sol#L186-L191 https://github.com/code-423n4/2024-08-wildcat/blob/fe746cc0fbedc4447a981a50e6ba4c95f98b9fe1/src/market/WildcatMarket.sol#L202-L214 https://github.com/code-423n4/2024-08-wildcat/blob/fe746cc0fbedc4447a981a50e6ba4c95f98b9fe1/src/market/WildcatMarket.sol#L226-L287
Vulnerability details
Impact
In the current implementation of the contract's
repayOutstandingDebt()
function, when a borrower repays their delinquent debt, the contract enters a delinquent state again just seconds after repayment due to improper handling of batched withdrawals. The repayment logic does not process pending withdrawals, resulting in the borrower incurring more debt despite having repaid their outstanding balance. This is due to batched and expired withdrawals not being accounted for during repayment, leading to the accumulation of additional debt.The
closeMarket()
function, on the other hand, correctly handles pending withdrawals by updating the market state and processing withdrawals before marking the market as closed. This behavior should be replicated in the debt repayment function.Proof of Concept
The contract does not account for batched withdrawals during debt repayment, as seen in this test:
The issue arises because pending withdrawals and fees are pay immediately the borrower repaid. After calling
_repay()
, the system continues to accumulate debt from these unprocessed batches. This is handled correctly in thecloseMarket()
function, where the contract processes all pending and expired withdrawals before finalizing the market closure.Tool Used
Manual Code analysis
Mitigation Steps
Suggested Fix The repayment function should follow the same flow as the
closeMarket()
function to ensure that all batched withdrawals are processed before marking the debt as cleared. This prevents the borrower from incurring more debt after repayment.Fix: Refactor
repayOutstandingDebt()
to process pending withdrawalsKey Changes:
By processing pending withdrawals in the
repayOutstandingDebt()
function, the contract ensures that the borrower does not incur additional debt after repayment. This follows the correct logic already present in thecloseMarket()
function, thereby aligning the two processes and preventing any inconsistency in the debt repayment flow.Assessed type
Error