Project

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

Lack of existing membership check

Summary

The MembershipFactory contract does not check if a user already has a membership in a specific tier before allowing them to join the DAO again.

Vulnerability Details

The current implementation of the joinDAO function in the MembershipFactory contract does not include any checks to verify if the user already has a membership in the specified tier. This allows users to join the DAO multiple times in the same tier, which goes against the intended membership model.

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

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

Impact

The DAO's membership model is designed to have one membership per user per tier. Allowing users to join multiple times in the same tier breaks this assumption and can lead to one member posing as multiple members making a proposal.

Tools Used

Manual review

Recommendations

The joinDAO function in the MembershipFactory contract should be modified to include a check for existing membership before allowing a user to join a specific tier. This can be done by maintaining a mapping of users to their owned memberships and checking against it before minting a new membership:

mapping(address => mapping(address => bool)) public userMemberships;
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.");
require(!userMemberships[_msgSender()][daoMembershipAddress], "User already has membership in this tier.");
// Rest of the function remains the same
uint256 tierPrice = daos[daoMembershipAddress].tiers[tierIndex].price;
// ...
userMemberships[_msgSender()][daoMembershipAddress] = true;
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, tierIndex);
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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