diff --git a/contracts/RMRK/extension/tokenAttributes/RMRKTokenAttributesRepository.sol b/contracts/RMRK/extension/tokenAttributes/RMRKTokenAttributesRepository.sol index 804dadc1..c9a8d13f 100644 --- a/contracts/RMRK/extension/tokenAttributes/RMRKTokenAttributesRepository.sol +++ b/contracts/RMRK/extension/tokenAttributes/RMRKTokenAttributesRepository.sol @@ -105,6 +105,47 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /// Used to signal that the presigned message's deadline has expired. error ExpiredDeadline(); + // ------------------- MODIFIERS ------------------- + + /** + * @notice Modifier to check if the collection is registered. + * @param collection Address of the collection. + */ + modifier onlyRegisteredCollection(address collection) { + if (!_ownerSettings[collection].registered) { + revert CollectionNotRegistered(); + } + _; + } + + /** + * @notice Modifier to check if the caller is the owner of the collection. + * @param collection Address of the collection. + */ + modifier onlyOwner(address collection) { + if (_ownerSettings[collection].useOwnable) { + if (Ownable(collection).owner() != _msgSender()) { + revert NotCollectionOwner(); + } + } else if (_ownerSettings[collection].owner != _msgSender()) { + revert NotCollectionOwner(); + } + _; + } + + /** + * @inheritdoc IERC165 + */ + function supportsInterface( + bytes4 interfaceId + ) public view virtual returns (bool) { + return + interfaceId == type(IERC7508).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + + // ------------------- ACCESS CONTROL ------------------- + /** * @inheritdoc IERC7508 */ @@ -115,8 +156,6 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { isCollaborator_ = _collaborators[collection][collaborator]; } - // ------------------- ACCESS CONTROL ------------------- - /** * @inheritdoc IERC7508 */ @@ -221,6 +260,17 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { attributesMetadataURI = _attributesMetadataURIs[collection]; } + /** + * @inheritdoc IERC7508 + */ + function setAttributesMetadataURIForCollection( + address collection, + string memory attributesMetadataURI + ) external onlyOwner(collection) { + _attributesMetadataURIs[collection] = attributesMetadataURI; + emit MetadataURIUpdated(collection, attributesMetadataURI); + } + // ------------------- GETTERS ------------------- /** @@ -583,112 +633,22 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { } } - // ------------------- SETTERS ------------------- - // ------------------- BATCH SETTERS ------------------- - // ------------------- PRESIGNED SETTERS ------------------- - - /** - * @inheritdoc IERC7508 - */ - function setAttributesMetadataURIForCollection( - address collection, - string memory attributesMetadataURI - ) external onlyOwner(collection) { - _attributesMetadataURIs[collection] = attributesMetadataURI; - emit MetadataURIUpdated(collection, attributesMetadataURI); - } - - /** - * @notice Modifier to check if the collection is registered. - * @param collection Address of the collection. - */ - modifier onlyRegisteredCollection(address collection) { - if (!_ownerSettings[collection].registered) { - revert CollectionNotRegistered(); - } - _; - } - - /** - * @notice Modifier to check if the caller is the owner of the collection. - * @param collection Address of the collection. - */ - modifier onlyOwner(address collection) { - if (_ownerSettings[collection].useOwnable) { - if (Ownable(collection).owner() != _msgSender()) { - revert NotCollectionOwner(); - } - } else if (_ownerSettings[collection].owner != _msgSender()) { - revert NotCollectionOwner(); - } - _; - } - - /** - * @notice Function to check if the caller is authorized to mamage a given parameter. - * @param collection The address of the collection. - * @param key Key of the attribute. - * @param tokenId The ID of the token. - */ - function _onlyAuthorizedCaller( - address caller, - address collection, - string memory key, - uint256 tokenId - ) private view { - AccessType accessType = _parameterAccessType[collection][ - _keysToIds[key] - ]; - - if ( - accessType == AccessType.Owner && - ((_ownerSettings[collection].useOwnable && - Ownable(collection).owner() != caller) || - (!_ownerSettings[collection].useOwnable && - _ownerSettings[collection].owner != caller)) - ) { - revert NotCollectionOwner(); - } else if ( - accessType == AccessType.Collaborator && - !_collaborators[collection][caller] - ) { - revert NotCollectionCollaborator(); - } else if ( - accessType == AccessType.OwnerOrCollaborator && - ((_ownerSettings[collection].useOwnable && - Ownable(collection).owner() != caller) || - (!_ownerSettings[collection].useOwnable && - _ownerSettings[collection].owner != caller)) && - !_collaborators[collection][caller] - ) { - revert NotCollectionOwnerOrCollaborator(); - } else if ( - accessType == AccessType.TokenOwner && - IERC721(collection).ownerOf(tokenId) != caller - ) { - revert NotTokenOwner(); - } else if ( - accessType == AccessType.SpecificAddress && - !(_parameterSpecificAddress[collection][_keysToIds[key]] == caller) - ) { - revert NotSpecificAddress(); - } - } + // ------------------- PREPARE PRESIGNED MESSAGES ------------------- /** * @inheritdoc IERC7508 */ - function prepareMessageToPresignUintAttribute( + function prepareMessageToPresignAddressAttribute( address collection, uint256 tokenId, string memory key, - uint256 value, + address value, uint256 deadline ) public view returns (bytes32 message) { message = keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_UINT_ATTRIBUTE_TYPEHASH, + SET_ADDRESS_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -701,17 +661,17 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function prepareMessageToPresignIntAttribute( + function prepareMessageToPresignBoolAttribute( address collection, uint256 tokenId, string memory key, - int256 value, + bool value, uint256 deadline ) public view returns (bytes32 message) { message = keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_UINT_ATTRIBUTE_TYPEHASH, + SET_BOOL_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -724,17 +684,17 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function prepareMessageToPresignStringAttribute( + function prepareMessageToPresignBytesAttribute( address collection, uint256 tokenId, string memory key, - string memory value, + bytes memory value, uint256 deadline ) public view returns (bytes32 message) { message = keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_STRING_ATTRIBUTE_TYPEHASH, + SET_BYTES_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -747,17 +707,17 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function prepareMessageToPresignBoolAttribute( + function prepareMessageToPresignIntAttribute( address collection, uint256 tokenId, string memory key, - bool value, + int256 value, uint256 deadline ) public view returns (bytes32 message) { message = keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_BOOL_ATTRIBUTE_TYPEHASH, + SET_UINT_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -770,17 +730,17 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function prepareMessageToPresignBytesAttribute( + function prepareMessageToPresignStringAttribute( address collection, uint256 tokenId, string memory key, - bytes memory value, + string memory value, uint256 deadline ) public view returns (bytes32 message) { message = keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_BYTES_ATTRIBUTE_TYPEHASH, + SET_STRING_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -793,17 +753,17 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function prepareMessageToPresignAddressAttribute( + function prepareMessageToPresignUintAttribute( address collection, uint256 tokenId, string memory key, - address value, + uint256 value, uint256 deadline ) public view returns (bytes32 message) { message = keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_ADDRESS_ATTRIBUTE_TYPEHASH, + SET_UINT_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -813,85 +773,89 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { ); } + // ------------------- SETTERS ------------------- + /** * @inheritdoc IERC7508 */ - function setBoolAttribute( + function setAddressAttribute( address collection, uint256 tokenId, string memory key, - bool value + address value ) external { - _setBoolAttribute(_msgSender(), collection, tokenId, key, value); + _setAddressAttribute(_msgSender(), collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function setBytesAttribute( + function setBoolAttribute( address collection, uint256 tokenId, string memory key, - bytes memory value + bool value ) external { - _setBytesAttribute(_msgSender(), collection, tokenId, key, value); + _setBoolAttribute(_msgSender(), collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function setAddressAttribute( + function setBytesAttribute( address collection, uint256 tokenId, string memory key, - address value + bytes memory value ) external { - _setAddressAttribute(_msgSender(), collection, tokenId, key, value); + _setBytesAttribute(_msgSender(), collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function setUintAttribute( + function setIntAttribute( address collection, uint256 tokenId, string memory key, - uint256 value + int256 value ) external { - _setUintAttribute(_msgSender(), collection, tokenId, key, value); + _setIntAttribute(_msgSender(), collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function setIntAttribute( + function setStringAttribute( address collection, uint256 tokenId, string memory key, - int256 value + string memory value ) external { - _setIntAttribute(_msgSender(), collection, tokenId, key, value); + _setStringAttribute(_msgSender(), collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function setStringAttribute( + function setUintAttribute( address collection, uint256 tokenId, string memory key, - string memory value + uint256 value ) external { - _setStringAttribute(_msgSender(), collection, tokenId, key, value); + _setUintAttribute(_msgSender(), collection, tokenId, key, value); } + // ------------------- BATCH SETTERS ------------------- + /** * @inheritdoc IERC7508 */ - function setBoolAttributes( + function setAddressAttributes( address[] memory collections, uint256[] memory tokenIds, - BoolAttribute[] memory attributes + AddressAttribute[] memory attributes ) external { ( bool multipleCollections, @@ -904,10 +868,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { attributes.length ); for (uint256 i; i < loopLength; ) { - BoolAttribute memory attribute = multipleAttributes + AddressAttribute memory attribute = multipleAttributes ? attributes[i] : attributes[0]; - _setBoolAttribute( + _setAddressAttribute( _msgSender(), multipleCollections ? collections[i] : collections[0], multipleTokens ? tokenIds[i] : tokenIds[0], @@ -923,10 +887,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function setBytesAttributes( + function setBoolAttributes( address[] memory collections, uint256[] memory tokenIds, - BytesAttribute[] memory attributes + BoolAttribute[] memory attributes ) external { ( bool multipleCollections, @@ -939,10 +903,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { attributes.length ); for (uint256 i; i < loopLength; ) { - BytesAttribute memory attribute = multipleAttributes + BoolAttribute memory attribute = multipleAttributes ? attributes[i] : attributes[0]; - _setBytesAttribute( + _setBoolAttribute( _msgSender(), multipleCollections ? collections[i] : collections[0], multipleTokens ? tokenIds[i] : tokenIds[0], @@ -958,10 +922,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function setStringAttributes( + function setBytesAttributes( address[] memory collections, uint256[] memory tokenIds, - StringAttribute[] memory attributes + BytesAttribute[] memory attributes ) external { ( bool multipleCollections, @@ -974,10 +938,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { attributes.length ); for (uint256 i; i < loopLength; ) { - StringAttribute memory attribute = multipleAttributes + BytesAttribute memory attribute = multipleAttributes ? attributes[i] : attributes[0]; - _setStringAttribute( + _setBytesAttribute( _msgSender(), multipleCollections ? collections[i] : collections[0], multipleTokens ? tokenIds[i] : tokenIds[0], @@ -993,10 +957,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function setUintAttributes( + function setIntAttributes( address[] memory collections, uint256[] memory tokenIds, - UintAttribute[] memory attributes + IntAttribute[] memory attributes ) external { ( bool multipleCollections, @@ -1009,10 +973,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { attributes.length ); for (uint256 i; i < loopLength; ) { - UintAttribute memory attribute = multipleAttributes + IntAttribute memory attribute = multipleAttributes ? attributes[i] : attributes[0]; - _setUintAttribute( + _setIntAttribute( _msgSender(), multipleCollections ? collections[i] : collections[0], multipleTokens ? tokenIds[i] : tokenIds[0], @@ -1028,10 +992,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function setIntAttributes( + function setStringAttributes( address[] memory collections, uint256[] memory tokenIds, - IntAttribute[] memory attributes + StringAttribute[] memory attributes ) external { ( bool multipleCollections, @@ -1044,10 +1008,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { attributes.length ); for (uint256 i; i < loopLength; ) { - IntAttribute memory attribute = multipleAttributes + StringAttribute memory attribute = multipleAttributes ? attributes[i] : attributes[0]; - _setIntAttribute( + _setStringAttribute( _msgSender(), multipleCollections ? collections[i] : collections[0], multipleTokens ? tokenIds[i] : tokenIds[0], @@ -1063,10 +1027,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { /** * @inheritdoc IERC7508 */ - function setAddressAttributes( + function setUintAttributes( address[] memory collections, uint256[] memory tokenIds, - AddressAttribute[] memory attributes + UintAttribute[] memory attributes ) external { ( bool multipleCollections, @@ -1079,10 +1043,10 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { attributes.length ); for (uint256 i; i < loopLength; ) { - AddressAttribute memory attribute = multipleAttributes + UintAttribute memory attribute = multipleAttributes ? attributes[i] : attributes[0]; - _setAddressAttribute( + _setUintAttribute( _msgSender(), multipleCollections ? collections[i] : collections[0], multipleTokens ? tokenIds[i] : tokenIds[0], @@ -1193,127 +1157,17 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { } } - function _checkIfMultipleCollectionsAndTokens( - address[] memory collections, - uint256[] memory tokenIds, - uint256 attributesLength - ) - internal - pure - returns ( - bool multipleCollections, - bool multipleTokens, - bool multipleAttributes, - uint256 loopLength - ) - { - multipleCollections = collections.length != 1; - multipleTokens = tokenIds.length != 1; - multipleAttributes = attributesLength != 1; - if ( - (multipleCollections && - multipleAttributes && - collections.length != attributesLength) || - (multipleTokens && - multipleAttributes && - tokenIds.length != attributesLength) || - (multipleCollections && - multipleTokens && - collections.length != tokenIds.length) - ) { - revert LengthsMismatch(); - } - - if (multipleCollections) { - loopLength = collections.length; - } else if (multipleTokens) { - loopLength = tokenIds.length; - } else { - loopLength = attributesLength; - } - } - - function _setBoolAttribute( - address caller, - address collection, - uint256 tokenId, - string memory key, - bool value - ) internal { - _onlyAuthorizedCaller(caller, collection, key, tokenId); - _boolValues[collection][tokenId][_getIdForKey(key)] = value; - emit BoolAttributeUpdated(collection, tokenId, key, value); - } - - function _setBytesAttribute( - address caller, - address collection, - uint256 tokenId, - string memory key, - bytes memory value - ) internal { - _onlyAuthorizedCaller(caller, collection, key, tokenId); - _bytesValues[collection][tokenId][_getIdForKey(key)] = value; - emit BytesAttributeUpdated(collection, tokenId, key, value); - } - - function _setAddressAttribute( - address caller, - address collection, - uint256 tokenId, - string memory key, - address value - ) internal { - _onlyAuthorizedCaller(caller, collection, key, tokenId); - _addressValues[collection][tokenId][_getIdForKey(key)] = value; - emit AddressAttributeUpdated(collection, tokenId, key, value); - } - - function _setStringAttribute( - address caller, - address collection, - uint256 tokenId, - string memory key, - string memory value - ) internal { - _onlyAuthorizedCaller(caller, collection, key, tokenId); - _stringValues[collection][tokenId][_getIdForKey(key)] = value; - emit StringAttributeUpdated(collection, tokenId, key, value); - } - - function _setUintAttribute( - address caller, - address collection, - uint256 tokenId, - string memory key, - uint256 value - ) internal { - _onlyAuthorizedCaller(caller, collection, key, tokenId); - _uintValues[collection][tokenId][_getIdForKey(key)] = value; - emit UintAttributeUpdated(collection, tokenId, key, value); - } - - function _setIntAttribute( - address caller, - address collection, - uint256 tokenId, - string memory key, - int256 value - ) internal { - _onlyAuthorizedCaller(caller, collection, key, tokenId); - _intValues[collection][tokenId][_getIdForKey(key)] = value; - emit IntAttributeUpdated(collection, tokenId, key, value); - } + // ------------------- PRESIGNED SETTERS ------------------- /** * @inheritdoc IERC7508 */ - function presignedSetUintAttribute( + function presignedSetAddressAttribute( address setter, address collection, uint256 tokenId, string memory key, - uint256 value, + address value, uint256 deadline, uint8 v, bytes32 r, @@ -1325,7 +1179,7 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_UINT_ATTRIBUTE_TYPEHASH, + SET_ADDRESS_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -1336,18 +1190,18 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { ) ); _checkDeadlineAndSigner(setter, deadline, digest, v, r, s); - _setUintAttribute(setter, collection, tokenId, key, value); + _setAddressAttribute(setter, collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function presignedSetIntAttribute( + function presignedSetBoolAttribute( address setter, address collection, uint256 tokenId, string memory key, - int256 value, + bool value, uint256 deadline, uint8 v, bytes32 r, @@ -1359,7 +1213,7 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_UINT_ATTRIBUTE_TYPEHASH, + SET_BOOL_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -1370,18 +1224,18 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { ) ); _checkDeadlineAndSigner(setter, deadline, digest, v, r, s); - _setIntAttribute(setter, collection, tokenId, key, value); + _setBoolAttribute(setter, collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function presignedSetStringAttribute( + function presignedSetBytesAttribute( address setter, address collection, uint256 tokenId, string memory key, - string memory value, + bytes memory value, uint256 deadline, uint8 v, bytes32 r, @@ -1393,7 +1247,7 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_STRING_ATTRIBUTE_TYPEHASH, + SET_BYTES_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -1404,18 +1258,18 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { ) ); _checkDeadlineAndSigner(setter, deadline, digest, v, r, s); - _setStringAttribute(setter, collection, tokenId, key, value); + _setBytesAttribute(setter, collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function presignedSetBoolAttribute( + function presignedSetIntAttribute( address setter, address collection, uint256 tokenId, string memory key, - bool value, + int256 value, uint256 deadline, uint8 v, bytes32 r, @@ -1427,7 +1281,7 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_BOOL_ATTRIBUTE_TYPEHASH, + SET_UINT_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -1438,18 +1292,18 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { ) ); _checkDeadlineAndSigner(setter, deadline, digest, v, r, s); - _setBoolAttribute(setter, collection, tokenId, key, value); + _setIntAttribute(setter, collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function presignedSetBytesAttribute( + function presignedSetStringAttribute( address setter, address collection, uint256 tokenId, string memory key, - bytes memory value, + string memory value, uint256 deadline, uint8 v, bytes32 r, @@ -1461,7 +1315,7 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_BYTES_ATTRIBUTE_TYPEHASH, + SET_STRING_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -1472,18 +1326,18 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { ) ); _checkDeadlineAndSigner(setter, deadline, digest, v, r, s); - _setBytesAttribute(setter, collection, tokenId, key, value); + _setStringAttribute(setter, collection, tokenId, key, value); } /** * @inheritdoc IERC7508 */ - function presignedSetAddressAttribute( + function presignedSetUintAttribute( address setter, address collection, uint256 tokenId, string memory key, - address value, + uint256 value, uint256 deadline, uint8 v, bytes32 r, @@ -1495,7 +1349,7 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { keccak256( abi.encode( DOMAIN_SEPARATOR, - SET_ADDRESS_ATTRIBUTE_TYPEHASH, + SET_UINT_ATTRIBUTE_TYPEHASH, collection, tokenId, key, @@ -1506,9 +1360,11 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { ) ); _checkDeadlineAndSigner(setter, deadline, digest, v, r, s); - _setAddressAttribute(setter, collection, tokenId, key, value); + _setUintAttribute(setter, collection, tokenId, key, value); } + // ------------------- HELPERS ------------------- + function _checkDeadlineAndSigner( address setter, uint256 deadline, @@ -1526,6 +1382,97 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { } } + function _checkIfMultipleCollectionsAndTokens( + address[] memory collections, + uint256[] memory tokenIds, + uint256 attributesLength + ) + internal + pure + returns ( + bool multipleCollections, + bool multipleTokens, + bool multipleAttributes, + uint256 loopLength + ) + { + multipleCollections = collections.length != 1; + multipleTokens = tokenIds.length != 1; + multipleAttributes = attributesLength != 1; + if ( + (multipleCollections && + multipleAttributes && + collections.length != attributesLength) || + (multipleTokens && + multipleAttributes && + tokenIds.length != attributesLength) || + (multipleCollections && + multipleTokens && + collections.length != tokenIds.length) + ) { + revert LengthsMismatch(); + } + + if (multipleCollections) { + loopLength = collections.length; + } else if (multipleTokens) { + loopLength = tokenIds.length; + } else { + loopLength = attributesLength; + } + } + + /** + * @notice Function to check if the caller is authorized to mamage a given parameter. + * @param collection The address of the collection. + * @param key Key of the attribute. + * @param tokenId The ID of the token. + */ + function _checkOnlyAuthorizedCaller( + address caller, + address collection, + string memory key, + uint256 tokenId + ) private view { + AccessType accessType = _parameterAccessType[collection][ + _keysToIds[key] + ]; + + if ( + accessType == AccessType.Owner && + ((_ownerSettings[collection].useOwnable && + Ownable(collection).owner() != caller) || + (!_ownerSettings[collection].useOwnable && + _ownerSettings[collection].owner != caller)) + ) { + revert NotCollectionOwner(); + } else if ( + accessType == AccessType.Collaborator && + !_collaborators[collection][caller] + ) { + revert NotCollectionCollaborator(); + } else if ( + accessType == AccessType.OwnerOrCollaborator && + ((_ownerSettings[collection].useOwnable && + Ownable(collection).owner() != caller) || + (!_ownerSettings[collection].useOwnable && + _ownerSettings[collection].owner != caller)) && + !_collaborators[collection][caller] + ) { + revert NotCollectionOwnerOrCollaborator(); + } else if ( + accessType == AccessType.TokenOwner && + IERC721(collection).ownerOf(tokenId) != caller + ) { + revert NotTokenOwner(); + } else if ( + accessType == AccessType.SpecificAddress && + !(_parameterSpecificAddress[collection][_keysToIds[key]] == caller) + ) { + revert NotSpecificAddress(); + } + } + /** * @notice Used to get the Id for a key. If the key does not exist, a new ID is created. * IDs are shared among all tokens and types @@ -1543,14 +1490,75 @@ contract RMRKTokenAttributesRepository is IERC7508, Context { } } - /** - * @inheritdoc IERC165 - */ - function supportsInterface( - bytes4 interfaceId - ) public view virtual returns (bool) { - return - interfaceId == type(IERC7508).interfaceId || - interfaceId == type(IERC165).interfaceId; + function _setAddressAttribute( + address caller, + address collection, + uint256 tokenId, + string memory key, + address value + ) internal { + _checkOnlyAuthorizedCaller(caller, collection, key, tokenId); + _addressValues[collection][tokenId][_getIdForKey(key)] = value; + emit AddressAttributeUpdated(collection, tokenId, key, value); + } + + function _setBoolAttribute( + address caller, + address collection, + uint256 tokenId, + string memory key, + bool value + ) internal { + _checkOnlyAuthorizedCaller(caller, collection, key, tokenId); + _boolValues[collection][tokenId][_getIdForKey(key)] = value; + emit BoolAttributeUpdated(collection, tokenId, key, value); + } + + function _setBytesAttribute( + address caller, + address collection, + uint256 tokenId, + string memory key, + bytes memory value + ) internal { + _checkOnlyAuthorizedCaller(caller, collection, key, tokenId); + _bytesValues[collection][tokenId][_getIdForKey(key)] = value; + emit BytesAttributeUpdated(collection, tokenId, key, value); + } + + function _setIntAttribute( + address caller, + address collection, + uint256 tokenId, + string memory key, + int256 value + ) internal { + _checkOnlyAuthorizedCaller(caller, collection, key, tokenId); + _intValues[collection][tokenId][_getIdForKey(key)] = value; + emit IntAttributeUpdated(collection, tokenId, key, value); + } + + function _setStringAttribute( + address caller, + address collection, + uint256 tokenId, + string memory key, + string memory value + ) internal { + _checkOnlyAuthorizedCaller(caller, collection, key, tokenId); + _stringValues[collection][tokenId][_getIdForKey(key)] = value; + emit StringAttributeUpdated(collection, tokenId, key, value); + } + + function _setUintAttribute( + address caller, + address collection, + uint256 tokenId, + string memory key, + uint256 value + ) internal { + _checkOnlyAuthorizedCaller(caller, collection, key, tokenId); + _uintValues[collection][tokenId][_getIdForKey(key)] = value; + emit UintAttributeUpdated(collection, tokenId, key, value); } }