DatingDapp

AI First Flight #6
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: low
Likelihood: high
Invalid

_baseURI is not overridden, so tokenURI returns bare base64 instead of a data: URI

Root + Impact

Description

  • tokenURI is meant to return on-chain metadata as a data:application/json;base64,... URI (it prepends _baseURI() to the base64 JSON).

  • SoulboundProfileNFT does not override _baseURI(), so OpenZeppelin's default returns an empty string. tokenURI returns bare base64 text (eyJuYW1lIjoi...) with no scheme. Wallets and marketplaces treat it as a relative URL / unknown format and cannot load the profile metadata or image.

function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
...
return string(
abi.encodePacked(
@> _baseURI(), // ERC721 default: "" (never overridden)
Base64.encode(...)
)
);
}

Effect: for token 1 the result starts with eyJ (base64 of {"), not with data:application/json;base64,. Any standard ERC721 metadata consumer fails to resolve it.

Risk

Likelihood:

  • Every token, every time metadata is read.

Impact:

  • Profiles show without name, age or picture in wallets/marketplaces; the on-chain profile feature is unusable for integrations. No funds at risk.

Proof of Concept

Test setup: owner deploys SoulboundProfileNFT and LikeRegistry(address(nft)); alice, bob, carol each get 10 ETH and mint a profile (token ids 1, 2, 3). Full file test/AuditPoC.t.sol, forge test --mc AuditPoC passes.

function test_F6_tokenUriMissingDataPrefix() public view {
bytes memory u = bytes(nft.tokenURI(1));
assertTrue(u[0] != "d"); // no "data:application/json;base64," prefix
assertEq(u[0], bytes1("e")); // starts with base64 of '{"' ("eyJ")
}

Recommended Mitigation

Override _baseURI() so the URI is a valid data URI:

+ function _baseURI() internal pure override returns (string memory) {
+ return "data:application/json;base64,";
+ }

Add a test that the result starts with data:application/json;base64, and decodes to valid JSON.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 8 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!