Project

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

Lack of Restriction Allows Users to Re-Join a DAO After Removal

Description

In the One World project, if a user breaks the terms and conditions, a proposal can be passed to remove that user from the DAO, if it receives enough votes in favor. The removal process uses the MembershipERC1155::burnBatch() or MembershipERC1155::burnBatchMultiple() function, which effectively removes all membership tokens held by the user.

However, the current implementation has a flaw: the user can rejoin the same DAO after his removed, simply by purchasing a new membership token through the MembershipFactory::joinDAO() function. This allows users who have been removed to bypass their removal by acquiring membership again. Ideally, the system should prevent users from rejoining the DAO once removed.

Impact

This vulnerability undermines the effectiveness of the DAO’s membership removal process. Users who are removed for violations can easily rejoin, which could lead to repeated rule-breaking and diminish the integrity of the DAO’s community governance.

Proof of Concept

  1. A user is removed from the DAO by passing a proposal that invokes MembershipERC1155::burnBatch(), effectively burning their membership tokens.

  2. The removed user then calls MembershipFactory::joinDAO(), allowing them to repurchase a membership token and rejoin the DAO without restriction.

Recommended Mitigation

Implement a mechanism to track removed users and prevent them from rejoining the DAO. This could involve maintaining a blacklist of addresses that are blocked from using joinDAO() after being removed.

contract MembershipFactory is AccessControl, NativeMetaTransaction {
+ mapping (address account => mapping (address dao => bool)) public isBlacklisted;
+ function removeUserFromDAO(address dao, address user) external onlyRole(EXTERNAL_CALLER) {
+ IMembershipERC1155(dao).burnBatch(user);
+ isBlacklisted[user][dao] = true;
+ }
function joinDAO(address daoMembershipAddress, uint256 tierIndex) external {
+ require(!isBlacklisted[_msgSender()][daoMembershipAddress], "MembershipFactory: User is Blacklisted.")
// ignore rest of the code
}
}
contract MembershipERC1155 is ERC1155Upgradeable, AccessControlUpgradeable, IMembershipERC1155 {
function initialize(
string memory name_,
string memory symbol_,
string memory uri_,
address creator_,
address currency_,
+ address membershipFactory_
) external initializer {
_name = name_;
_symbol = symbol_;
creator = creator_;
currency = currency_;
+ membershipFactory = membershipFactory_;
_setURI(uri_);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(DAO_CREATOR, creator_);
_grantRole(OWP_FACTORY_ROLE, msg.sender);
}
function _update(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual override(ERC1155Upgradeable) {
+ require(!IMembershipFactory(membershipFactory).isBlacklisted(to, address(this)), "MembershipERC1155: User is Blacklisted and Cannot Receive MembershipToken.");
if (from != address(0)) saveProfit(from);
if (to != address(0)) saveProfit(to);
super._update(from, to, ids, amounts);
}
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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