Open c4-submissions opened 11 months ago
minhquanym marked the issue as sufficient quality report
d1ll0n (sponsor) confirmed
MarioPoneder marked the issue as satisfactory
MarioPoneder marked the issue as selected for report
MarioPoneder marked the issue as primary issue
Lines of code
https://github.com/code-423n4/2023-10-wildcat/blob/main/src/market/WildcatMarketBase.sol#L510-L511
Vulnerability details
Bug Description
After a lender calls
queueWithdrawal()
, the amount of assets allocated to a withdrawal batch is calculated in_applyWithdrawalBatchPayment()
as shown:WildcatMarketBase.sol#L510-L518
The calculation relies on
normalizeAmount()
to convert the amount of market tokens in a batch into assets.However, as
normalizeAmount()
rounds up, it might cause the amount of assets allocated to a batch to be 1 higher than the correct amount. For example, ifavailableLiquidity
is77e6
USDC,normalizedAmount
could become77e6 + 1
after calculation due to rounding.This is problematic as it causes
totalDebts()
to increase, causing the market to incorrectly become delinquent after_applyWithdrawalBatchPayment()
is called although the borrower has transferred sufficient assets.More specifically, if a market's asset balance is equal to
totalDebts()
, it should never be delinquent regardless of what function is called as the market has sufficient assets to cover the amount owed. However, due to the bug shown above, this could occur after a function such asqueueWithdrawal()
is called.Impact
A market could incorrectly become delinquent after
_applyWithdrawalBatchPayment()
is called.This could cause a borrower to wrongly pay a higher interest rate, for example:
totalDebts()
to get the amount of assets owed.updateState()
.queueWithdrawal()
.Additionally, this bug also makes it possible for a market to become delinquent after it is closed through
closeMarket()
, which should not be possible.Proof of Concept
The code below contains two tests:
test_queueWithdrawalRoundingAffectsDelinquency()
demonstrates how rounding up in_applyWithdrawalBatchPayment()
could make the market delinquent even when it should not be.test_marketCanBecomeDelinquentAfterClosing()
shows how a market can become delinquent even aftercloseMarket()
is called.Recommended Mitigation
In
_applyWithdrawalBatchPayment()
, consider rounding down when calculating the amount of assets allocated to a batch:WildcatMarketBase.sol#L510-L511
Assessed type
Math