Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: medium
Valid

The chance to win a specified snek NFT is not implemented correctly

Summary

The chances for win a given snek NFT in the raffle defined in the Snek NFT Stats are not observed.

Vulnerability Details

The 3 rarity scores are defined as follows:

COMMON_RARITY: public(constant(uint256)) = 70
RARE_RARITY: public(constant(uint256)) = 25
LEGEND_RARITY: public(constant(uint256)) = 5

This means that the chance the participant to win a NFT with COMMON_RARITY is 70%, with RARE_RARITY is 25% and with LEGEND_RARITY is 5%. But the fulfillRandomWords doesn't implement the rarity chances:

def fulfillRandomWords(request_id: uint256, random_words: uint256[MAX_ARRAY_SIZE]):
index_of_winner: uint256 = random_words[0] % len(self.players)
recent_winner: address = self.players[index_of_winner]
self.recent_winner = recent_winner
self.players = []
self.raffle_state = RaffleState.OPEN
self.last_timestamp = block.timestamp
@> rarity: uint256 = random_words[0] % 3
self.tokenIdToRarity[ERC721._total_supply()] = rarity
log WinnerPicked(recent_winner)
ERC721._mint(recent_winner, ERC721._total_supply())
send(recent_winner, self.balance)

The function calculates the rarity in the following way: random_words[0] % 3. As 0 is for the COMMON (Brown Snek), 1 is for RARE (Jungle Snek) and 2 is for LEGEND (Cosmic Snek). This means that the three types NFTs have an equal chance to be won (33.33%).

Impact

The participants in the raffle are misleading about the chance to win the COMMON, RARE and LEGEND NFT.

Tools Used

VS Code, Manual Review

Recommendations

Add the following changes to the fulfillRandomWords function:

def fulfillRandomWords(request_id: uint256, random_words: uint256[MAX_ARRAY_SIZE]):
index_of_winner: uint256 = random_words[0] % len(self.players)
recent_winner: address = self.players[index_of_winner]
self.recent_winner = recent_winner
self.players = []
self.raffle_state = RaffleState.OPEN
self.last_timestamp = block.timestamp
+ rarity: uint256 = random_words[0] % 100;
+ if (rarity < COMMON_RARITY) {
+ self.tokenIdToRarity[ERC721._total_supply()] = COMMON;
+ } else if (rarity < COMMON_RARITY + RARE_RARITY) {
+ self.tokenIdToRarity[ERC721._total_supply()] = RARE;
+ } else {
+ self.tokenIdToRarity[ERC721._total_supply()] = LEGEND;
+ }
- rarity: uint256 = random_words[0] % 3
- self.tokenIdToRarity[ERC721._total_supply()] = rarity
log WinnerPicked(recent_winner)
ERC721._mint(recent_winner, ERC721._total_supply())
send(recent_winner, self.balance)
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Rarity is 1/3 instead of what the docs say

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.