@@ -11,11 +11,12 @@ import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/Mes
11
11
import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol " ;
12
12
13
13
import { BaseOrgStoryNFT } from "./BaseOrgStoryNFT.sol " ;
14
+ import { CachableNFT } from "./CachableNFT.sol " ;
14
15
import { IStoryBadgeNFT } from "../interfaces/story-nft/IStoryBadgeNFT.sol " ;
15
16
16
17
/// @title Story Badge NFT
17
18
/// @notice A Story Badge is a soulbound NFT that has an unified token URI for all tokens.
18
- contract StoryBadgeNFT is IStoryBadgeNFT , BaseOrgStoryNFT , ERC721Holder {
19
+ contract StoryBadgeNFT is IStoryBadgeNFT , BaseOrgStoryNFT , CachableNFT , ERC721Holder {
19
20
using MessageHashUtils for bytes32 ;
20
21
21
22
/// @notice Story Proof-of-Creativity PILicense Template address.
@@ -97,25 +98,16 @@ contract StoryBadgeNFT is IStoryBadgeNFT, BaseOrgStoryNFT, ERC721Holder {
97
98
if (! SignatureChecker.isValidSignatureNow ($.signer, digest, signature))
98
99
revert StoryBadgeNFT__InvalidSignature ();
99
100
100
- // Mint the badge and register it as an IP
101
- (tokenId, ipId) = _mintAndRegisterIp (
102
- address (this ),
103
- $.tokenURI,
104
- $.ipMetadataURI,
105
- $.ipMetadataHash,
106
- $.nftMetadataHash
107
- );
101
+ // Try to transfer from cache first
102
+ (tokenId, ipId) = _transferFromCache (recipient);
108
103
109
- address [] memory parentIpIds = new address [](1 );
110
- uint256 [] memory licenseTermsIds = new uint256 [](1 );
111
- parentIpIds[0 ] = orgIpId ();
112
- licenseTermsIds[0 ] = DEFAULT_LICENSE_TERMS_ID;
113
-
114
- // Make the badge a derivative of the organization IP
115
- _makeDerivative (ipId, parentIpIds, PIL_TEMPLATE, licenseTermsIds, "" , 0 );
104
+ if (ipId == address (0 )) {
105
+ // cache miss or cache mode is disabled, mint directly
106
+ (tokenId, ipId) = _mintToSelf ();
116
107
117
- // Transfer the badge to the recipient
118
- _safeTransfer (address (this ), recipient, tokenId);
108
+ // Transfer the badge to the recipient
109
+ _transfer (address (this ), recipient, tokenId);
110
+ }
119
111
120
112
emit StoryBadgeNFTMinted (recipient, tokenId, ipId);
121
113
}
@@ -164,6 +156,38 @@ contract StoryBadgeNFT is IStoryBadgeNFT, BaseOrgStoryNFT, ERC721Holder {
164
156
return "" ;
165
157
}
166
158
159
+ /// @notice Mints an NFT to the contract itself.
160
+ /// @return tokenId The token ID of the minted NFT.
161
+ /// @return ipId The IP ID of the minted NFT.
162
+ function _mintToSelf () internal override returns (uint256 tokenId , address ipId ) {
163
+ StoryBadgeNFTStorage storage $ = _getStoryBadgeNFTStorage ();
164
+
165
+ // Mint the badge and register it as an IP
166
+ (tokenId, ipId) = _mintAndRegisterIp (
167
+ address (this ),
168
+ $.tokenURI,
169
+ $.ipMetadataURI,
170
+ $.ipMetadataHash,
171
+ $.nftMetadataHash
172
+ );
173
+
174
+ address [] memory parentIpIds = new address [](1 );
175
+ uint256 [] memory licenseTermsIds = new uint256 [](1 );
176
+ parentIpIds[0 ] = orgIpId ();
177
+ licenseTermsIds[0 ] = DEFAULT_LICENSE_TERMS_ID;
178
+
179
+ // Make the badge a derivative of the organization IP
180
+ _makeDerivative (ipId, parentIpIds, PIL_TEMPLATE, licenseTermsIds, "" , 0 );
181
+ }
182
+
183
+ /// @notice Transfers an NFT from one address to another.
184
+ /// @param from The address to transfer the NFT from.
185
+ /// @param to The address to transfer the NFT to.
186
+ /// @param tokenId The token ID of the NFT to transfer.
187
+ function _transferFrom (address from , address to , uint256 tokenId ) internal override {
188
+ _transfer (from, to, tokenId);
189
+ }
190
+
167
191
/// @dev Returns the storage struct of StoryBadgeNFT.
168
192
function _getStoryBadgeNFTStorage () private pure returns (StoryBadgeNFTStorage storage $) {
169
193
assembly {
0 commit comments