Project

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

Price paid to `MembershipERC1155` is not distributed and will be stuck in contract.

Summary

In MembershipFactory, any user can create a DAO for people to join in, to join, users would need to pay the selected currency set by DAO creator. The price of each tier's token will be splitted between the membership token contract and the platform. However, when price tokens are transferred, they are not distributed into profit, nor can be claimed by DAO creator.

Vulnerability Details

Here, in joinDAO:

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

And we can see, tokens are transferred to daoMembershipAddress, and according to createNewDAOMembership, this is the proxy's address for the implementation:

TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
membershipImplementation,
address(proxyAdmin),
abi.encodeWithSignature("initialize(string,string,string,address,address)", daoConfig.ensname, "OWP", baseURI, _msgSender(), daoConfig.currency)
);
DAOConfig storage dao = daos[address(proxy)];
dao.ensname = daoConfig.ensname;
dao.daoType = daoConfig.daoType;
dao.currency = daoConfig.currency;
dao.maxMembers = daoConfig.maxMembers;
dao.noOfTiers = daoConfig.noOfTiers;

But as this is a contract, and based on the fact that MembershipERC1155, does not have a function to withdraw tokens, all currency tokens sent will be stuck. As they also don't contribute to the prize pool, since the only way is via spendProfit:

function sendProfit(uint256 amount) external {
uint256 _totalSupply = totalSupply;
if (_totalSupply > 0) {
totalProfit += (amount * ACCURACY) / _totalSupply;
IERC20(currency).safeTransferFrom(msg.sender, address(this), amount);
emit Profit(amount);
} else {
IERC20(currency).safeTransferFrom(msg.sender, creator, amount); // Redirect profit to creator if no supply
}
}

But there is no way to self-transfer, as it would require approval first.

Impact

All token sales money will be stuck.

Tools Used

Manual review

Recommendations

Consider either using sales money as prize, or add a function to withdraw those tokens.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!