Project

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

Role Misassignment in initialize Function of MembershipERC1155 Contract Breaks Core Permissions on Upgrade, Disabling Essential MembershipFactory Operations

Summary

The initialize function in the MembershipERC1155.sol contract assigns the OWP_FACTORY_ROLE to msg.sender upon contract initialization. This causes a critical issue during contract upgrades, as the proxy admin — rather than the MembershipFactory contract — becomes the new msg.sender and subsequently holds the OWP_FACTORY_ROLE. As a result, the MembershipFactory contract loses its ability to call essential functions like mint and burn in the MembershipERC1155 contract. This role misassignment breaks core functionalities, including joinDAO and upgradeTier, which rely on these permissions.

Vulnerability Details

In the MembershipERC1155 contract, the initialize function is responsible for setting the OWP_FACTORY_ROLE role. This function assigns the role to msg.sender, which works correctly during initial deployment since the MembershipFactory contract is the one deploying and initializing the membership instances. However, when the MembershipERC1155 contract is later upgraded through the TransparentUpgradeableProxy controlled by ProxyAdmin, the initialize function is called with ProxyAdmin as msg.sender. Consequently, OWP_FACTORY_ROLE is assigned to ProxyAdmin instead of the MembershipFactory contract, resulting in permission issues for the MembershipFactory.

This permission mismatch prevents the MembershipFactory from executing critical functions such as mint and burn within MembershipERC1155, disrupting essential functionalities like joinDAO and upgradeTier.

Relevant Code Snippet

function initialize(...) external initializer {
...
@> _grantRole(OWP_FACTORY_ROLE, msg.sender); // `msg.sender` becomes ProxyAdmin during upgrades, not Factory
}

Functions which will be blocked due to this in MembershipFactory:

function joinDAO(address daoMembershipAddress, uint256 tierIndex) external {
...
@> IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, tierIndex);
}
function upgradeTier(address daoMembershipAddress, uint256 fromTierIndex) external {
...
@> IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
@> IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
}

Example of How This Affects the System

  1. During initial deployment, the MembershipFactory initializes MembershipERC1155 and gains OWP_FACTORY_ROLE, allowing it to call mint and burn as needed.

  2. Upon an upgrade, the initialize function is called by the ProxyAdmin (as msg.sender), which now holds OWP_FACTORY_ROLE.

  3. The MembershipFactory no longer holds OWP_FACTORY_ROLE, preventing it from calling mint and burn in the MembershipERC1155 contract.

  4. This breaks key functionalities in the MembershipFactory contract, including joinDAO and upgradeTier.

Impact

This vulnerability disrupts the primary functions of the MembershipFactory contract, rendering it unable to mint and burn tokens in MembershipERC1155. This effectively blocks users from joining DAOs or upgrading membership tiers, severely impacting system functionality.

Tools Used

Manual analysis

Recommendations

To prevent this issue, modify the initialize function in MembershipERC1155 to explicitly assign the OWP_FACTORY_ROLE to the MembershipFactory contract address rather than to msg.sender.

function initialize(..., address factoryAddr) external initializer {
...
- _grantRole(OWP_FACTORY_ROLE, msg.sender);
+ _grantRole(OWP_FACTORY_ROLE, factoryAddr); // Explicitly assign role to the Factory address
}
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

0xsecuri Submitter
10 months ago
0xbrivan2 Lead Judge
10 months ago
0xbrivan2 Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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