Project

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

The `weights/power` used in share calculation are hardcoded and do not account for the `power` values chosen by the DAO creator

Summary

The profit-sharing mechanism uses hardcoded weights for each tier, ignoring the customizable power values set during DAO creation. This results in incorrect profit distribution when DAOs have custom tier configurations.

Vulnerability Details

In the MembershipERC1155 contract, the shareOf function calculates a user's share of profits based on hardcoded weights:

function shareOf(address account) public view returns (uint256) {
return (balanceOf(account, 0) * 64) + (balanceOf(account, 1) * 32) + (balanceOf(account, 2) * 16)
+ (balanceOf(account, 3) * 8) + (balanceOf(account, 4) * 4) + (balanceOf(account, 5) * 2)
+ balanceOf(account, 6);
}

However, during DAO creation, tiers can be configured with custom power values:

tierConfig[0] = TierConfig({price: 3200, amount: 320, minted: 0, power: 32});
tierConfig[1] = TierConfig({price: 1600, amount: 160, minted: 0, power: 16});
tierConfig[2] = TierConfig({price: 800, amount: 80, minted: 0, power: 8});

The shareOf function does not use these custom power values, leading to incorrect calculations of users' profit shares.

POC

function testShareOfDoesNotAccountForActualTierPower() public {
TierConfig[] memory tierConfig = new TierConfig[]();
tierConfig[0] = TierConfig({price: 3200, amount: 320, minted: 0, power: 32});
tierConfig[1] = TierConfig({price: 1600, amount: 160, minted: 0, power: 16});
tierConfig[2] = TierConfig({price: 800, amount: 80, minted: 0, power: 8});
MockUsdc mockUsdc = new MockUsdc();
DAOInputConfig memory daoConfig = DAOInputConfig({
ensname: "testdao.eth",
daoType: DAOType.PUBLIC,
currency: address(mockUsdc),
maxMembers: 1270,
noOfTiers: 3
});
currencyManager.addCurrency(address(mockUsdc));
address dao = membershipFactory.createNewDAOMembership(
daoConfig,
tierConfig
);
uint256 mintAmount = 1000 * 10 ** 18;
mockUsdc.mint(alice, mintAmount);
vm.startPrank(alice);
mockUsdc.approve(address(membershipFactory), 3200);
membershipFactory.joinDAO(dao, 0);
mockUsdc.approve(address(membershipFactory), 1600);
membershipFactory.joinDAO(dao, 1);
mockUsdc.approve(address(membershipFactory), 800);
membershipFactory.joinDAO(dao, 2);
vm.stopPrank();
uint256 actualShare = MembershipERC1155(dao).shareOf(alice);
uint256 expectedUserProfit = (MembershipERC1155(dao).balanceOf(alice, 0) * 32) +
(MembershipERC1155(dao).balanceOf(alice, 1) * 16) +
(MembershipERC1155(dao).balanceOf(alice, 2) * 8);
// The expected share must be 56 but gives 112, 2 times more than what's expected
console.log(actualShare); // 112
console.log(expectedUserProfit); // 56
assert(actualShare >= expectedUserProfit * 2);
}

Impact

Users receive incorrect profit amounts, which can be significantly higher or lower than intended. This undermines the fairness and trust in the DAO, potentially causing disputes and dissatisfaction among members.

Tools Used

Manual review and foundry

Recommendations

  • Modify the shareOf function to retrieve and use the actual power values from the tier configurations stored during DAO creation.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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