-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
aslanbek - Anyone can cancel a raffle with tickets == minTicketsThreshold, griefing all participants #26
Comments
Escalate Permanent DoS of Breaks core contract functionality (drawing a winner) for a subset of drawable raffles, (arguably) rendering the contract useless. Loss of funds in the form of lost EV for all participants if total value of the tickets was smaller than the prize. |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
The root cause is indeed valid, but what's the impact here? Only if someone calls
The impact is LOW, and the likelihood is between Low/medium as it requires both:
|
#340 is a duplicate of this issue. |
#330 is a duplicate |
#550 is a partial duplicate of this (the second vulnerability + the second attack path); or this is a partial duplicate of #550, whatever fits. According to Sherlock rules:
Both of the above apply:
Thus, according to the Sherlock rules this may be even a valid High; but it is clearly at least a valid Medium. |
A fixed is desired to perfect the conditional check but it's deemed low given the trivial change needed. |
@mystery0x I would kindly ask to point to the Sherlock docs which allow to qualify the finding as Low if the fix is trivial. To the best of my knowledge no such docs exist. Moreover, they can't exist. There are literally billions of funds lost due to bugs with trivial fixes. As an example, take a look at the Wormhole Bridge Exploit Incident Analysis. The exploit was for over $320M, but the fix is trivial: replace the deprecated function load_current_index with |
It's not about whether the fix is trivial or not, the impact is low and the likelihood is low/medium. This doesn't quality for Medium severity |
To that I have already elaborated above; have nothing to add. The severity is at least Medium; arguably can be a High. |
@kuprumxyz about your points in the previous comment:
I don't think this "lock" can be considered a DOS here, because it's how the protocol should work, i.e. you enter the raffle and your funds are locked until the raffle has finished or gets cancelled. Moreover, I don't think the finding is about this, the finding is about cancelling the raffle before the winner was drawn and I don't think any funds are locked here, since as noted above anyone can call
But, in that sense, just cancelling the raffle is DOSing the drawing of the winner. Could you elaborate a bit more on why you consider this a time-sensitive function, I don't think the ability to cancel a raffle, makes the function of picking a winner time-sensitive. |
@WangSecurity the scenario is as follows:
We see that "the user funds are locked for more than a week". Yes, this is how the protocol works, but the point is that the users lock their funds not just because of some weird desire to lock them for a month; they lock them because each of them wishes to participate in a raffle, and may be win. Depriving them of the right to draw a winner, and of winning a raffle, is the same as DoS of their funds for a month.
Point 4. above is the bifurcation point, at which only one of the two alternatives is possible: either the winner will be drawn xor the raffle will be canceled. From the time point when one happens, another can't happen anymore; thus drawing a winner is time-sensitive for this specific combination of parameters. |
@WangSecurity, here is another point to consider: If the above scenario happens, i.e. users were waiting for a month, and then the raffle got canceled though it should have been drawn, the trust of users into the protocol will be severely undermined, and most likely they won't like to participate anymore. This may easily lead to the protocol collapse. |
I would like to add that in some raffles, at the end of the buying period, someone will buy just enough tickets so the raffle reaches minTicketsThreshold, reasonably expecting that it would guarantee that the raffle will be drawn. |
This is not a valid impact.
The likelihood is between Low/medium as it requires both:
Even in such a case, if someone calls |
It will happen only if |
@WangSecurity, thank you; the advice is highly appreciated. |
hey @WangSecurity |
@WangSecurity the mentioned comment says
Which means the raffle can draw a winner if this amount is reached, which is true. There is no vulnerability in allowing the round to be both drawable and cancelled when the tickets are exactly We should assume people act in their best interest and if they want to ensure the round is drawn, they can just buy the number of tickets left to |
#475 is duplicate of this issue |
I didn't say the comment is broken and that's why the issue is validated. The problem here is that the intended design of the protocol is that the raffle shouldn't be cancellable when the min tickets threshold requirement is passed (i.e. tickets == minTicketsThreshold). Therefore, this issue qualifies for medium severity since it breaks the functionality (the raffle can be cancelled when it shouldn't be) and thus the raffle that should've been finalised, wouldn't be finalised:
The decision remains the same, accept the escalation and validate with medium severity. The duplication list has been updated. |
@WangSecurity could you elaborate on this part?
Due to this, this will never happen unless users want to, which is fair. Also, this boils down to just 1 difference in the number of tickets needed to cancel, I don't see how this is breaking core functionality as it is a very small error. |
hey @WangSecurity |
It's fair argument, but still, the scenario where the bought tickets equal exactly the minimum tickets threshold and no one wants to buy more is completely viable. I understand that it's only one ticket difference, but this can fairly happen. The decision remains, accept the escalation and validate with medium severity. The duplication list has been updated. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
@WangSecurity |
The protocol team fixed this issue in the following PRs/commits: |
aslanbek
Medium
Anyone can cancel a raffle with tickets == minTicketsThreshold, griefing all participants
Summary
As we can see, once the ticket sale is over, if exactly
minTicketsThreshold
were sold, bothcancelRaffle
anddrawWinner
are available. If anyone (e.g. a participant who does not want to participate anymore, or a griefer) manages to callcancelRaffle
before anyone callsdrawWinner
for thatraffleId
, it would cancel a raffle that should have been drawn, according to the code comment.Root Cause
_checkShouldCancel
does not revert whensupply == raffle.minTicketsThreshold
.Internal pre-conditions
currentTicketSold == raffle.minTicketsThreshold
block.timestamp >= raffle.endsAt
raffleStatus == RaffleStatus.IDLE
Attack Path
Anyone calls
cancelRaffle
whenblock.timestamp >= raffle.endsAt
, and beforedrawWinner
is called.Impact
Raffle that should be drawn is cancelled.
Mitigation
The text was updated successfully, but these errors were encountered: