Closed howlbot-integration[bot] closed 1 month ago
koolexcrypto marked the issue as unsatisfactory: Invalid
I think there is a misunderstanding regarding my submission. It's not duplicate of #224. This issue highlights the potential differences in entropy values, while #224 asserts that performanceFactor cannot be zero. Let me explain again with more details.
Note: Sponsor has also confirmed (in Discord) that this is a valid issue in the game mechanics.
Based on the Traitforge documentation, the entropy value should be a random number within the range of [100,000 to 999,999]. In the current system, entropy values are derived from slots, which involves extracting 6 digits from a random position within a 78-digit number. Due to this extraction process, the resulting 6-digit number may sometimes be smaller if the extracted digits start with zeros.
The system addresses this issue by padding the number with leading zeros until it reaches a 6-digit length. Consequently, obtaining an NFT with an entropy value of 100,000 has a significantly higher probability compared to obtaining one with an entropy value of 123,456. This discrepancy impacts the game mechanics, as entropy is a crucial component for NFTs.
1) The slot can directly yield 100,000. 2) 10,000 -> 100,000 (padding) 3) 1,000 -> 100,000 (padding) 4) 100 -> 100,000 (padding) 5) 10 -> 100,000 (padding) 6) 1 -> 100,000 (padding)
There are 6 ways to generate an entropy value of 100,000.
1) The slot can directly yield 123,456.
There is only 1 way to generate an entropy value of 123,456.
Thus, obtaining an NFT with an entropy value of 100,000 is 6 times more likely than obtaining one with 123,456. This is just one example, but many more exist.
In my original submission, I mentioned that non-aging NFTs have a higher probability of being generated compared to aging NFTs. This issue extends further. Consider this example:
Entropy: 123,456 Entropy[0] = PhysicalTrait1 Entropy[1] = PhysicalTrait2 Entropy[2] = PhysicalTrait3 Entropy[3] = PhysicalTrait4 Entropy[4] = Colour1 & ForgePotential Entropy[5] = Colour2 Entropy / 40 = InitialNukeFactor Entropy % 10 = PerformanceFactor Entropy % 3 ? 0 == Role
Forge potential is another key component for entities, and NFTs with a forge potential of 0 have a higher likelihood of being minted than others.
There are two possible ways to obtain a non-forgeable NFT:
Normal method (no padding): 10% Padding method: If the extracted value from the slot has fewer than 5 digits (e.g., 1234), it will be non-forgeable. Calculation: 10% for the first digit, then 10% of that 10% for the second digit = 11% total probability of a non-forgeable NFT ( it should be 10% for fair random distribution ). For non-aging NFTs, this probability is 20%, as previously mentioned ( it should be 10% for fair random distribution ).
I believe this padding algorithm should be reconsidered for non-6-digit slots, as it causes significant differences in probabilities.
koolexcrypto marked the issue as not a duplicate
koolexcrypto removed the grade
koolexcrypto marked the issue as primary issue
koolexcrypto marked the issue as nullified
koolexcrypto marked the issue as not nullified
This is a valid issue.
To determine the severity, could you please refer where it is mentioned in the docs that the probability should be 1/10 or 10% ?
@koolexcrypto
The documentation states that the entropy value should be a random number between 100,000 and 999,999. If we focus on the performance factor for NFTs (the last digit of the entropy), there are 10 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. Since 0 is just one of these 10 possible values, it has a probability of 1/10, which equals 10%.
Thank you for your input.
However, given that the impact is
Wrong main functionality
with no real harm demonstrated. I believe, this can be a QA as I don't see a Med risk here.
koolexcrypto changed the severity to QA (Quality Assurance)
koolexcrypto marked the issue as grade-c
@koolexcrypto
The game mechanics are significantly impacted by poor randomness. As a result, most NFTs will have a lower performance factor. I provided a proof of concept in my original submission. The performance factor greatly affects various aspects of the game, such as the nuking functionality. Due to the flawed randomness, most users will have non-aging entities, which will lead to their nuking rewards being significantly lower than expected.
Taking into account the sponsor's input
Valid but not detrimental
stands as is
Lines of code
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/NukeFund/NukeFund.sol#L126 https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/NukeFund/NukeFund.sol#L147-L148 https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/NukeFund/NukeFund.sol#L165-L165
Vulnerability details
Vulnerability Details
Age is a key component in trait forge entities. It's calculated using the entropy value of entity. While calculating the age of NFT, it directly multiply value by performance factor. Performance factor is calculated using the last digit of the entropy and the last digit also can be 0. If it's 0, that means it's non-aging entity.
The probability of getting non-aging NFT is 20% (It's higher than all the other performance factor values). The reason of this is the padding operation of entropy calculation.
Calculation: First situation: Last digit of entropy is 0: There can be 10 possible number for last digit [0,9] which makes 10%
Second situation: If the cutted slot position starts with 0 it will end with 0: In entropy calculation, using slotIndex and numberIndex it cuts 6 digit from random slot and if this number doesn't have 6 digits, it pads the value with 0. (eg: cutted value is 12345, it will be converted to 123450 ), So it makes another 10% possibility and in conclusion it makes 20% of getting non-aging NFT.
Padding code:
According to the documents and sponsor, this possibility should be equal to other possibilities:
https://ibb.co/xCf6fMq (image link from imgbb.com)
Impact
Wrong main functionality
Proof of Concept
You can check the approximation using this test
Tools Used
Foundry and manual review
Recommended Mitigation Steps
There can be many solution to this problem and my suggestion is if entropy is derived from padding adding the last digit of not-padded entropy value to padded version will keep the probability at 10% level
Assessed type
Math