Omniscia Tangible Audit

TNFTMetadata Manual Review Findings

TNFTMetadata Manual Review Findings

TNF-01M: Inexistent Usage of Function

Description:

The TNFTMetadata::_removeFromType function remains unutilized within the codebase.

Example:

contracts/TNFTMetadata.sol
320function _removeFromType(uint256 _tnftType, uint256 _indexInType) internal {
321 require(tnftTypes[_tnftType].added, "non-existing tnftType");
322
323 uint256 last = typeFeatures[_tnftType].length - 1; // get last index
324 uint256 lastItem = typeFeatures[_tnftType][last]; // grab last item
325
326 typeFeatures[_tnftType][_indexInType] = lastItem; // set last item to removed item's index
327 typeFeatures[_tnftType].pop(); // remove last item
328}

Recommendation:

We advise the Tangible team to evaluate its validity and potentially omit it or correctly utilize it.

Alleviation (2ad448279d9e8e4b6edd94bcd2eb22129b6f7357):

The referenced function has been omitted from the code as it was deemed unnecessary by the Tangible team.

TNF-02M: Incorrect Index Entry

Description:

The featureIndexInList mapping will contain an incorrect non-zero index entry when the featureItem to be removed is the last in the featureList to be removed.

Impact:

While an incorrect entry will be present in the featureIndexInList mapping, it will be inconsequential given that it serves no purpose outside the TNFTMetadata contract.

Example:

contracts/TNFTMetadata.sol
207// remove from array of added
208uint256 index = featureIndexInList[featureItem];
209delete featureIndexInList[featureItem];
210
211featureList[index] = featureList[featureList.length - 1]; // move last to index of removing
212featureIndexInList[featureList[featureList.length - 1]] = index;
213featureList.pop(); // pop last element
214delete featureInfo[featureItem]; // delete from featureInfo mapping

Recommendation:

We advise the code to delete the featureIndexInlist of the featureItem after the array shift operation. Alternatively, the correction for this exhibit can be coupled with the last-element shift optimization.

Alleviation (2ad448279d9e8e4b6edd94bcd2eb22129b6f7357):

The delete operation of the featureIndexInList entry was relocated after the index's re-assignment, ensuring that it remains non-zero in case the featureItem matches the featureList[featureList.length - 1] entry.

TNF-03M: Inexistent Prevention of Duplicate Entries

Description:

The TNFTMetadata::addFeatuersForTNFTType function does not prevent duplicate features to be added to a particular _tnftType, causing significant misbehaviours in case a feature is removed from a _tnftType only once as in such a case the featureInType value would incorrectly be false.

Impact:

The features supposedly present in a particular _tnftType may be incorrect if a feature is added more than once and removed once for a particular _tnftType due to the misbehaviour mentioned by this exhibit.

Example:

contracts/TNFTMetadata.sol
263function addFeaturesForTNFTType(
264 uint256 _tnftType,
265 uint256[] calldata _features
266) external onlyFactoryOwner {
267 require(tnftTypes[_tnftType].added, "tnftType doesn't exist");
268 uint256 length = _features.length;
269
270 for (uint256 i; i < length; ) {
271 uint256 item = _features[i];
272 require(featureInfo[item].added, "feature doesn't exist");
273
274 typeFeatures[_tnftType].push(item);
275 featureInfo[item].tnftTypes.push(_tnftType);
276 featureInType[_tnftType][item] = true;
277
278 emit FeatureAddedToTnftType(_tnftType, item);
279
280 unchecked {
281 ++i;
282 }
283 }
284}

Recommendation:

We advise the code to ensure duplicate features cannot be added to a particular _tnftType by imposing a require check within the for loop of the function that ensures the featureInType value is false.

Alleviation (2ad448279d9e8e4b6edd94bcd2eb22129b6f7357):

The code of TNFTMetadata::addFeaturesForTNFTType was updated to properly ensure that each newly introduced feature has not already been added to the respective type, alleviating this exhibit in full.