MEDIUM-2: In the "selectWinner" function, there is a "rarity" calculation that returns a reminder of division by 100. This decreases the player's change to obtain the more rare NFTs.
Mathematical vulnerability causes a decrease in the chance of obtaining the Legendary NFT by 20%.
The rarity calculation will result in one of the values on the interval of <0, 99>. The rarity itself is determined based on this value as follows. If the rarity result is less than OR EQUAL to "COMMON_RARITY" (a constant value of 70), the winner receives a "COMMON" NFT. However, the scale of numbers ranges <0, 70> which contains 71 of the 100 possible values of the "rarity" variable. The true chance is therefore 1% higher than declared.
Similar goes for the "RARE" NFT, where we focus on the adjusted range (all values that are 70 or less are already resolved) of <71, 95>. The chance to get a "RARE" NFT therefore meets the specified rules.
In case of "LEGENDARY" NFT, we get the following range <96, 99> that contains only 4 values.
This vulnerability decreases the chance of obtaining the "LEGENDARY" NFT by 20% while increasing the chance of obtaining the "COMMON" NFT by 1%.
Static analysis, mathematical proof
Instead of using the "less than or equal" operator in the rarity section of the "selectWinner" function, use "strictly less than" operator. This will ensure that all rarity values ranging <0, 69> = 70 values will get COMMON NFT, values <70, 94> = 25 values will get "RARE" NFT, and values <95, 99> = 5 values will receive "LEGENDARY" NFT. This spread of 70:25:5 meets the specifications of the contract.
71% 25% 4%
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.