Status DataClose notification

OpenEden Disclosed Report

Duplicate entries in users array due to quota reset leads to enumeration bloat

Company
Created date
Oct 16 2025

Target

https://github.com/OpenEdenHQ/openeden.usdoexpress.audit/tree/f3f31d2ac15e3253cba342229f9d05495f95d6fd

Vulnerability Details

The vulnerability occurs in the quota management logic within setUserQuota(). When a user's quota is set to zero, the function clears authorizedUsers[user] = false and resets their used quota, but does not remove the user from the users array. Subsequently, when reassigning a positive quota to the same user, the condition if (!authorizedUsers[user]) evaluates to true, causing the user to be pushed into the users array again, creating a duplicate entry.

Repeating this reset-and-reassign cycle results in unbounded growth of duplicate entries in the users array, with each cycle adding another duplicate of the same user.

    function setUserQuota(address user, uint256 quota) external onlyOwner {
        uint256 oldQuota = userQuotas[user];
        uint256 usedQuota = usedQuotas[user];

        // Update total allocated accounting
        if (oldQuota > 0) {
            totalAllocated = totalAllocated - oldQuota;
        }

        if (quota > 0) {
            // Check that new quota isn't less than already used amount
            if (quota < usedQuota) {
                revert QuotaExceedsUsed(quota, usedQuota);
            }

            // Check if new allocation fits within total liquidity
            if (totalAllocated + quota > totalLiquidity) {
                revert QuotaExceedsTotal(quota, totalLiquidity - totalAllocated);
            }

            totalAllocated = totalAllocated + quota;

            // Add to users array if new user
            if (!authorizedUsers[user]) {
                users.push(user);
                authorizedUsers[user] = true;
            }
        } else {
            // Removing quota - also clear used quota
            authorizedUsers[user] = false;
            if (usedQuota > 0) {
                totalUsed = totalUsed - usedQuota;
                usedQuotas[user] = 0;
            }
        }

        userQuotas[user] = quota;

        emit QuotaSet(user, quota);
    }

The duplicate entries cause the users array to grow unbounded when quotas are reset to zero and reassigned. This leads to storage bloat and makes operations that enumerate the array increasingly gas-expensive. Functions like getAllUsers() may eventually become unusable due to gas limits when called on-chain with large arrays containing many duplicates.

Validation steps

This behavior can be reproduced through the following sequence:

  1. Owner sets a positive quota for a user, adding them to users array and setting authorizedUsers[user] = true
  2. Owner later sets the user's quota to zero, which sets authorizedUsers[user] = false but leaves the user in the users array
  3. Owner reassigns a positive quota to the same user, triggering the addition logic again and creating a duplicate entry

Attachments

hidden
CommentsReport History
Comments on this report are hidden
Details
Statedisclosed
Severity
Low
Bounty$29
Visibilitypartially
VulnerabilityDoS with Block Gas Limit
Participants (4)
company admin
triage team
triage team
author