Project

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

Reentrancy Risk in joinDAO

Issue: The joinDAO function in MembershipFactory involves multiple external calls to ERC20 token contracts for fund transfers, increasing the risk of reentrancy. This function transfers platform fees and tier prices, then calls the mint function on an ERC1155 contract, which may indirectly call untrusted code and lead to reentrancy vulnerabilities.

Impact: Reentrancy vulnerabilities could allow an attacker to drain funds by re-entering the function before state updates are completed.

Exploit:

joinDAO involves multiple external token transfers and could be exploited through reentrancy to mint tokens without transferring the required funds.

Location of Code:

  • MembershipFactory.sol:

    function joinDAO(address daoMembershipAddress, uint256 tierIndex) external {
    // External token transfer calls without reentrancy protection
    IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
    IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, tierPrice - platformFees);
    // Mint membership token after transfer
    IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
    }

POC:

function joinDAO(address daoMembershipAddress, uint256 tierIndex) external {
// Transfer calls susceptible to reentrancy.
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, tierPrice - platformFees);
// Potential reentrancy in the `mint` call
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
}

Exploit Code:

An attacker could re-enter joinDAO using a custom ERC20 token that triggers joinDAO recursively in its transferFrom function, allowing unlimited minting without fees.

Code Change:

Add reentrancy guard to joinDAO.

// Use ReentrancyGuard from OpenZeppelin
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
function joinDAO(address daoMembershipAddress, uint256 tierIndex) external nonReentrant {
// Safe token transfer with reentrancy guard in place
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, tierPrice - platformFees);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
}
  • Tool used : VSC, Github

  • Recommendation: Implement a reentrancy guard using the nonReentrant modifier from OpenZeppelin's ReentrancyGuard library. Ensure that state updates are done before making external calls.

Updates

Lead Judging Commences

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.