Project

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

Inconsistent Token Logic Preventing Tier Upgrades

Summary

The current DAO smart contract structure limits users from upgrading their tier due to a shortage of tokens in their accounts and tier capacity constraints. When a user joins the DAO, only one membership token is minted to their account for the chosen tier. However, to upgrade to a higher tier, two tokens are required to be burned from the lower tier. Since users receive only one token upon joining, they cannot fulfill the token burn requirement, making tier upgrades unachievable. Additionally, even if users attempt to rejoin to gain additional tokens, they may be prevented if the specific tier they wish to rejoin is already at full capacity.

Vulnerability Details

When users join a DAO through joinDAO, they are minted 1 token for their selected tier.

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;
daos[daoMembershipAddress].tiers[tierIndex].minted += 1;
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, tierPrice - platformFees);
>> IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, tierIndex);
}

When users attempt to upgrade their tier through upgradeTier, the function requires 2 tokens to be burned from the current tier to proceed with the 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.");
>> IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
}

So a user attempts to obtain more tokens by rejoining the same tier but it could be unsuccessful if the tier's maximum capacity is reached, due to a check in the joinDAO function that restricts new entries when the tier is full.

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

Scenario

  • A user joins a DAO at tier 4 and receives one token.

  • The user wishes to upgrade to tier 3, which requires burning two tokens.

  • The user attempts to rejoin tier 4 to acquire an additional token but finds the tier is full.

  • As a result, the user is unable to upgrade to tier 3 due to insufficient tokens.

Impact

Users are permanently blocked from upgrading to higher tiers due to the 2-token burn requirement that cannot be fulfilled with the 1-token holding from joining

Tools Used

Manual Review

Recommendations

Implement a mechanism to allow users obtain additional tokens even if the tier is full, solely for the purpose of meeting upgrade requirements without impacting the maximum user capacity.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice
0xbrivan2 Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!