Project

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

Non-uniform increase in price of membership Nfts from a lower to the next higher tier in a sponsored DAO allows users to get a higher tier membership for cheap

Summary

If the increase in price of membership Nfts of a sponsored DAO from a lower tier to a higher tier is not uniform, then users can get memberships of a higher tier at a profitable rate by purchasing two Nfts from a lower tier and upgrading to the next higher tier.

Vulnerability Details

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 Nft in the next higher tier. There are no restrictions on the price of purchasing a membership Nft in each tier. So if the price of a membership Nft in a higher tier is greater than double the price of the membership Nft in the next lower tier, then users can simply use the upgrade mechanism to get the higher tier memberships for a cheaper price.

Proof of Concept

Consider an example scenario given below.

  1. A sponsored DAO is created with 7 tiers where the price of membership Nft in tier 6 is 1 USDC and in tier 5, it is 3 USDC.

  2. User 1 purchases 2 Nfts from tier 6 for a cost of 2 USDC and upgrades to tier 5 at a profit of 1 USDC.

  3. On the other hand, user 2 purchases a tier 3 membership for 3 USDC, at a loss of 1 USDC as compared to the upgrade way.

Impact

Users can purchase membership Nfts of a higher tier at a profit by upgrading from a lower tier.

Recommended Mitigation

Charge the user an additional amount in such case.

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.");
+ uint256 fromTierIndexPrice = daos[daoMembershipAddress].tiers[fromTierIndex].price;
+ uint256 toTierIndexPrice = daos[daoMembershipAddress].tiers[fromTierIndex - 1].price;
+ if (fromTierIndexPrice * 2 < toTierIndexPrice) {
+ uint256 difference = toTierIndexPrice - (fromTierIndexPrice * 2);
+ uint256 feeAmount = (difference * 20) / 100;
+ IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, feeAmount);
+ IERC20(daos[daoMembershipAddress].currency).transferFrom(
+ _msgSender(), daoMembershipAddress, difference - feeAmount
+ );
+ }
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!