Project

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

Hardcoded Platform Fees in joinDAO Function Create Inflexibility and Lack of Transparency

Summary

The hardcoding of platform fees at 20% in the joinDAO function represents a significant architectural rigidity that could impact the protocol's long-term sustainability and adaptability. This inflexible fee structure prevents the protocol from adjusting to market conditions, competitive pressures, or varying economic models across different types of DAOs. In scenarios where fee adjustments are necessary due to market dynamics or protocol governance decisions, the entire contract would require redeployment, leading to potential operational disruptions and increased administrative overhead. Furthermore, the hardcoded nature of the fee calculation makes the contract less transparent to users who need to inspect the code to understand the fee structure rather than being able to query it through a public variable.

The root cause lies in the direct embedding of the fee percentage within the function logic, rather than implementing it as a configurable parameter managed through protocol governance. The calculation uint256 platformFees = (20 * tierPrice) / 100 demonstrates how the 20% fee is tightly coupled with the business logic, making it impossible to modify without a contract upgrade. This approach also increases the risk of calculation errors or inconsistencies if the fee structure needs to be referenced or validated across different parts of the protocol, as the value is not centrally managed.

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

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; // Hardcoded 20% fee
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);
}

Recommended Fix

Implement a configurable fee structure using an administrative function and state variable. Use basis points (BPS) for more precise fee calculations:

contract MembershipFactory {
uint256 public platformFeeBps = 2000; // 20% in basis points (1 bps = 0.01%)
event PlatformFeeUpdated(uint256 oldFee, uint256 newFee);
function setPlatformFee(uint256 newFeeBps) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(newFeeBps <= 10000, "Fee cannot exceed 100%");
uint256 oldFee = platformFeeBps;
platformFeeBps = newFeeBps;
emit PlatformFeeUpdated(oldFee, newFeeBps);
}
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;
require(tierPrice > 0, "Invalid tier price");
uint256 platformFees = (tierPrice * platformFeeBps) / 10000;
uint256 daoAmount = tierPrice - platformFees;
daos[daoMembershipAddress].tiers[tierIndex].minted += 1;
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, daoAmount);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, tierIndex);
}
}
Updates

Lead Judging Commences

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

Support

FAQs

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