Project

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

Upgrading membership in a sponsored DAO does not update the tier details leading to a mismatch in the actual and expected number of members in each tier

Summary

A sponsored DAO consists of 7 tiers where users can upgrade their membership by burning two Nfts from a lower tier and minting a new memebership Nft in the next higher tier. However, during the upgrade, the minting and burning of membership NFts is not accounted for in the DAO tier details in storage, resulting in a disparity in the expected and the actual number of memeberships.

Vulnerability Details

A sponsored DAO has 7 tiers whose details such as the number of memebership Nfts available in each tier, the number of memebership Nfts already minted, the price of purchasing a membership Nft in a tier, and the associated voting power are all stored in storage. However, as can be seen from the code below, the necessary accouting isn't done while upgrading.

/// @notice Allows users to upgrade their tier within a sponsored DAO
/// @param daoMembershipAddress The address of the DAO membership NFT
/// @param fromTierIndex The current tier index of the user
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);
}

This leads to a lesser number of memberships available in the lower tier, and a breach in the total number of memberships in the tier being upgraded to.

Proof of Concept

Consider an example scenario given below.

  1. A sponsored DAO is created with 5 memberships available in each tier.

  2. User 1 purchases 2 memberships in tier 1, and upgrades to tier 0, the highest tier.

  3. Now the expected number of memberships available in tier 1 should be 5, and in tier 0, it should be 4.

  4. However, since tier details aren't updated, only 3 membership Nfts are purchasable in tier 1, and 5 in tier 0. Now, if all of tier 0 Nfts are minted, it will contain 6 members instead of the 5 members that were allowed in the tier.

Impact

Since accounting isn't handled correctly, the number of membership Nfts purchasable in the lower tier will decrease despite the fact that Nfts were burned during the upgrade, and the number of Nfts in the next higher tier will increase. This breaches the limit set on the number of Nfts available in the tier during DAO creation.

Recommended Mitigation

Update the DAO tiers during an upgrade.

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.");
+ daos[daoMembershipAddress].tiers[fromTierIndex].minted -= 2;
+ daos[daoMembershipAddress].tiers[fromTierIndex - 1].minted += 1;
IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
}

Tools Used

Manual review.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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

Give us feedback!