encodeTokenId Leads to Token ID Collision and ImpersonationThe protocol uses bitmasking to pack a collectionId and an itemId into a single uint256 tokenId. The decodeTokenId function assumes that the itemId occupies the lower 128 bits and the collectionId occupies the upper 128 bits.
The vulnerability lies in the encodeTokenId function, which accepts itemId as a uint256 without validating that it fits within the designated 128 bits. The function uses addition (+) . If an itemId larger than 2**128 - 1 is provided, the addition "carries over" the excess bits, which corrupts the upper 128 bits reserved for the collectionId.
This breaks the critical invariant decodeTokenId(encodeTokenId(c, i)) == (c, i) and allows an attacker to predictably generate a tokenId that collides with a legitimate one.
Likelihood:
Reason 1 : The exploit occurs whenever the itemId becomes greater than or equal to 2**128 to any public-facing function that uses encodeTokenId to generate a token's unique identifier.
Impact:
Improper input validation in the encodeTokenId function allows a malicious actor to craft inputs that produce a tokenId identical to that of a separate, legitimate token. This collision enables an attacker to mint a token that impersonates another existing asset.
Add the following to your test suite , the test will fail at assertEq(decodedItem, itemId)
It is strongly recommended to enforce size constraints on the inputs to encodeTokenId. The most robust and gas-efficient solution is to change the function's input parameters from uint256 to uint128.
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.