Skip to content
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

jsmi - Attacker can cancel raffle when there is exactly minimum participants. #340

Closed
sherlock-admin2 opened this issue Aug 20, 2024 · 2 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A Medium severity issue. Reward A payout will be made for this issue Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed

Comments

@sherlock-admin2
Copy link

sherlock-admin2 commented Aug 20, 2024

jsmi

Medium

Attacker can cancel raffle when there is exactly minimum participants.

Summary

When there is exactly minimum participants, both drawing winner and cancelling raffle are available at the same time.
Attacker can exploit this vulnerability and cancel the raffle.

Vulnerability Detail

When tickets sale period finishes, anyone can call WinnablesTicketManager.drawWinner() which in turn calls the following _checkShouldDraw() to validate some conditions.

    function _checkShouldDraw(uint256 raffleId) internal view {
        Raffle storage raffle = _raffles[raffleId];
        if (raffle.status != RaffleStatus.IDLE) revert InvalidRaffle();
        uint256 currentTicketSold = IWinnablesTicket(TICKETS_CONTRACT).supplyOf(raffleId);
        if (currentTicketSold == 0) revert NoParticipants();

        if (block.timestamp < raffle.endsAt) {
            if (currentTicketSold < raffle.maxTicketSupply) revert RaffleIsStillOpen();
        }
431     if (currentTicketSold < raffle.minTicketsThreshold) revert TargetTicketsNotReached();
    }

From L431, the sold ticket count should be equal or larger than minimum threshold to start drawing winner.
On the other hand, attacker can call WinnablesTicketManager.cancelRaffle() which in turn calls the following _checkShouldCancel().

    function _checkShouldCancel(uint256 raffleId) internal view {
        Raffle storage raffle = _raffles[raffleId];
        if (raffle.status == RaffleStatus.PRIZE_LOCKED) return;
        if (raffle.status != RaffleStatus.IDLE) revert InvalidRaffle();
        if (raffle.endsAt > block.timestamp) revert RaffleIsStillOpen();
        uint256 supply = IWinnablesTicket(TICKETS_CONTRACT).supplyOf(raffleId);
440     if (supply > raffle.minTicketsThreshold) revert TargetTicketsReached();
    }

From L440, the sold ticket count should be less or equal than minimum threshold to cancel raffle.
As a result, when the sold ticket count is equal to minimum threshold, both drawing winner and canceling raffle are available.
Attacker can cancel the raffle before any other users drawing winner in such a case

Impact

Attacker can cancel raffle when there is exactly minimum participants and this means DoS of core function of contract.

Code Snippet

Tool used

Manual Review

Recommendation

Modify WinnablesTicketManager._checkShouldDraw() function as follows.

    function _checkShouldCancel(uint256 raffleId) internal view {
        Raffle storage raffle = _raffles[raffleId];
        if (raffle.status == RaffleStatus.PRIZE_LOCKED) return;
        if (raffle.status != RaffleStatus.IDLE) revert InvalidRaffle();
        if (raffle.endsAt > block.timestamp) revert RaffleIsStillOpen();
        uint256 supply = IWinnablesTicket(TICKETS_CONTRACT).supplyOf(raffleId);
-       if (supply > raffle.minTicketsThreshold) revert TargetTicketsReached();
+       if (supply >= raffle.minTicketsThreshold) revert TargetTicketsReached();
    }

Duplicate of #26

@github-actions github-actions bot added the Excluded Excluded by the judge without consulting the protocol or the senior label Aug 29, 2024
@sherlock-admin3 sherlock-admin3 changed the title Upbeat Merlot Monkey - Attacker can cancel raffle when there is exactly minimum participants. jsmi - Attacker can cancel raffle when there is exactly minimum participants. Sep 4, 2024
@sherlock-admin3 sherlock-admin3 added the Non-Reward This issue will not receive a payout label Sep 4, 2024
@sherlock-admin3 sherlock-admin3 added Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed labels Sep 10, 2024
@WangSecurity
Copy link

This will be duplicated with #26 and validated with Medium severity.

@WangSecurity WangSecurity added Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A Medium severity issue. and removed Excluded Excluded by the judge without consulting the protocol or the senior labels Sep 20, 2024
@sherlock-admin2 sherlock-admin2 added Reward A payout will be made for this issue and removed Non-Reward This issue will not receive a payout labels Sep 20, 2024
@sherlock-admin2
Copy link
Author

The protocol team fixed this issue in the following PRs/commits:
Winnables/public-contracts#23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A Medium severity issue. Reward A payout will be made for this issue Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed
Projects
None yet
Development

No branches or pull requests

3 participants