DatingDapp

First Flight #33
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Invalid

Front-running vulnerability in `SoulboundProfileNFT::mintProfile` allows profile name squatting

Summary

The SoulboundProfileNFT::mintProfile function is vulnerable to front-running attacks where an attacker can observe pending profile creation transactions and front-run them to claim desirable profile names or prevent specific users from registering their profiles.

Vulnerability Details

function mintProfile(string memory name, uint8 age, string memory profileImage) external {
require(profileToToken[msg.sender] == 0, "Profile already exists");
uint256 tokenId = ++_nextTokenId;
_safeMint(msg.sender, tokenId);
_profiles[tokenId] = Profile(name, age, profileImage);
profileToToken[msg.sender] = tokenId;
emit ProfileMinted(msg.sender, tokenId, name, age, profileImage);
}

The function doesn't have any protection against transaction ordering manipulation, allowing attackers to front-run profile creation.

Proof Of Concept

function testProfileFrontRunning() public {
string memory desiredName = "VitalikButerin";
string memory desiredImage = "ipfs://vitalik";
// User trying to create their legitimate profile
vm.startPrank(alice);
vm.deal(alice, 1 ether);
// Transaction pending in mempool
// Attacker sees this and front-runs
vm.stopPrank();
// Attacker front-runs with same name
vm.startPrank(attacker);
nft.mintProfile(desiredName, 25, desiredImage);
// Verify attacker got the name first
uint256 attackerTokenId = nft.profileToToken(attacker);
assertGt(attackerTokenId, 0, "Attacker should have a token");
vm.stopPrank();
// Original user's transaction now fails
vm.startPrank(alice);
// Try to mint with same name
nft.mintProfile(desiredName, 30, desiredImage);
// Verify victim has no profile
uint256 aliceTokenId = nft.profileToToken(alice);
assertEq(aliceTokenId, 0, "Alice should not have a token");
vm.stopPrank();
}

Impact

High severity because:

  • Attackers can steal valuable or recognizable profile names

  • Users can be prevented from creating their legitimate profiles

  • Can be used for impersonation and social engineering

  • Damages platform reputation and user trust

  • Opens up possibilities for ransom/extortion of profile names

Tools Used

  • Manual review

  • Foundry testing framework

Recommendations

Implement a commit-reveal scheme for profile creation:

mapping(address => bytes32) public nameCommitments;
mapping(address => uint256) public commitmentTimestamps;
function commitProfileName(bytes32 commitment) external {
nameCommitments[msg.sender] = commitment;
commitmentTimestamps[msg.sender] = block.timestamp;
}
function revealAndMintProfile(string memory name, uint8 age, string memory profileImage, bytes32 salt) external {
require(block.timestamp >= commitmentTimestamps[msg.sender] + 1 hours, "Too early");
require(nameCommitments[msg.sender] == keccak256(abi.encodePacked(name, salt)), "Invalid commitment");
// Existing mint logic
uint256 tokenId = ++_nextTokenId;
_safeMint(msg.sender, tokenId);
_profiles[tokenId] = Profile(name, age, profileImage);
profileToToken[msg.sender] = tokenId;
delete nameCommitments[msg.sender];
delete commitmentTimestamps[msg.sender];
emit ProfileMinted(msg.sender, tokenId, name, age, profileImage);
}
Updates

Appeal created

n0kto Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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