diff --git a/src/IAuthorizeMints.sol b/src/IAuthorizeMints.sol index 26038a9b..5d8de728 100644 --- a/src/IAuthorizeMints.sol +++ b/src/IAuthorizeMints.sol @@ -8,13 +8,6 @@ struct SignedMintAuthorization { bytes authorization; } -struct SignedPoiAuthorization { - string poi; - string tokenURI; - address to; - bytes authorization; -} - /// @title IAuthorizeMints /// @author molecule.to /// @notice a flexible interface to gate token mint calls on another contract, built for IP-NFTs @@ -29,7 +22,4 @@ interface IAuthorizeMints { /// @notice called by the gated token contract to signal that a token has been minted and an authorization can be invalidated /// @param data implementation specific data function redeem(bytes memory data) external; - - /// @notice checks whether the poi is owned by address to by verifying the trustee's signature - function verifyPoi(bytes memory signedAuthorization) external view returns (bool); } diff --git a/src/IPNFT.sol b/src/IPNFT.sol index 4c0e5967..f5998c57 100644 --- a/src/IPNFT.sol +++ b/src/IPNFT.sol @@ -8,7 +8,7 @@ import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/O import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import { CountersUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { IAuthorizeMints, SignedMintAuthorization, SignedPoiAuthorization } from "./IAuthorizeMints.sol"; +import { IAuthorizeMints, SignedMintAuthorization } from "./IAuthorizeMints.sol"; import { IReservable } from "./IReservable.sol"; /* @@ -102,6 +102,39 @@ contract IPNFT is ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, IReser emit Reserved(_msgSender(), reservationId); } + /** + * @notice mints an IPNFT with `tokenURI` as source of metadata. This IPNFT is linked a proof of idea (POI) which is a hash of any collection of files that represents an idea, anchored on any chain. + * @notice We are charging a nominal fee to symbolically represent the transfer of ownership rights, for a price of .001 ETH (<$2USD at current prices). This helps ensure the protocol is affordable to almost all projects, but discourages frivolous IP-NFT minting. + * + * @param to the recipient of the NFT + * @param poi the hash of the poi that will be computed to the tokenId + * @param _tokenURI a location that resolves to a valid IP-NFT metadata structure + * @param _symbol a symbol that represents the IPNFT's derivatives. Can be changed by the owner + * @param authorization a bytes encoded parameter that ensures that the poi is owned by the owner (to param) + * @return computedTokenId + */ + function mintWithPOI(address to, bytes calldata poi, string calldata _tokenURI, string calldata _symbol, bytes calldata authorization) + external + payable + whenNotPaused + returns (uint256) + { + uint256 computedTokenId = uint256(keccak256(poi)); + if (msg.value < SYMBOLIC_MINT_FEE) { + revert MintingFeeTooLow(); + } + + if (!mintAuthorizer.authorizeMint(_msgSender(), to, abi.encode(SignedMintAuthorization(computedTokenId, _tokenURI, authorization)))) { + revert Unauthorized(); + } + + mintAuthorizer.redeem(authorization); + _mint(to, computedTokenId); + _setTokenURI(computedTokenId, _tokenURI); + emit IPNFTMinted(to, computedTokenId, _tokenURI, _symbol); + return computedTokenId; + } + /** * @notice mints an IPNFT with `tokenURI` as source of metadata. Invalidates the reservation. Redeems `mintpassId` on the authorizer contract * @notice We are charging a nominal fee to symbolically represent the transfer of ownership rights, for a price of .001 ETH (<$2USD at current prices). This helps ensure the protocol is affordable to almost all projects, but discourages frivolous IP-NFT minting. @@ -142,31 +175,6 @@ contract IPNFT is ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, IReser return reservationId; } - /** - * @notice mints an IPNFT with `tokenURI` as source of metadata. This IPNFT is linked a proof of idea (POI) which is a hash of any collection of files that represents an idea, anchored on any chain. - * @notice We are charging a nominal fee to symbolically represent the transfer of ownership rights, for a price of .001 ETH (<$2USD at current prices). This helps ensure the protocol is affordable to almost all projects, but discourages frivolous IP-NFT minting. - * - * @param to the recipient of the NFT - * @param _tokenURI a location that resolves to a valid IP-NFT metadata structure - * @param _symbol a symbol that represents the IPNFT's derivatives. Can be changed by the owner - * @param authorization a bytes encoded parameter that ensures that the poi is owned by the owner (to param) - * @param poi the hash of the poi that will be the tokenId - * @return reservationId the tokenId - */ - function mintWithPOI( - address to, - uint256 reservationId, - string calldata _tokenURI, - string calldata _symbol, - bytes calldata authorization, - string memory poi - ) external payable whenNotPaused returns (uint256) { - if (!mintAuthorizer.verifyPoi(abi.encode(SignedPoiAuthorization(poi, _tokenURI, to, authorization)))) { - revert Unauthorized(); - } - return this.mintReservation(to, reservationId, _tokenURI, _symbol, authorization); - } - /** * @notice grants time limited "read" access to gated resources * @param reader the address that should be able to access gated content diff --git a/src/SignedMintAuthorizer.sol b/src/SignedMintAuthorizer.sol index fe083447..51e04b40 100644 --- a/src/SignedMintAuthorizer.sol +++ b/src/SignedMintAuthorizer.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.18; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { IAuthorizeMints, SignedMintAuthorization, SignedPoiAuthorization } from "./IAuthorizeMints.sol"; +import { IAuthorizeMints, SignedMintAuthorization } from "./IAuthorizeMints.sol"; /// @title SignedMintAuthorizer /// @author molecule.to @@ -36,16 +36,6 @@ contract SignedMintAuthorizer is IAuthorizeMints, Ownable { return trustedSigners[signer]; } - function verifyPoi(bytes memory signedPoiAuthorization) external view override returns (bool) { - SignedPoiAuthorization memory auth = abi.decode(signedPoiAuthorization, (SignedPoiAuthorization)); - - bytes32 signedHash = ECDSA.toEthSignedMessageHash(keccak256(abi.encodePacked(auth.poi, auth.tokenURI, auth.to))); - - (address signer,) = ECDSA.tryRecover(signedHash, auth.authorization); - - return trustedSigners[signer]; - } - /// @inheritdoc IAuthorizeMints /// @dev this authorizer does not restrict reservations function authorizeReservation(address) external pure override returns (bool) {