code-423n4 / 2023-03-wenwin-findings

1 stars 1 forks source link

It is possible to buy tickets without holding the nativeToken #217

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

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

Vulnerability details

Impact

An external contract could call the buyTickets() function and mint tickets for a draw without holding any of the rewardToken for paying for the ticket

Proof of Concept

If an attacker writes an external contract to call the buyTickets() function, tickets will be minted through each iteration of the for loop

for (uint256 i = 0; i < drawIds.length; ++i) {
            ticketIds[i] = registerTicket(drawIds[i], tickets[i], frontend, referrer);
        }

When registerTicket() is called, it calls the mint() function, which sends tickets to the callers address.

ticketId = mint(msg.sender, drawId, ticket);

Up to now, the contract hasn’t checked whether we have sufficient rewardToken to pay for the tickets. When execution gets to the final line of the function which takes payment, we have already received our tickets and can allow to function to fail.

Recommended Mitigation Steps

Check that the function caller has sufficient tokens to pay

require(rewardToken.balanceOf(msg.sender) >= ticketPrice * tickets.length)
c4-judge commented 1 year ago

thereksfour marked the issue as unsatisfactory: Invalid