Wenwin contest - Dug's results

The next generation of chance-based gaming.

General Information

Platform: Code4rena

Start Date: 06/03/2023

Pot Size: $36,500 USDC

Total HM: 8

Participants: 93

Period: 3 days

Judge: cccz

Total Solo HM: 3

Id: 218

League: ETH

Wenwin

Findings Distribution

Researcher Performance

Rank: 33/93

Findings: 1

Award: $148.64

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: sashik_eth

Also found by: 0xbepresent, Dug, Haipls, MadWookie, adriro, hl_, horsefacts, peanuts

Labels

bug
2 (Med Risk)
satisfactory
duplicate-366

Awards

148.6407 USDC - $148.64

External Links

Lines of code

https://github.com/code-423n4/2023-03-wenwin/blob/91b89482aaedf8b8feb73c771d11c257eed997e8/src/Lottery.sol#L259-L269

Vulnerability details

Impact

An unclaimed, winning ticket could be listed for sale on a peer to peer NFT exchange by a nefarious actor who then watches the mempool for a purchase/transfer.

Upon seeing that the NFT was purchased, they could frontrun the transaction with a call to claimRewards, receiving the rewards ahead of transferring the now claimed NFT to the recipient.

Proof of Concept

It is just calling an existing claimRewards function, which calls claimWinningTicket, rewarding the owner and marking it as claimed.

    function claimRewards(LotteryRewardType rewardType) external override returns (uint256 claimedAmount) {
        address beneficiary = (rewardType == LotteryRewardType.FRONTEND) ? msg.sender : stakingRewardRecipient;
        claimedAmount = LotteryMath.calculateRewards(ticketPrice, dueTicketsSoldAndReset(beneficiary), rewardType);

        emit ClaimedRewards(beneficiary, claimedAmount, rewardType);
        rewardToken.safeTransfer(beneficiary, claimedAmount);
    }
    function claimWinningTicket(uint256 ticketId) private onlyTicketOwner(ticketId) returns (uint256 claimedAmount) {
        uint256 winTier;
        (claimedAmount, winTier) = this.claimable(ticketId);
        if (claimedAmount == 0) {
            revert NothingToClaim(ticketId);
        }

        unclaimedCount[ticketsInfo[ticketId].drawId][ticketsInfo[ticketId].combination]--;
        markAsClaimed(ticketId);
        emit ClaimedTicket(msg.sender, ticketId, claimedAmount);
    }

Tools Used

Manual review

Burn tickets when claimed.

#0 - c4-judge

2023-03-11T15:59:35Z

thereksfour marked the issue as duplicate of #425

#1 - c4-judge

2023-03-19T10:06:32Z

thereksfour marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter