Users could get blocked from claiming their profits.
When a user claims profits the system calls saveProfit() and then getUnsaved(). If the current totalProfit is <= to the last totalProfit at which the user has claimed profits this will return 0 or less. If the previous savedProfit of the msg.sender + the returned value from getUnsaved is <= 0, claimProfit will revert. This is a case in which the user should be able to claim his accumulated profits but isn't able to do so because of the value of totalProfits. Here is a simple scenario:
Initial State:
totalProfit = 1000
User A has a balance that gives them a share of the profits, say shareOf(User A) = 200.
User A's lastProfit is initially 0, and savedProfit is also 0.
2. User A Claims Profits:
User A calls claimProfit().
The getUnsaved(User A) function calculates the unsaved profit:
getUnsaved(User A) = ((totalProfit - lastProfit[User A]) * shareOf(User A)) / ACCURACY
Since lastProfit[User A] is 0, this results in:
getUnsaved(User A) = ((1000 - 0) * 200) / ACCURACY
User A claims their profit, which is 200, and savedProfit[User A] is updated to 200.
After claiming, lastProfit[User A] is updated to 1000.
3. Subsequent State:
Now, let's say totalProfit does not increase and remains 1000.
User A's lastProfit is now 1000, and savedProfit is 200.
4. User A Attempts to Claim Again:
User A calls claimProfit() again.
The getUnsaved(User A) function is called:
getUnsaved(User A) = ((totalProfit - lastProfit[User A]) * shareOf(User A)) / ACCURACY
Since lastProfit[User A] is now 1000, this results in:
getUnsaved(User A) = ((1000 - 1000) * 200) / ACCURACY = 0
The require(profit > 0, "No profit available") check fails because profit is 0, and User A cannot claim any profits.
Users can get DoSed by keeping the totalProfit at a certain level.
Manual Review
Consider a different approach to calculate the user's claimable shares; for example store the user's profits that they can claim in the saveProfile function instead of relaying only on their last calimed an current profit.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.