11// SPDX-License-Identifier: Apache-2.0
22pragma solidity ^ 0.8.0 ;
33
4- import "./ERC1155Base.sol " ;
4+ import { ERC1155 } from "../eip/ERC1155.sol " ;
5+
6+ import "../extension/ContractMetadata.sol " ;
7+ import "../extension/Multicall.sol " ;
8+ import "../extension/Ownable.sol " ;
9+ import "../extension/Royalty.sol " ;
10+ import "../extension/BatchMintMetadata.sol " ;
511import "../extension/LazyMint.sol " ;
612
13+ import "../lib/TWStrings.sol " ;
14+
715/**
816 * BASE: ERC1155Base
917 * EXTENSION: LazyMint
1018 *
11- * The `ERC1155LazyMint` contract uses the `ERC1155Base` contract, along with the `LazyMint` extension.
19+ * The `ERC1155LazyMint` smart contract implements the ERC1155 NFT standard.
20+ * It includes the following additions to standard ERC1155 logic:
21+ *
22+ * - Lazy minting
23+ *
24+ * - Ability to mint NFTs via the provided `mintTo` and `batchMintTo` functions.
25+ *
26+ * - Contract metadata for royalty support on platforms such as OpenSea that use
27+ * off-chain information to distribute roaylties.
28+ *
29+ * - Ownership of the contract, with the ability to restrict certain functions to
30+ * only be called by the contract's owner.
31+ *
32+ * - Multicall capability to perform multiple actions atomically
33+ *
34+ * - EIP 2981 compliance for royalty support on NFT marketplaces.
35+ *
36+ *
37+ * The `ERC1155LazyMint` contract uses the `LazyMint` extension.
1238 *
1339 * 'Lazy minting' means defining the metadata of NFTs without minting it to an address. Regular 'minting'
1440 * of NFTs means actually assigning an owner to an NFT.
@@ -18,7 +44,19 @@ import "../extension/LazyMint.sol";
1844 *
1945 */
2046
21- contract ERC1155LazyMint is ERC1155Base , LazyMint {
47+ contract ERC1155LazyMint is ERC1155 , ContractMetadata , Ownable , Royalty , Multicall , BatchMintMetadata , LazyMint {
48+ using TWStrings for uint256 ;
49+
50+ /*//////////////////////////////////////////////////////////////
51+ Mappings
52+ //////////////////////////////////////////////////////////////*/
53+
54+ /**
55+ * @notice Returns the total supply of NFTs of a given tokenId
56+ * @dev Mapping from tokenId => total circulating supply of NFTs of that tokenId.
57+ */
58+ mapping (uint256 => uint256 ) public totalSupply;
59+
2260 /*//////////////////////////////////////////////////////////////
2361 Constructor
2462 //////////////////////////////////////////////////////////////*/
@@ -28,59 +66,127 @@ contract ERC1155LazyMint is ERC1155Base, LazyMint {
2866 string memory _symbol ,
2967 address _royaltyRecipient ,
3068 uint128 _royaltyBps
31- ) ERC1155Base (_name, _symbol, _royaltyRecipient, _royaltyBps) {}
69+ ) ERC1155 (_name, _symbol) {
70+ _setupOwner (msg .sender );
71+ _setupDefaultRoyaltyInfo (_royaltyRecipient, _royaltyBps);
72+ }
73+
74+ /*//////////////////////////////////////////////////////////////
75+ Overriden metadata logic
76+ //////////////////////////////////////////////////////////////*/
77+
78+ /// @notice Returns the metadata URI for the given tokenId.
79+ function uri (uint256 _tokenId ) public view virtual override returns (string memory ) {
80+ string memory batchUri = getBaseURI (_tokenId);
81+ return string (abi.encodePacked (batchUri, _tokenId.toString ()));
82+ }
3283
3384 /*//////////////////////////////////////////////////////////////
34- OVERRIDEN MINT LOGIC
85+ CLAIM LOGIC
3586 //////////////////////////////////////////////////////////////*/
3687
3788 /**
38- * @notice Lets an authorized address mint lazy minted NFTs to a recipient.
39- * @dev - The logic in the `_canMint` function determines whether the caller is authorized to mint NFTs.
89+ * @notice Lets an address claim multiple lazy minted NFTs at once to a recipient.
90+ * Contract creators should override this function to create custom logic for claiming,
91+ * for e.g. price collection, allowlist, max quantity, etc.
4092 *
41- * @param _to The recipient of the NFTs to mint.
42- * @param _tokenId The tokenId of the lazy minted NFT to mint.
43- * @param _amount The amount of the same NFT to mint.
93+ * @dev The logic in the `verifyClaim` function determines whether the caller is authorized to mint NFTs.
94+ *
95+ * @param _receiver The recipient of the tokens to mint.
96+ * @param _tokenId The tokenId of the lazy minted NFT to mint.
97+ * @param _quantity The number of tokens to mint.
4498 */
45- function mintTo (
46- address _to ,
99+ function claim (
100+ address _receiver ,
47101 uint256 _tokenId ,
48- string memory ,
49- uint256 _amount
50- ) public virtual override {
51- require ( _canMint (), " Not authorized to mint. " );
102+ uint256 _quantity
103+ ) public payable virtual {
104+ verifyClaim ( msg . sender , _tokenId, _quantity); // add your claim verification logic by overriding this function
105+
52106 require (_tokenId < nextTokenIdToMint (), "invalid id " );
53107
54- _mint (_to , _tokenId, _amount , "" );
108+ _mint (_receiver , _tokenId, _quantity , "" );
55109 }
56110
57111 /**
58- * @notice Lets an authorized address mint multiple lazy minted NFTs at once to a recipient.
59- * @dev The logic in the `_canMint` function determines whether the caller is authorized to mint NFTs.
112+ * @notice Override this function to add logic for claim verification, based on conditions
113+ * such as allowlist, price, max quantity etc.
114+ *
115+ * @dev Checks a request to claim NFTs against a custom condition.
116+ *
117+ * @param _claimer Caller of the claim function.
118+ * @param _tokenId The tokenId of the lazy minted NFT to mint.
119+ * @param _quantity The number of NFTs being claimed.
120+ */
121+ function verifyClaim (
122+ address _claimer ,
123+ uint256 _tokenId ,
124+ uint256 _quantity
125+ ) public view virtual {}
126+
127+ /**
128+ * @notice Lets an owner or approved operator burn NFTs of the given tokenId.
60129 *
61- * @param _to The recipient of the NFT to mint .
62- * @param _tokenIds The tokenIds of the NFTs to mint .
63- * @param _amounts The amounts of each NFT to mint .
130+ * @param _owner The owner of the NFT to burn .
131+ * @param _tokenId The tokenId of the NFT to burn .
132+ * @param _amount The amount of the NFT to burn .
64133 */
65- function batchMintTo (
66- address _to ,
134+ function burn (
135+ address _owner ,
136+ uint256 _tokenId ,
137+ uint256 _amount
138+ ) external virtual {
139+ address caller = msg .sender ;
140+
141+ require (caller == _owner || isApprovedForAll[_owner][caller], "Unapproved caller " );
142+ require (balanceOf[_owner][_tokenId] >= _amount, "Not enough tokens owned " );
143+
144+ _burn (_owner, _tokenId, _amount);
145+ }
146+
147+ /**
148+ * @notice Lets an owner or approved operator burn NFTs of the given tokenIds.
149+ *
150+ * @param _owner The owner of the NFTs to burn.
151+ * @param _tokenIds The tokenIds of the NFTs to burn.
152+ * @param _amounts The amounts of the NFTs to burn.
153+ */
154+ function burnBatch (
155+ address _owner ,
67156 uint256 [] memory _tokenIds ,
68- uint256 [] memory _amounts ,
69- string memory
70- ) public virtual override {
71- require ( _canMint (), " Not authorized to mint. " );
72- require (_amounts. length > 0 , "Minting zero tokens. " );
157+ uint256 [] memory _amounts
158+ ) external virtual {
159+ address caller = msg . sender ;
160+
161+ require (caller == _owner || isApprovedForAll[_owner][caller] , "Unapproved caller " );
73162 require (_tokenIds.length == _amounts.length , "Length mismatch " );
74163
75164 for (uint256 i = 0 ; i < _tokenIds.length ; i += 1 ) {
76- require (_tokenIds[i] < nextTokenIdToMint () , "invalid id " );
165+ require (balanceOf[_owner][ _tokenIds[i]] >= _amounts[i] , "Not enough tokens owned " );
77166 }
78167
79- _mintBatch (_to, _tokenIds, _amounts, "" );
168+ _burnBatch (_owner, _tokenIds, _amounts);
169+ }
170+
171+ /*//////////////////////////////////////////////////////////////
172+ ERC165 Logic
173+ //////////////////////////////////////////////////////////////*/
174+
175+ /// @notice Returns whether this contract supports the given interface.
176+ function supportsInterface (bytes4 interfaceId ) public view virtual override (ERC1155 , IERC165 ) returns (bool ) {
177+ return
178+ interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
179+ interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
180+ interfaceId == 0x0e89341c || // ERC165 Interface ID for ERC1155MetadataURI
181+ interfaceId == type (IERC2981 ).interfaceId; // ERC165 ID for ERC2981
80182 }
81183
184+ /*//////////////////////////////////////////////////////////////
185+ View functions
186+ //////////////////////////////////////////////////////////////*/
187+
82188 /// @notice The tokenId assigned to the next new NFT to be lazy minted.
83- function nextTokenIdToMint () public view virtual override returns (uint256 ) {
189+ function nextTokenIdToMint () public view virtual returns (uint256 ) {
84190 return nextTokenIdToLazyMint;
85191 }
86192
@@ -92,4 +198,43 @@ contract ERC1155LazyMint is ERC1155Base, LazyMint {
92198 function _canLazyMint () internal view virtual override returns (bool ) {
93199 return msg .sender == owner ();
94200 }
201+
202+ /// @dev Returns whether contract metadata can be set in the given execution context.
203+ function _canSetContractURI () internal view virtual override returns (bool ) {
204+ return msg .sender == owner ();
205+ }
206+
207+ /// @dev Returns whether owner can be set in the given execution context.
208+ function _canSetOwner () internal view virtual override returns (bool ) {
209+ return msg .sender == owner ();
210+ }
211+
212+ /// @dev Returns whether royalty info can be set in the given execution context.
213+ function _canSetRoyaltyInfo () internal view virtual override returns (bool ) {
214+ return msg .sender == owner ();
215+ }
216+
217+ /// @dev Runs before every token transfer / mint / burn.
218+ function _beforeTokenTransfer (
219+ address operator ,
220+ address from ,
221+ address to ,
222+ uint256 [] memory ids ,
223+ uint256 [] memory amounts ,
224+ bytes memory data
225+ ) internal virtual override {
226+ super ._beforeTokenTransfer (operator, from, to, ids, amounts, data);
227+
228+ if (from == address (0 )) {
229+ for (uint256 i = 0 ; i < ids.length ; ++ i) {
230+ totalSupply[ids[i]] += amounts[i];
231+ }
232+ }
233+
234+ if (to == address (0 )) {
235+ for (uint256 i = 0 ; i < ids.length ; ++ i) {
236+ totalSupply[ids[i]] -= amounts[i];
237+ }
238+ }
239+ }
95240}
0 commit comments