Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: low
Valid

Missing currency check when joining a DAO leading to potential loss of profits and protocol fees

Relevant GitHub Links

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

Summary

The protocol has implemented some allowed currencies to use its functions to ensure payments are received. However, using MembershipFactory::joinDAO no check is made to ensure payments are all made with allowed currencies. (As done using the MembershipFactory::createNewDAOMembership)

Vulnerability Details

No check made through the currencyManager::isCurrencyWhitelisted function when joining a DAO using MembershipFactory::joinDAO.
This because the OG currency could have been removed from the list because the protocol cannot accept that currency anymore.

Impact

As not stated otherwise in the documentation provided it is reasonable to assume that payments made with no viewWhitelistedCurrencies could not be received by the contract/wallet causing this way a loss of all the funds.

As not stated otherwise in the documentation provided it is reasonable to assume that payments made with no viewWhitelistedCurrencies could not be received by the contract/wallet causing this way a loss of all the funds.

POC

````Solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
import { IMembershipERC1155 } from "../contracts/dao/interfaces/IERC1155Mintable.sol";
import { ICurrencyManager } from "../contracts/dao/interfaces/ICurrencyManager.sol";
import { CurrencyManager } from "../contracts/dao/CurrencyManager.sol";
import { MembershipERC1155 } from "../contracts/dao/tokens/MembershipERC1155.sol";
import { MembershipFactory } from "../contracts/dao/MembershipFactory.sol";
import { DAOConfig, DAOInputConfig, TierConfig, DAOType, TIER_MAX } from "../contracts/dao/libraries/MembershipDAOStructs.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import { NativeMetaTransaction } from "../contracts/meta-transaction/NativeMetaTransaction.sol";
import {Test, console} from "../forge-std/src/Test.sol";
contract OWPTest is Test {
string baseURI = "test_trial";
address public owpWallet = address(1);
address public user = makeAddr("user");
event firstslotevent (uint256);
MembershipFactory membershipfactory;
MembershipERC1155 membershipImplementation;
CurrencyManager currencymanager;
function setUp () public {
currencymanager = new CurrencyManager();
membershipImplementation = new MembershipERC1155();
membershipfactory = new MembershipFactory(address(currencymanager), owpWallet, baseURI, address(membershipImplementation));
}
function test_paymentWithNotAllowedCurrency () public {
Currency currency1 = new Currency("currency1", "CUR1");
Currency currency2 = new Currency("currency2", "CUR2");
Currency currency3 = new Currency("currency3", "CUR3");
currencymanager.addCurrency(address(currency1));
currencymanager.addCurrency(address(currency2));
currencymanager.addCurrency(address(currency3));
uint256 numtiers = 6;
TierConfig[] memory tierconf = new TierConfig[]();
for (uint256 i=0; i<numtiers; ++i) {
tierconf[i] = TierConfig({amount:10, price:10, power:1, minted:0});
}
DAOInputConfig memory conf = DAOInputConfig({ensname: "BestDAO", daoType: DAOType.PUBLIC, currency:address(currency1), maxMembers:200, noOfTiers:6});
address newdao = membershipfactory.createNewDAOMembership(conf, tierconf);
currencymanager.removeCurrency(address(currency1));
vm.deal(user, 1 ether);
vm.startPrank(user);
currency1.mint(user);
currency1.approve(address(membershipfactory), type(uint256).max);
vm.expectRevert();
membershipfactory.joinDAO(newdao, 4);
}
}```

Tools Used

Manual review

Recommendations

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(currencyManager.isCurrencyWhitelisted(daos[daoMembershipAddress].currency), "Currency not accepted.");
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);
}
Updates

Lead Judging Commences

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

Appeal created

0xbrivan2 Lead Judge
9 months ago
0xbrivan2 Lead Judge 9 months ago
Submission Judgement Published
Validated
Assigned finding tags:

missing DAO currency update

Support

FAQs

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