The README describes the NFT as the user's "verified dating profile". Before a user can pay to like others and be matched, their dating profile should have a usable name and image and a plausible adult age.
mintProfile's only check is profileToToken[msg.sender] == 0 (L31). It stores Profile(name, age, profileImage) (L37) with no bound on the uint8 age and no non-empty check on name or profileImage. LikeRegistry treats any address with profileToToken != 0 as a valid participant (L35-L36) and never reads the profile fields. A profile declaring age 15, 0 or 255 with a blank name and image is therefore minted and published in tokenURI. It can then like, be liked, match and co-own a match multisig.
Likelihood:
Any user can mint such a profile through a normal, permissionless mintProfile call. A careless or honest entry is accepted as given, whether it is a blank field, age 0 or a true age under 18.
Age is self-declared, so on-chain bounds catch only honestly disclosed or nonsensical values. No on-chain check can stop a user who types a false adult age.
Impact:
The protocol mints and fully enables "verified dating profiles" with blank names and images and with nonsensical or under-age ages. In the PoC, an age-15 profile with a blank name and image:
pays 1 ETH to like an adult;
is matched;
appears in both getMatches() lists;
is owner1 of the deployed MultiSigWallet.
tokenURI publishes the stored values (Age 15, 0 or 255, empty name and image) as protocol-generated metadata. No funds are at risk. The effect is that invalid profile data is admitted into the paid matching flow.
The PoC deploys SoulboundProfileNFT and LikeRegistry. The baseline shows that an address without a profile cannot like. The tests then show the following:
Mint accepts anything: mintProfile("", 15, ""), mintProfile("", 0, "") and mintProfile("Old", 255, "ipfs://x") all succeed, and tokenURI returns exactly the Base64 JSON with those values.
Full participation: the age-15 profile with a blank name and image:
pays 1 ETH to like an adult;
is liked back, which emits Matched;
appears in both getMatches() lists;
is owner1 of the MultiSigWallet deployed at the predicted address.
Run from the repository root, with the file saved as test/PoC_DD-10.t.sol:
Result: Suite result: ok. 3 passed; 0 failed; 0 skipped.
Validate the fields at mint. Because the age is self-declared, the age bound is a sanity check, not identity verification, which has to happen off-chain.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.