Solidity mappings do not provide a way to iterate over keys natively. However, if developers use an array to track mapping keys for iteration, looping through the keys can lead to unbounded loops if the array grows indefinitely
Game
If this auxiliary array grows without restriction, what will looping over it do?
// SPDX-License-Identifier: MIT// Open me in VSCode and really think before opening the hints!// Add @audit tags wherever suspicious// Go to the solidity docs to complete missing knowledge of what's happening here// Solve by drafting a fix!pragmasolidity ^0.8.0;contract UnrestrictedMappingGame {mapping(address=>uint256) public balances;address[] public users;// Add or update a user's balancefunctionsetBalance(address user,uint256 amount) public {if (balances[user] ==0) { users.push(user); } balances[user] = amount; }// Sum up all balancesfunctiontotalBalances() publicviewreturns (uint256) {uint256 total =0;for (uint256 i =0; i < users.length; i++) { total += balances[users[i]]; }return total; }}
Consider how you can limit the size of the users array to ensure predictable gas consumption for functions like totalBalances.
Think about how precomputing or chunking operations might help avoid the need for full iteration in a single transaction.
contract UnrestrictedMappingGame {mapping(address=>uint256) public balances;address[] public users;uint256public maxUsers =1000; // Fix: Restrict the maximum number of usersfunctionsetBalance(address user,uint256 amount) public {if (balances[user] ==0) {require(users.length < maxUsers,"User limit reached"); // Fix: Enforce user limit users.push(user); } balances[user] = amount; }functiontotalBalances(uint256 start,uint256 end) publicviewreturns (uint256) {require(end > start && end <= users.length,"Invalid range");uint256 total =0;for (uint256 i = start; i < end; i++) { total += balances[users[i]]; }return total; }}