ProjectOpenSea / seadrop

Smart contracts for primary drops on EVM chains

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

maxSupply is never reached when calculating randomOffset

Mouradif opened this issue · comments

There is a discrepancy between the comment

// randomOffset returns between 1 and MAX_SUPPLY

and the code

randomOffset = (uint256(keccak256(abi.encode(block.difficulty))) % (maxSupply - 1)) + 1;

Doing % someNumber already yields a number between 0 and someNumber - 1. Here, doing % (maxSupply - 1) yields a number between 0 and maxSupply - 2, then the last +1 raises it to a number between 1 and maxSupply - 1. If we want a number between 1 and maxSupply we could simply do

randomOffset = (uint256(keccak256(abi.encode(block.difficulty))) % maxSupply) + 1;

The result achieved by obtaining a number between 1 and maxSupply - 1 is that we have the guarantee that the token indexes will get shifted by at least 1 offset. If we want to open the possibility for the random draw to achieve a total index shifting of zero (effectively keeping the indexes as they were), we do need to generate a number between 1 and maxSupply or more simply: a number between 0 and maxSupply - 1 by just removing the + 1:

randomOffset = uint256(keccak256(abi.encode(block.difficulty))) % maxSupply;

Then in the only use of this state variable:

((tokenId + randomOffset) % _maxSupply) +

we trade the possibility of randomOffset being equal to maxSupply (resulting to zero shift) with the possibility of it being equal to zero (achieving the same result) at a slightly lower gas cost

I think you should change solidity version to 0.8.19

I do on my own contracts but it should be a different PR. This PR's goal is to achieve unpredictability in the random offset

See reasoning here #46 (comment)

That feature isn't used so often so it's okay if it's implemented wrong 😅? Like I said in my previous comment, I do take liberties on my own contracts, the idea here was to suggest a fix for the people who will use this repo.

At least, would you consider updating the wrong comment:

// randomOffset returns between 1 and MAX_SUPPLY

to

// randomOffset returns between 1 and MAX_SUPPLY - 1

because that's what it currently does