Summary
The upgradeTier
function does not enforce a fee check, allowing users to bypass tier-specific pricing.
Vulnerability Details
The joinDAO
function calculates and charges a tier-specific price when joining a DAO tier, as shown below:
File: MembershipFactory.sol
140: function joinDAO(address daoMembershipAddress, uint256 tierIndex) external {
141: require(daos[daoMembershipAddress].noOfTiers > tierIndex, "Invalid tier.");
142: require(daos[daoMembershipAddress].tiers[tierIndex].amount > daos[daoMembershipAddress].tiers[tierIndex].minted, "Tier full.");
143: @> uint256 tierPrice = daos[daoMembershipAddress].tiers[tierIndex].price;
144: @> uint256 platformFees = (20 * tierPrice) / 100;
145: daos[daoMembershipAddress].tiers[tierIndex].minted += 1;
146: @> IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
147: @> IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, tierPrice - platformFees);
148: IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
149: emit UserJoinedDAO(_msgSender(), daoMembershipAddress, tierIndex);
150: }
In contrast, the upgradeTier
function does not perform a fee check, meaning users could join a lower-cost tier and upgrade without paying the higher tier’s price. This could suggest that all tiers are intended to have the same price, which may not align with the intended tier classification structure unless following a first-come, first-served (FCFS) model.
File: MembershipFactory.sol
152:
153:
154:
155: function upgradeTier(address daoMembershipAddress, uint256 fromTierIndex) external {
156: require(daos[daoMembershipAddress].daoType == DAOType.SPONSORED, "Upgrade not allowed.");
157: require(daos[daoMembershipAddress].noOfTiers >= fromTierIndex + 1, "No higher tier available.");
158: IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
159: IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
160: emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
161: }
Impact
Users can avoid paying the appropriate tier price by initially joining a lower-priced tier and then upgrading without an additional fee.
Tools Used
Manual analysis
Recommendations
Add a fee check in the upgradeTier
function to enforce tier-specific pricing when upgrading and/or require some additional payment or refund when there is discrepancy between the tier pricing.