Summary
The TroveNFT contract maintains a custom _ownerToTroveIds mapping that duplicates functionality already provided by the inherited ERC721Enumerable extension.
Vulnerability Detail
ERC721Enumerable already maintains mappings to track all tokens owned by each address via _ownedTokens mapping and provides tokenOfOwnerByIndex() function. The custom _ownerToTroveIds array duplicates this logic, increasing gas costs and storage usage.
Impact
Unnecessary gas costs for minting/transferring and storage overhead.
Code Snippet
mapping(address => uint256[]) private _ownerToTroveIds; // @audit - duplicates ERC721Enumerable
function ownerToTroveIds(address owner) external view returns (uint256[] memory) {
return _ownerToTroveIds[owner];
}ERC721Enumerable already provides: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721Enumerable.sol#L18-L19
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Can iterate using tokenOfOwnerByIndex(owner, index) for index in [0, balanceOf(owner))Tool Used
Manual Review
Recommendation
Remove the custom mapping and use ERC721Enumerable's built-in functionality:
function ownerToTroveIds(address owner) external view returns (uint256[] memory) {
uint256 balance = balanceOf(owner);
uint256[] memory troveIds = new uint256[](balance);
for (uint256 i = 0; i < balance; i++) {
troveIds[i] = tokenOfOwnerByIndex(owner, i);
}
return troveIds;
}