getUserMemorabiliaDetailed() can cause permanent DoSDescription
The getUserMemorabiliaDetailed() function contains nested unbounded loops that iterate through all collection IDs and all items within each collection. There are no limits on:
The number of collections the organizer can create
The maxSupply (and thus currentItemId) for each collection
If the organizer creates many collections with high item counts, the gas cost can exceed the block gas limit, making this function permanently uncallable.
Impact
HIGH severity due to permanent DoS:
Permanent DoS: Once gas cost exceeds block gas limit (~30M gas), the function will always revert with out-of-gas error
Loss of Functionality: Users and front-ends cannot retrieve user memorabilia data, breaking core protocol functionality
Griefing Attack: Malicious or compromised organizer can intentionally DoS the function by creating many collections
Front-end Breaking: Any dApp relying on this view function will be unable to display user collections
No Recovery: Once DoS occurs, the function is permanently broken with no way to recover
Proof of Concept
Attack scenario:
Organizer creates 100 collections, each with maxSupply = 1000
Total iterations: 100 collections × 1000 items = 100,000 iterations per loop
Function has TWO identical nested loops, so 200,000 total iterations
Each iteration performs: encodeTokenId(), balanceOf() (SLOAD), and comparisons
Gas estimation:
balanceOf(): ~2,100 gas per call (cold SLOAD)
200,000 iterations × 2,100 gas ≈ 420,000,000 gas
Block gas limit: ~30,000,000 gas
Result: Function exceeds block gas limit by 14x and always reverts
Even with fewer collections, the quadratic complexity makes DoS inevitable as the protocol grows.
Mitigation
Implement pagination to limit iterations per call:
This allows callers to paginate through collections in batches (e.g., 50 at a time), preventing DoS while maintaining functionality.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.