Project

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

Restricted and hardcoded tier upgrade path

Summary

Restricted and hardcoded tier upgrade path.

Vulnerability Details

The upgradeTier function implements a rigid upgrade system where members can only move to the next immediate tier up. The target tier is automatically calculated by subtracting 1 from the current tier index (fromTierIndex - 1), removing any flexibility in the upgrade path.

function upgradeTier(address daoMembershipAddress, uint256 fromTierIndex) external {
require(daos[daoMembershipAddress].daoType == DAOType.SPONSORED, "Upgrade not allowed.");
require(daos[daoMembershipAddress].noOfTiers >= fromTierIndex + 1, "No higher tier available.");
IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
}

https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/dao/MembershipFactory.sol#L155C3-L161C6

Here is how the current implementation works:

Tier System Structure:

  • Lower index numbers represent higher tiers (e.g., Tier 0 is highest)

  • Tier 3 → Tier 2 → Tier 1 → Tier 0 (ascending value)

Token Operations:

// If member is in Tier 3 (fromTierIndex = 3)
burn(_msgSender(), 3, 2); // Burns 2 tokens from Tier 3
mint(_msgSender(), 2, 1); // Mints 1 token for Tier 2

Impact

  • Members cannot skip tiers (e.g., Tier 3 to Tier 1)

  • Forces sequential upgrades through all tiers

  • Increases transaction costs for members wanting higher tiers

  • Limits DAO flexibility in membership management

Tools Used

Manual review

Recommendations

Upgrade should be made flexible:

function upgradeTier(
address daoMembershipAddress,
uint256 fromTierIndex,
uint256 toTierIndex
) external {
require(toTierIndex < fromTierIndex, "Must upgrade to higher tier");
require(daos[daoMembershipAddress].daoType == DAOType.SPONSORED, "Upgrade not allowed.");
IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 1);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), toTierIndex, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, toTierIndex);
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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