Project

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

Lack of Validation for Zero Tier Prices in joinDAO Function Could Lead to Division by Zero and Financial Losses

Summary

The lack of validation for zero tier prices in the joinDAO function creates a critical vulnerability where a division by zero could occur during the platform fees calculation. This could lead to transaction reverts and denial of service for legitimate membership purchases. More significantly, if the tier price is zero and the platform fee calculation doesn't revert (due to compiler optimizations or future solidity versions handling division by zero differently), users could potentially join tiers without paying the required fees, leading to financial losses for the protocol and disruption of the DAO's economic model.

The issue stems from the direct usage of the tier price in fee calculations without prior validation. The function retrieves the tier price from storage and immediately uses it in arithmetic operations without ensuring its value is greater than zero. In Solidity, division operations with zero can lead to unexpected behavior and transaction reverts, making certain tiers completely inaccessible even if they were meant to be free. This becomes particularly problematic in scenarios where tier prices are managed through external admin functions or could be set to zero due to contract upgrades or initialization issues.

https://github.com/Cyfrin/2024-11-one-world/blob/main/contracts/dao/MembershipFactory.sol#L140

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; // Potential division by zero if tierPrice is 0
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);
}

Recommended Fix

Implement a proper validation check for the tier price before performing any calculations. If free tiers are intended to be supported, handle them with a specific condition:

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;
require(tierPrice > 0, "Invalid tier price");
uint256 platformFees = (20 * tierPrice) / 100;
uint256 daoAmount = tierPrice - platformFees;
daos[daoMembershipAddress].tiers[tierIndex].minted += 1;
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, daoAmount);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, tierIndex);
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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