Summary
The request_raffle_winner
returns the total supply of NFTs instead the request_id
and doesn't emit an event RequestedRaffleWinner
.
Vulnerability Details
The request_raffle_winner
function should get a random winner.
@external
def request_raffle_winner() -> uint256:
"""Request a random winner from the VRF Coordinator after a raffle has completed."""
is_open: bool = RaffleState.OPEN == self.raffle_state
time_passed: bool = (block.timestamp - self.last_timestamp) > RAFFLE_DURATION
has_players: bool = len(self.players) > 0
has_balance: bool = self.balance > 0
assert is_open and time_passed and has_players and has_balance, ERROR_NOT_ENDED
self.raffle_state = RaffleState.CALCULATING
request_id: uint256 = VRF_COORDINATOR.requestRandomWords(
GAS_LANE,
SUBSCRIPTION_ID,
REQUEST_CONFIRMATIONS,
CALLBACK_GAS_LIMIT,
NUM_WORDS
)
@> return ERC721._total_supply()
But actually the function returns the total supply of the NFTs. That can lead to confusion that the total supply of the NFTs is the request_id
.
Also, there is an event RequestedRaffleWinner
in events section:
event RequestedRaffleWinner:
request_id: indexed(uint256)
But this event is never emitted.
Impact
The function request_raffle_winner
returns the total supply of NFTs instead of the request_id
. That leads to misunderstanding what is the correct value of the request_id
.
The function also doesn't emit an event RequestedRaffleWinner
. In that way there is no way to understand if the function successfully has retrieved the request_id
.
Tools Used
Manual Review
Recommendations
Change the return value of the request_raffle_winner
function and emit an event RequestedRaffleWinner
:
@external
def request_raffle_winner() -> uint256:
"""Request a random winner from the VRF Coordinator after a raffle has completed."""
is_open: bool = RaffleState.OPEN == self.raffle_state
time_passed: bool = (block.timestamp - self.last_timestamp) > RAFFLE_DURATION
has_players: bool = len(self.players) > 0
has_balance: bool = self.balance > 0
assert is_open and time_passed and has_players and has_balance, ERROR_NOT_ENDED
self.raffle_state = RaffleState.CALCULATING
request_id: uint256 = VRF_COORDINATOR.requestRandomWords(
GAS_LANE,
SUBSCRIPTION_ID,
REQUEST_CONFIRMATIONS,
CALLBACK_GAS_LIMIT,
NUM_WORDS
)
+ log RequestedRaffleWinner(request_id)
+ return request_id
- return ERC721._total_supply()