Project

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

Joining a tier can be DOSed because of the minted value not being updated in upgradeTier

Summary

the joinDAO method checks for the minted value of a tier before minting NFTs in the tier. However the NFTs minted in a tier are burned when they are used in upgrading to the next tier.

This means an user who has minted all the tier NFTS and then used it to upgrade to the next tier, will not be in posession of the NFT, and the NFT will not be in circulation as well.

However the end result is that no more tier NFTs for that particular tier can be minted again because of the minted check in joinDAO

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

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

This is in stark contrast to the case when the user buys an upgraded tier NFT in the first place, leaving the lower tiers unaffected.

Vulnerability Details

joinDAO checks for minted variable exceeding amount available for a tier NFT

function joinDAO(address daoMembershipAddress, uint256 tierIndex) external {
require(daos[daoMembershipAddress].noOfTiers > tierIndex, "Invalid tier.");
@> require(daos[daoMembershipAddress].tiers[tierIndex].amount > daos[daoMembershipAddress].tiers[tierIndex].minted, "Tier full.");
uint256 tierPrice = daos[daoMembershipAddress].tiers[tierIndex].price;
uint256 platformFees = (20 * tierPrice) / 100;

UpgradeTier doesn't change the minted value of the tier amount when burning tier NFTs.

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);
}

Using this, an user can mint till the amount for a tier is reached, then upgradeTier. This will disallow anyone else from getting the initial tier minted.

Impact

No tier NFTs can be minted for tiers that are not the top-most tier (The tiers that have another tier to upgrade to are vulnerable)

Tools Used

manual analysis

Recommendations

update the minted value for the upgradeTier method, that is,

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
IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Appeal created

copperscrewer Submitter
9 months ago
0xbrivan2 Lead Judge
9 months ago
0xbrivan2 Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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