Beatland Festival

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

The `getUserMemorabiliaDetailed` function performs **nested unbounded loops**, leading to failure in results

Root + Impact

Root Cause

The getUserMemorabiliaDetailed function performs nested unbounded loops over:

  • All collections (1 → nextCollectionId)

  • All items in each collection (1 → currentItemId)

for (uint256 cId = 1; cId < nextCollectionId; cId++) {
for (uint256 iId = 1; iId < collections[cId].currentItemId; iId++) {
uint256 tokenId = encodeTokenId(cId, iId);
if (balanceOf(user, tokenId) > 0) {
count++;
}
}
}

This results in O(n × m) complexity, where:

  • n = number of collections

  • m = items per collection

As these values grow, the function becomes increasingly expensive and can exceed the block gas limit.


Impact

  • Denial of Service (DoS)
    Function becomes uncallable due to gas limits when collections/items grow large

  • Frontend / RPC failures
    Wallets or dApps calling this view function may fail or timeout

  • Poor scalability
    Contract design does not scale with increasing usage


Description

  • Under normal behavior, view functions should remain efficient and callable regardless of system growth, especially when intended for frontend consumption.

  • In the current implementation, getUserMemorabiliaDetailed iterates over all collections and all items within them. As the protocol grows, this leads to excessive gas consumption, eventually making the function unusable due to block gas limits or RPC restrictions.


Risk

Likelihood:

  • Occurs as the number of collections and minted items increases over time

  • Triggered when users query their holdings via frontend or direct RPC calls


Impact:

  • Function becomes unusable for large datasets

  • Breaks user experience and off-chain integrations


Recommended Mitigation

Include pagination to reduce the collection frames, this allows reduction in size of loop

+ function getUserMemorabiliaPaginated(
+ address user,
+ uint256 startCollection,
+ uint256 endCollection
+ ) external view returns (...) {
+ // Iterate only within range
+ }
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 3 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!