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

tokenURI probabilities are not equally distributed

Summary

The [Documentation] reports that

You'll see the tokenURI function returns one of 4 random Mondrian art paintings. Each should have equal distribution and be random.

The tokenURI method is defined in MondrianWallet.sol#L161-L175. It is true that this method returns one of 4 random Mondrian art paintings. However, probability is not equally distributed.

Vulnerability Details

The tokenURI method is defined in MondrianWallet.sol#L161-L175:

function tokenURI(uint256 tokenId) public view override returns (string memory) {
if (ownerOf(tokenId) == address(0)) {
revert MondrainWallet__InvalidTokenId();
}
uint256 modNumber = tokenId % 10;
if (modNumber == 0) {
return ART_ONE;
} else if (modNumber == 1) {
return ART_TWO;
} else if (modNumber == 2) {
return ART_THREE;
} else {
return ART_FOUR;
}
}

The return value is computed from the value of tokenID, using modulus by 10. In the following table, we report the probability distribution:

modNumber tokenURI likehood
0 ART_ONE 10%
1 ART_TWO 10%
2 ART_THREE 10%
3 ART_FOUR 10%
4 ART_FOUR 10%
5 ART_FOUR 10%
6 ART_FOUR 10%
7 ART_FOUR 10%
8 ART_FOUR 10%
9 ART_FOUR 10%

This means that the likehood to obtain ART_ONE=10%, ART_TWO=10%, ART_THREE=10%, ART_FOUR=70%

Impact

The declared rarity of a specific tokenURI is very different from the rarity declared in documentations. This fact
could strongly impact the secondary market of MondianWallet NFT. A buyer could assume that an NFT is rarer than the real likehood to find it.
If the market is not aware about this from the beginning, the discover of this issue could strongly impact the market equilibrium.

Tools Used

Visual inspection

Recommendations

Let's change the tokenUri method in this way:

function tokenURI(uint256 tokenId) public view override returns (string memory) {
if (ownerOf(tokenId) == address(0)) {
revert MondrainWallet__InvalidTokenId();
}
- uint256 modNumber = tokenId % 10;
+ uint256 modNumber = tokenId % 4;
if (modNumber == 0) {
return ART_ONE;
} else if (modNumber == 1) {
return ART_TWO;
} else if (modNumber == 2) {
return ART_THREE;
} else {
return ART_FOUR;
}
}
Updates

Lead Judging Commences

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

NFT's should have equal distribution

Support

FAQs

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