Skip to content

Commit

Permalink
compute the tokenId from poi hash and reuse the authoriseMint function
Browse files Browse the repository at this point in the history
  • Loading branch information
nour-karoui committed Oct 24, 2024
1 parent 0070789 commit 88368b7
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 47 deletions.
10 changes: 0 additions & 10 deletions src/IAuthorizeMints.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
60 changes: 34 additions & 26 deletions src/IPNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/*
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
12 changes: 1 addition & 11 deletions src/SignedMintAuthorizer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 88368b7

Please sign in to comment.