Project

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

Lack of Access Control on sendProfit Function Allows Unauthorized Profit Distributions, Leading to Potential Economic Exploits and Financial Loss

Summary

The sendProfit function lacks access control mechanisms, allowing any external actor to trigger profit distributions to token holders as long as they have approved tokens. This creates a critical security vulnerability where unauthorized parties can manipulate the profit distribution system, potentially leading to economic damage through malicious profit distribution timing or amounts. Since the contract handles actual value transfer through ERC20 tokens, this vulnerability poses direct financial risks to the protocol and its users.

The root cause is the omission of access control modifiers on the sendProfit function, contrasting with the pattern established throughout the rest of the contract where sensitive functions are protected with onlyRole modifiers. The contract implements OpenZeppelin's AccessControl pattern and defines several roles like OWP_FACTORY_ROLE and DAO_CREATOR, but fails to utilize them for this critical function.

The vulnerability is exacerbated by the fact that the function handles actual token transfers and updates the profit accounting system that determines how much profit each token holder can claim. This system maintains state variables like totalProfit and uses them in conjunction with ACCURACY (1e30) for precise profit calculations, making unauthorized access particularly dangerous.

Vulnerable code snippet

https://github.com/Cyfrin/2024-11-one-world/blob/main/contracts/dao/tokens/MembershipERC1155.sol#L191

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

Consider a scenario where a malicious actor monitors the mempool for large token holder transactions. Just before a significant token transfer or claim operation, they could call sendProfit with a specific amount, manipulating the profit distribution timing to their advantage. Since profit calculations depend on token holdings at specific timestamps (through the saveProfit mechanism), unauthorized profit distributions could be used to exploit the timing of these calculations, effectively stealing value from legitimate token holders.

Recommended Fix

Add appropriate access control modifier to restrict the function to authorized roles:

function sendProfit(uint256 amount) external onlyRole(DAO_CREATOR) {
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);
}
}

Alternatively, if multiple roles should have access to this function, consider creating a new role specifically for profit distribution:

bytes32 public constant PROFIT_DISTRIBUTOR_ROLE = keccak256("PROFIT_DISTRIBUTOR_ROLE");
function sendProfit(uint256 amount) external onlyRole(PROFIT_DISTRIBUTOR_ROLE) {
// ... rest of the function
}

Remember to grant this role appropriately during initialization or through admin actions.

Updates

Lead Judging Commences

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

Support

FAQs

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