Skip to content

Commit 0070789

Browse files
committed
add poi verification before minting function
1 parent 20c5824 commit 0070789

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

src/IAuthorizeMints.sol

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ struct SignedMintAuthorization {
88
bytes authorization;
99
}
1010

11+
struct SignedPoiAuthorization {
12+
string poi;
13+
string tokenURI;
14+
address to;
15+
bytes authorization;
16+
}
17+
1118
/// @title IAuthorizeMints
1219
/// @author molecule.to
1320
/// @notice a flexible interface to gate token mint calls on another contract, built for IP-NFTs
@@ -22,4 +29,7 @@ interface IAuthorizeMints {
2229
/// @notice called by the gated token contract to signal that a token has been minted and an authorization can be invalidated
2330
/// @param data implementation specific data
2431
function redeem(bytes memory data) external;
32+
33+
/// @notice checks whether the poi is owned by address to by verifying the trustee's signature
34+
function verifyPoi(bytes memory signedAuthorization) external view returns (bool);
2535
}

src/IPNFT.sol

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/O
88
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
99
import { CountersUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
1010
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
11-
import { IAuthorizeMints, SignedMintAuthorization } from "./IAuthorizeMints.sol";
11+
import { IAuthorizeMints, SignedMintAuthorization, SignedPoiAuthorization } from "./IAuthorizeMints.sol";
1212
import { IReservable } from "./IReservable.sol";
1313

1414
/*
@@ -104,7 +104,7 @@ contract IPNFT is ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, IReser
104104

105105
/**
106106
* @notice mints an IPNFT with `tokenURI` as source of metadata. Invalidates the reservation. Redeems `mintpassId` on the authorizer contract
107-
* @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 the ensure the protocol is affordable to almost all projects, but discourages frivolous IP-NFT minting.
107+
* @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.
108108
*
109109
* @param to the recipient of the NFT
110110
* @param reservationId the reserved token id that has been reserved with `reserve()`
@@ -142,6 +142,31 @@ contract IPNFT is ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, IReser
142142
return reservationId;
143143
}
144144

145+
/**
146+
* @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.
147+
* @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.
148+
*
149+
* @param to the recipient of the NFT
150+
* @param _tokenURI a location that resolves to a valid IP-NFT metadata structure
151+
* @param _symbol a symbol that represents the IPNFT's derivatives. Can be changed by the owner
152+
* @param authorization a bytes encoded parameter that ensures that the poi is owned by the owner (to param)
153+
* @param poi the hash of the poi that will be the tokenId
154+
* @return reservationId the tokenId
155+
*/
156+
function mintWithPOI(
157+
address to,
158+
uint256 reservationId,
159+
string calldata _tokenURI,
160+
string calldata _symbol,
161+
bytes calldata authorization,
162+
string memory poi
163+
) external payable whenNotPaused returns (uint256) {
164+
if (!mintAuthorizer.verifyPoi(abi.encode(SignedPoiAuthorization(poi, _tokenURI, to, authorization)))) {
165+
revert Unauthorized();
166+
}
167+
return this.mintReservation(to, reservationId, _tokenURI, _symbol, authorization);
168+
}
169+
145170
/**
146171
* @notice grants time limited "read" access to gated resources
147172
* @param reader the address that should be able to access gated content
@@ -188,7 +213,7 @@ contract IPNFT is ERC721URIStorageUpgradeable, ERC721BurnableUpgradeable, IReser
188213
(bool success,) = _msgSender().call{ value: address(this).balance }("");
189214
require(success, "transfer failed");
190215
}
191-
216+
192217
/// @inheritdoc UUPSUpgradeable
193218
function _authorizeUpgrade(address /*newImplementation*/ )
194219
internal

src/SignedMintAuthorizer.sol

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity 0.8.18;
33

44
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
55
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
6-
import { IAuthorizeMints, SignedMintAuthorization } from "./IAuthorizeMints.sol";
6+
import { IAuthorizeMints, SignedMintAuthorization, SignedPoiAuthorization } from "./IAuthorizeMints.sol";
77

88
/// @title SignedMintAuthorizer
99
/// @author molecule.to
@@ -36,6 +36,16 @@ contract SignedMintAuthorizer is IAuthorizeMints, Ownable {
3636
return trustedSigners[signer];
3737
}
3838

39+
function verifyPoi(bytes memory signedPoiAuthorization) external view override returns (bool) {
40+
SignedPoiAuthorization memory auth = abi.decode(signedPoiAuthorization, (SignedPoiAuthorization));
41+
42+
bytes32 signedHash = ECDSA.toEthSignedMessageHash(keccak256(abi.encodePacked(auth.poi, auth.tokenURI, auth.to)));
43+
44+
(address signer,) = ECDSA.tryRecover(signedHash, auth.authorization);
45+
46+
return trustedSigners[signer];
47+
}
48+
3949
/// @inheritdoc IAuthorizeMints
4050
/// @dev this authorizer does not restrict reservations
4151
function authorizeReservation(address) external pure override returns (bool) {

0 commit comments

Comments
 (0)