Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: medium
Invalid

Critical State Loss in DAO Tier Management

Github

Summary

The updateDAOMembership function in the MembershipFactory contract contains a critical vulnerability where reducing the number of tiers can result in loss of token state tracking while the tokens remain in circulation. This creates a permanent mismatch between the recorded state and actual token distribution.

Vulnerability Details

The vulnerability exists in the following code section:

function updateDAOMembership(string calldata ensName, TierConfig[] memory tierConfigs)
external onlyRole(EXTERNAL_CALLER) returns (address) {
// ...
DAOConfig storage dao = daos[daoAddress];
// 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;
}
}
// Reset and update the tiers array
delete dao.tiers;
for (uint256 i = 0; i < tierConfigs.length; i++) {
dao.tiers.push(tierConfigs[i]);
}
// ...
}

The vulnerability stems from:

  • No validation of existing tokens in tiers being removed

  • Destructive state update pattern using delete

  • Assumption that tiers can be safely removed without token consideration

Step-by-Step Breakdown:

  • The function receives new tier configurations that can be shorter than existing tiers

  • It only preserves minted values for tiers that will continue to exist

  • The entire tiers array is deleted with delete dao.tiers

  • New tiers are added with preserved minted values only for continuing tiers

  • Any tokens minted in removed tiers are no longer tracked but remain valid

Example:

// Initial State (3 tiers):
dao.tiers = [
{price: 100, amount: 10, minted: 5}, // Tier 0
{price: 200, amount: 5, minted: 3}, // Tier 1
{price: 300, amount: 3, minted: 2} // Tier 2
];
// Update to 2 tiers:
tierConfigs = [
{price: 150, amount: 10, minted: 5}, // Preserved
{price: 250, amount: 5, minted: 3} // Preserved
];
// Result: 2 tokens from Tier 2 still exist but are untracked

Impact

The contract loses track of minted tokens in removed tiers and tokens continue to exist but are no longer tracked. Also DAO configuration no longer reflects actual token distribution.

Tools Used

Manual Review

Recommendations

Apply the following idea:

// RECOMMENDATION:
function secureUpdateDAOMembership(string calldata ensName, TierConfig[] memory tierConfigs) {
DAOConfig storage dao = daos[daoAddress];
// Ensure no tokens exist in tiers being removed
if (tierConfigs.length < dao.tiers.length) {
for (uint256 i = tierConfigs.length; i < dao.tiers.length; i++) {
require(dao.tiers[i].minted == 0, "Cannot remove tier with existing tokens");
}
}
// Rest of the function remains the same
delete dao.tiers;
for (uint256 i = 0; i < tierConfigs.length; i++) {
if (i < dao.tiers.length) {
tierConfigs[i].minted = dao.tiers[i].minted;
}
dao.tiers.push(tierConfigs[i]);
}
}
Updates

Lead Judging Commences

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

Support

FAQs

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