When users buy a ticket, they can set an address for the Frontend Operator where they bought it. Then Frontend Operators can claim Frontend Rewards of 10% on the sold tickets.
But nothing prevents users from settings theirselves as the Frontend Operator, and getting back 10% of the ticket price instantly.
Proof of Concept
• User set himself as frontend when buying tickets through the buyTickets function
• User calls the claimRewards function with rewardType = LotteryRewardType.FRONTEND as the parameters
• User will receive 10% of the ticket price
First the user buys the ticket, setting himself as the frontend:
// File: src/Lottery.sol
110: function buyTickets(
111: uint128[] calldata drawIds,
112: uint120[] calldata tickets,
113: address frontend, // @audit-info Users can set theirselves as `frontend`
114: address referrer
115: )
116: external
117: override
118: requireJackpotInitialized
119: returns (uint256[] memory ticketIds)
120: {
121: if (drawIds.length != tickets.length) {
122: revert DrawsAndTicketsLenMismatch(drawIds.length, tickets.length);
123: }
124: ticketIds = new uint256[](tickets.length);
125: for (uint256 i = 0; i < drawIds.length; ++i) {
126: ticketIds[i] = registerTicket(drawIds[i], tickets[i], frontend, referrer);
127: }
128: referralRegisterTickets(currentDraw, referrer, msg.sender, tickets.length);
129: frontendDueTicketSales[frontend] += tickets.length; // @audit-info Tickets sold via a "frontend" address
130: rewardToken.safeTransferFrom(msg.sender, address(this), ticketPrice * tickets.length);
131: }
Return zero rewards for Frontend Operators that don't reach a minimum of tickets sold, such as the check done in the referral system, that requires users to have a minimum of referrals in order to claim the referrer rewards.
This way, it discourages users trying to game the system by referring themselves as Frontend Operators, as they would need to buy at least a minimum amount of tickets to receive the reward.
Lines of code
https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L110-L131 https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L151-L157 https://github.com/code-423n4/2023-03-wenwin/blob/main/src/Lottery.sol#L249-L257 https://github.com/code-423n4/2023-03-wenwin/blob/main/src/LotteryMath.sol#L119-L130
Vulnerability details
Impact
When users buy a ticket, they can set an address for the Frontend Operator where they bought it. Then Frontend Operators can claim Frontend Rewards of 10% on the sold tickets.
But nothing prevents users from settings theirselves as the Frontend Operator, and getting back 10% of the ticket price instantly.
Proof of Concept
• User set himself as
frontend
when buying tickets through thebuyTickets
function• User calls the
claimRewards
function withrewardType = LotteryRewardType.FRONTEND
as the parameters• User will receive 10% of the ticket price
First the user buys the ticket, setting himself as the
frontend
:Link to code
Then the user claims the 10% ticket price as a reward, calling the
claimRewards
function with therewardType = LotteryRewardType.FRONTEND
parameter.The
beneficiary
will be themsg.sender
Link to code
The due tickets corresponding to the claiming address were previously set when the ticket was bought.
Link to code
The function that calculates the rewards doesn't perform any additional check for Frontend Rewards.
Link to code
Tools Used
Manual review
Recommended Mitigation Steps
Return zero rewards for Frontend Operators that don't reach a minimum of tickets sold, such as the check done in the referral system, that requires users to have a minimum of referrals in order to claim the referrer rewards.
This way, it discourages users trying to game the system by referring themselves as Frontend Operators, as they would need to buy at least a minimum amount of tickets to receive the reward.