Beatland Festival

First Flight #44
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: low
Likelihood: medium
Invalid

Bitwise shift collision in `encodeTokenId` allows token ID ambiguity

Root + Impact

Bitwise shift collision in encodeTokenId allows token ID ambiguity

Description

The FestivalPass::encodeTokenId function combines collectionId and itemId using a left bit shift followed by addition. However, this implemenmtation does not validate that itemId fits within the expected bit range after shifting collectionId. Without overflow checks different pairs can produce the same encoded token ID, causing collisions and breaking token ID uniqueness guarantees.

function encodeTokenId(uint256 collectionId, uint256 itemId) public pure returns (uint256) {
@> return (collectionId << COLLECTION_ID_SHIFT) + itemId;
}

Risk

Likelihood: Low
Although it is easy to cause collisions, the itemId is managed by the system and needs a very large itemId.

Impact: Medium
Token IDs may collide across collections.

Proof of Concept

function test_encodeTokenIdCollision() public view {
uint256 collectionId1 = 1;
uint256 itemId1 = 2 ** 128;
uint256 collectionId2 = 2;
uint256 itemId2 = 0;
assertEq(festivalPass.encodeTokenId(collectionId1, itemId1), festivalPass.encodeTokenId(collectionId2, itemId2));
}

Recommended Mitigation

Apply strict bounds to prevent silent overflowing.

+ uint256 constant ITEM_ID_BITS = 128;
function encodeTokenId(uint256 collectionId, uint256 itemId) public pure returns (uint256) {
+ require(collectionId < (1 << COLLECTION_ID_BITS), "collectionId overflow");
+ require(itemId < (1 << ITEM_ID_BITS), "itemId overflow");
return (collectionId << COLLECTION_ID_SHIFT) + itemId;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
about 1 month ago
inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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