Project

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

Front-Running Vulnerability in joinDAO Membership Purchase

Summary

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

Vulnerability Details

The joinDAO function allows users to join a DAO by purchasing a membership NFT at a specific tier. Each tier has a limited number of available memberships, as defined by TierConfig.amount. This function does not implement any mechanism to prevent front-running attacks, allowing a bot to:

Monitor Pending Transactions: Observe an impending joinDAO transaction to a tier close to reaching its capacity.

Front-Run the User: Submit a joinDAO transaction with a higher gas price, securing the membership spot ahead of the original user’s transaction.

Block the User: If the front-runner successfully joins, the original user may be blocked from joining the tier due to it reaching its capacity.

This behavior could lead to unfair access to limited-tier memberships, particularly in cases of high-demand DAO memberships.

Impact

A front-runner or bot could detect a high-demand membership purchase transaction in the joinDAO function and preemptively join a tier by submitting a transaction at a higher gas price. This would result in the attacker taking up a spot in a limited membership tier before the intended user can complete their transaction. Users may miss out on limited membership opportunities due to front-running, leading to frustration and potentially reputational damage for the DAO platform.

Tools Used

Manual Review

Proof of Code

Here's a closer look at the joinDAO function and the logic that allows for front-running:

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;
// Increment minted count for the selected tier
daos[daoMembershipAddress].tiers[tierIndex].minted += 1;
// Transfer platform fees and tier price
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), owpWallet, platformFees);
IERC20(daos[daoMembershipAddress].currency).transferFrom(_msgSender(), daoMembershipAddress, tierPrice - platformFees);
// Mint the membership NFT for the user
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), tierIndex, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, tierIndex);
}

The critical issue here is that any user can interact with joinDAO without restrictions on when they can join, allowing bots or malicious users to front-run a membership purchase by submitting a transaction with a higher gas price.

Recommendations

To prevent front-running attacks, consider implementing the following measures:

Commit-Reveal Scheme: Implement a two-phase process for joining a DAO:

Commit Phase: Users submit a hash of their intent to join a specific DAO and tier without revealing details (i.e., hash of user address, DAO address, and tier).

Reveal Phase: After a specified time window, users reveal their original commitment and complete the join process. This reduces the likelihood of front-running as attackers cannot act on hash commitments alone.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Appeal created

mustaphaabdulaziz00 Submitter
7 months ago
0xbrivan2 Lead Judge
7 months ago
0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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