Project

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

MembershipFactory will fail to deploy future implementations of MembershipERC1155

Summary

MembershipFactory will fail to deploy future implementations of MembershipERC1155

Vulnerability Details

Users can call MemebershipFactory.createNewDAOMembership() to create a new DAO contract, which consists of a TransparentUpgradeableProxy contract that uses 'membershipImplementation' as implementation contract. The issue is that the function calls initialize() in the deployed contract with a fixed function selector and parameters.

TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
membershipImplementation,
address(proxyAdmin),
=> abi.encodeWithSignature("initialize(string,string,string,address,address)", daoConfig.ensname, "OWP", baseURI, _msgSender(), daoConfig.currency)
);

Which is valid for this initial implementation of MembershipERC1155:

function initialize(
string memory name_,
string memory symbol_,
string memory uri_,
address creator_,
address currency_
) external initializer {

However, if future versions of this implementation contract require different initialization parameters, probably because they include new features or state variables (e.g. a DAO operator role, a fee receiver address or a fee amount to pay) contract deployment will revert, as the initialize() function's signature being called does not exist inside the new implementation contract.

This happens because when upgradeAndCall() is executed inside Proxy contract, the verification of the called function will return false, making the deployment revert.

/**
* @dev Performs implementation upgrade with additional setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) internal {
_setImplementation(newImplementation);
emit IERC1967.Upgraded(newImplementation);
if (data.length > 0) {
Address.functionDelegateCall(newImplementation, data);
} else {
_checkNonPayable();
}
}

Impact

Future implementations of MemebershipERC1155 are prevented from having new state variables, limiting the functionalities of deployed DAOs, which cannot be deployed with MemebershipFactory.createNewDAOMembership().

Tools Used

Manual review, Remix

Recommendations

Let the calldata used for initializing the TransparentUpgradeableProxy be variable. As some parameter should always be fixed, ADMIN may set those fixed parameters and let DAO creator use arbitrary ones:

contract MembershipFactory is AccessControl, NativeMetaTransaction {
+bytes public initializeData;
+function setInitializeData(bytes memory _initializeData) external onlyRole(DEFAULT_ADMIN_ROLE){
+ initializeData = _initializeData;
+ }
.
.
.
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
membershipImplementation,
address(proxyAdmin),
- abi.encodeWithSignature("initialize(string,string,string,address,address)", daoConfig.ensname, "OWP", baseURI, _msgSender(), daoConfig.currency)
+ initializeData
);
Updates

Lead Judging Commences

0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope
0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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