From 2d8650dc7c30fa8f56a3b0a25ee3c6f5a9958e27 Mon Sep 17 00:00:00 2001 From: stadolf Date: Tue, 24 Sep 2024 15:56:11 +0200 Subject: [PATCH] repurpose MintAuthorizer to allow signed metadata amendments Signed-off-by: stadolf --- src/IPNFT.sol | 13 +++++++++++++ subgraph/abis/IPNFT.json | 23 +++++++++++++++++++++++ test/IPNFT.t.sol | 22 ++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/IPNFT.sol b/src/IPNFT.sol index 597869e3..4005f02d 100644 --- a/src/IPNFT.sol +++ b/src/IPNFT.sol @@ -161,6 +161,18 @@ contract IPNFT is ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, IReser emit ReadAccessGranted(tokenId, reader, until); } + function amendMetadata(uint256 tokenId, string calldata _newTokenURI, bytes calldata authorization) external { + if (ownerOf(tokenId) != _msgSender()) { + revert Unauthorized(); + } + + if (!mintAuthorizer.authorizeMint(_msgSender(), _msgSender(), abi.encode(SignedMintAuthorization(tokenId, _newTokenURI, authorization)))) { + revert Unauthorized(); + } + + _setTokenURI(tokenId, _newTokenURI); + } + /** * @notice check whether `reader` currently is able to access gated content behind `tokenId` * @param reader the address in question @@ -177,6 +189,7 @@ contract IPNFT is ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, IReser require(success, "transfer failed"); } + /// @inheritdoc UUPSUpgradeable function _authorizeUpgrade(address /*newImplementation*/ ) internal diff --git a/subgraph/abis/IPNFT.json b/subgraph/abis/IPNFT.json index d342d424..b03fe6f6 100644 --- a/subgraph/abis/IPNFT.json +++ b/subgraph/abis/IPNFT.json @@ -4,6 +4,29 @@ "inputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "amendMetadata", + "inputs": [ + { + "name": "tokenId", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_newTokenURI", + "type": "string", + "internalType": "string" + }, + { + "name": "authorization", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "approve", diff --git a/test/IPNFT.t.sol b/test/IPNFT.t.sol index 05dfa23d..85607c27 100644 --- a/test/IPNFT.t.sol +++ b/test/IPNFT.t.sol @@ -24,6 +24,7 @@ contract IPNFTTest is IPNFTMintHelper { event IPNFTMinted(address indexed owner, uint256 indexed tokenId, string tokenURI, string symbol); event SymbolUpdated(uint256 indexed tokenId, string symbol); event ReadAccessGranted(uint256 indexed tokenId, address indexed reader, uint256 until); + event MetadataUpdate(uint256 tokenId); IPNFT internal ipnft; @@ -216,4 +217,25 @@ contract IPNFTTest is IPNFTMintHelper { vm.warp(block.timestamp + 60); assertFalse(ipnft.canRead(bob, tokenId)); } + + function testOwnerCanAmendMetadataAfterSignoff() public { + mintAToken(ipnft, alice); + + vm.startPrank(deployer); + ipnft.setAuthorizer(new SignedMintAuthorizer(deployer)); + vm.stopPrank(); + + bytes32 authMessageHash = ECDSA.toEthSignedMessageHash(keccak256(abi.encodePacked(alice, alice, uint256(1), "ipfs://QmNewUri"))); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(deployerPk, authMessageHash); + bytes memory authorization = abi.encodePacked(r, s, v); + + vm.startPrank(alice); + vm.expectEmit(true, true, false, false); + emit MetadataUpdate(1); + ipnft.amendMetadata(1, "ipfs://QmNewUri", authorization); + assertEq(ipnft.tokenURI(1), "ipfs://QmNewUri"); + vm.stopPrank(); + } + + }