First Flight #12: Kitty Connect

First Flight #12: Kitty Connect
Beginner FriendlyFoundryNFTGameFi
100 EXP
View results
Submission Details
Severity: medium
Invalid

`KittyConnect` functions `tokenURI`, `getCatAge`, `getCatInfo` do not check whether `tokenId` exists

Summary

KittyConnect functions tokenURI, getCatAge, getCatInfo do not check whether tokenId exists, they accept non-existent tokenIds as input.

Impact

When providing non-existent tokenIds to these 3 functions, they will run and return values as if the tokenId existed, leading to confusion.

Proof of Code
function test_tokenUriDoesNotCheckIfTokenIdExists() public {
uint256 nonExistentTokenId = 1000;
vm.expectRevert("ERC721: invalid token ID");
address owner = kittyConnect.ownerOf(nonExistentTokenId);
//require(kittyConnect._exists(nonExistentTokenId) == false); // this function is not exposed externally
string memory tokenUri = kittyConnect.tokenURI(nonExistentTokenId);
console.log(tokenUri);
}
function test_getCatAgeDoesNotCheckIfTokenExists() public {
uint256 nonExistentTokenId = 1000;
vm.warp(block.timestamp + 10 weeks);
uint256 catAge = kittyConnect.getCatAge(nonExistentTokenId);
console.log("Catage: ", catAge);
assert(catAge > 0);
}
function test_getCatInfoDoesNotCheckIfTokenExists() public view {
uint256 nonExistentTokenId = 1000;
KittyConnect.CatInfo memory catInfo = kittyConnect.getCatInfo(nonExistentTokenId);
console.log("CatName: ", catInfo.catName);
console.log("Breed: ", catInfo.breed);
console.log("Image: ", catInfo.image);
console.log("DoB: ", catInfo.dob);
//console.log("PrevOwner: ", catInfo.prevOwner[0]); // throws error [FAIL. Reason: panic: array out-of-bounds access (0x32)]
console.log("ShopPartner: ", catInfo.shopPartner);
console.log("Idx: ", catInfo.idx);
}

Tools Used

Manual review, Foundry.

Recommendations

In all these functions, check whether the tokenId provided as input actually exist:

function tokenURI(uint256 tokenId) public view override returns (string memory) {
+ require(_ownerOf(tokenId) != address(0), "TokenID does not exist.");
...
}
function getCatAge(uint256 tokenId) external view returns (uint256) {
+ require(_ownerOf(tokenId) != address(0), "TokenID does not exist.");
return block.timestamp - s_catInfo[tokenId].dob;
}
function getCatInfo(uint256 tokenId) external view returns (CatInfo memory) {
+ require(_ownerOf(tokenId) != address(0), "TokenID does not exist.");
return s_catInfo[tokenId];
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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