In Lottery.sol contract any user can buy tickets for lottery. Call to buyTickets() takes 4 parameters and 1 of those is address frontend. After passing checks and bounds if tickets are minted then number of minted tickets are stored in this mapping frontendDueTicketSales[frontend]. It will be used later.
buyTickets() has no validation of != address(0) for address frontend. When 0x0 address is passed then function will record the frontendDueTicketSales for 0x0 and this frontendDueTicketSales rewards are not claimable by any address.
Impact
Rewards stored at frontendDueTicketSales[0x0] remains unclaimed and never returned to Jackpot either. Which makes rewards locked in contract forever.
Proof of Concept
For POC, I made frontendDueTicketSales variable public which makes verification easy. Below POC shows that it is possible to send 0x0 as frontend address and tickets will be stored against 0x0 which eventually results in rewards locked forever.
Lines of code
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L110-L131
Vulnerability details
Description
In Lottery.sol contract any user can buy tickets for lottery. Call to
buyTickets()
takes 4 parameters and 1 of those isaddress frontend
. After passing checks and bounds if tickets are minted then number of minted tickets are stored in this mappingfrontendDueTicketSales[frontend]
. It will be used later.Now at any point in future frontend operator aka
address frontend
can callclaimRewards
to claim rewards from Lottery contract.Issue
buyTickets()
has no validation of!= address(0)
foraddress frontend
. When 0x0 address is passed then function will record thefrontendDueTicketSales
for 0x0 and thisfrontendDueTicketSales
rewards are not claimable by any address.Impact
Rewards stored at
frontendDueTicketSales[0x0]
remains unclaimed and never returned to Jackpot either. Which makes rewards locked in contract forever.Proof of Concept
For POC, I made
frontendDueTicketSales
variable public which makes verification easy. Below POC shows that it is possible to send 0x0 as frontend address and tickets will be stored against 0x0 which eventually results in rewards locked forever.Recommended Mitigation Steps
There are two possible solution for this to avoid this situation.
require(frontend != address(0), "Frontend-address-zero");
inbuyTickets()
method OR