Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: low
Valid

Updating tier configurations can lock tiers, preventing new members from joining a DAO

Summary

When updating tier configurations for a specific DAO, there is no validation on the minted field of the TierConfig struct, meaning that tier configurations can be updated with non-zero minted values even when the supply for a given tier index is actually zero.

Vulnerability Details

In MembershipFactory.sol, the updateDAOMembership function does not verify whether tierConfigs[i].minted is zero when adding new tiers.

for (uint256 i = 0; i < tierConfigs.length; i++) {
dao.tiers.push(tierConfigs[i]);
maxMembers += tierConfigs[i].amount;
}

It only preserves the minted values for existing tiers based on the current configuration length. This behavior means that any new tiers added during the update may have arbitrary non-zero minted values, as there is no validation to ensure they are initialized to zero.

// Preserve minted values and adjust the length of dao.tiers
for (uint256 i = 0; i < tierConfigs.length; i++) {
if (i < dao.tiers.length) {
tierConfigs[i].minted = dao.tiers[i].minted;
}
}

Example scenario:

  1. DAO A has the following tier configurations:

    • tier1.minted = 10

    • tier2.minted = 10

  2. New tierConfigs values are:

    • tier1.minted = 10

    • tier2.minted = 10

    • tier3.minted = 15 (incorrectly set)

  3. The new tierConfigs.length is 3, while the old dao.tiers.length is 2.

  4. As a result, tier1.minted and tier2.minted are preserved as 10, but tier3.minted will be set to 15, as there is no validation to ensure that minted is initialized to zero for new tiers.

Because the updateDAOMembership function preserves the minted values during each call, if the function is invoked again, the minted values for existing tiers will continue to persist and cannot be fixed.

Impact

Each tier has a defined amount, which represents the total number of members allowed in that tier. minted is a counter that tracks the number of members who have joined that specific tier.

When someone attempts to join a DAO using the joinDAO function, the following check ensures that there is room in the tier:

require(daos[daoMembershipAddress].tiers[tierIndex].amount > daos[daoMembershipAddress].tiers[tierIndex].minted, "Tier full.");

Example Scenario:

Suppose the amount for tier 3 is set to 10, meaning it can accommodate up to 10 members. However, if the minted value for tier 3 is set to 15, this check will evaluate as 10 > 15, causing the function to revert with a "Tier full" error. As a result, no new members will be able to join tier 3, effectively locking it and preventing the DAO from onboarding new members in that tier.

Tools Used

Manual Review

Recommendations

Add a validation check for new tiers to ensure that any new tier configurations being added do not have a non-zero minted value.

// Preserve minted values and adjust the length of dao.tiers
for (uint256 i = 0; i < tierConfigs.length; i++) {
if (i < dao.tiers.length) {
tierConfigs[i].minted = dao.tiers[i].minted;
+ } else {
+ require(tierConfigs[i].minted == 0, "Invalid tier config");
+ }
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge
8 months ago
0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

falendar Submitter
8 months ago
0xbrivan2 Lead Judge
8 months ago
0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

minted value is not asserted to be zero when adding new tiers

Support

FAQs

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