User could withdraw more than supposed to, forcing last user withdraw to fail #64
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
edited-by-warden
H-01
primary issue
Highest quality submission among a set of duplicates
🤖_14_group
AI based duplicate group recommendation
satisfactory
satisfies C4 submission criteria; eligible for awards
selected for report
This submission will be included/highlighted in the audit report
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2024-08-wildcat/blob/main/src/market/WildcatMarketWithdrawals.sol#L248
Vulnerability details
Impact
User could withdraw more than supposed to and force last user's withdraw to fail.
Proof of Concept
Within Wildcat, withdraw requests are put into batches. Users first queue their withdraws and whenever there's sufficient liquidity, they're filled at the current rate. Usually, withdraw requests are only executable after the expiry passes and then all users within the batch get a cut from the
batch.normalizedAmountPaid
proportional to the scaled amount they've requested a withdraw for.This makes sure that the sum of all withdraws doesn't exceed the total
batch.normalizedAmountPaid
.However, this invariant could be broken, if the market is closed as it allows for a batch's withdraws to be executed, before all requests are added.
Consider the market is made of 3 lenders - Alice, Bob and Laurence.
state.normalizedUnclaimedWithdrawals
Note: marking this as High severity as it both could happen intentionally (attacker purposefully queuing numerous low-value withdraws to cause rounding down) and also with normal behaviour in high-value closed access markets where a user's withdraw could easily be in the hundreds of thousands.
Also breaks core invariant:
Adding a PoC to showcase the issue:
Tools Used
Manual review
Recommended Mitigation Steps
Although it's not a clean fix, consider adding a
addNormalizedUnclaimedRewards
function which can only be called after a market is closed. It takes token from the user and increases the global variablestate.normalizedUnclaimedRewards
. The invariant would remain broken, but it will make sure no funds are permanently stuck.Assessed type
Under/Overflow
The text was updated successfully, but these errors were encountered: