The encodeTokenId() and decodeTokenId() functions combine a collectionId and itemId into a single uint256 token ID by shifting the collectionId left by 128 bits and adding the itemId in the lower 128 bits.
However, decodeTokenId() assumes the itemId always fits into 128 bits without validation. If itemId exceeds 128 bits, it will be silently truncated during decoding, causing loss of uniqueness and potential collisions between token IDs.
Likelihood: Low
If a large itemId (> 2^128) is ever used, this truncation will occur.
Lack of input validation in token creation enables this scenario.
Impact: Low
Token ID collisions may happen due to truncated itemIds.
Incorrect URIs, duplicate token minting, and broken uniqueness guarantees.
This could undermine system correctness or trust in token authenticity.
Explanation:
In this example, an extremely large itemId that exceeds the 128-bit size limit is encoded with a valid collectionId. When decoding, the itemId portion is truncated to fit into 128 bits, resulting in a value different from the original itemId. This demonstrates how the current decode logic silently loses information, which can cause token ID collisions and incorrect behavior.
The encodeTokenId function now includes a require statement that enforces the itemId to fit within 128 bits. This prevents any overflow or truncation issues later during decoding.
The encoding operation uses a bitwise OR (|) instead of addition (+). This is more appropriate for combining two values stored in distinct bit ranges, ensuring no accidental carry or overlap.
The decodeTokenId function extracts the itemId using a bitmask (tokenId & ((1 << COLLECTION_ID_SHIFT) - 1)), which safely recovers the lower 128 bits as the itemId without truncation.
These changes guarantee that encoding and decoding are perfectly reversible and maintain the uniqueness and correctness of token IDs.
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.