Skip to content

Commit ac0cd9d

Browse files
authored
Refactor LazyMint bases (#233)
* refactor ERC721LazyMint and ERC1155LazyMint * update tests * run prettier * remove data param from claim * ERC721Drop: nextTokenIdToClaim * run prettier
1 parent af5a3d1 commit ac0cd9d

File tree

7 files changed

+309
-241
lines changed

7 files changed

+309
-241
lines changed

contracts/base/ERC1155DelayedReveal.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import "./ERC1155LazyMint.sol";
55
import "../extension/DelayedReveal.sol";
66

77
/**
8-
* BASE: ERC1155Base
9-
* EXTENSION: LazyMint, DelayedReveal
8+
* BASE: ERC1155LazyMint
9+
* EXTENSION: DelayedReveal
1010
*
11-
* The `ERC1155DelayedReveal` contract uses the `ERC1155Base` contract, along with the `LazyMint` and `DelayedReveal` extension.
11+
* The `ERC1155DelayedReveal` contract uses the `DelayedReveal` extension.
1212
*
1313
* 'Lazy minting' means defining the metadata of NFTs without minting it to an address. Regular 'minting'
1414
* of NFTs means actually assigning an owner to an NFT.

contracts/base/ERC1155LazyMint.sol

Lines changed: 177 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,40 @@
11
// SPDX-License-Identifier: Apache-2.0
22
pragma 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";
511
import "../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
}

contracts/base/ERC721DelayedReveal.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import "./ERC721LazyMint.sol";
66
import "../extension/DelayedReveal.sol";
77

88
/**
9-
* BASE: ERC721Base
10-
* EXTENSION: LazyMint, DelayedReveal
9+
* BASE: ERC721LazyMint
10+
* EXTENSION: DelayedReveal
1111
*
12-
* The `ERC721DelayedReveal` contract uses the `ERC721Base` contract, along with the `LazyMint` and `DelayedReveal` extension.
12+
* The `ERC721DelayedReveal` contract uses the `ERC721LazyMint` contract, along with `DelayedReveal` extension.
1313
*
1414
* 'Lazy minting' means defining the metadata of NFTs without minting it to an address. Regular 'minting'
1515
* of NFTs means actually assigning an owner to an NFT.

contracts/base/ERC721Drop.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ contract ERC721Drop is
137137
return nextTokenIdToLazyMint;
138138
}
139139

140+
/// @notice The tokenId assigned to the next new NFT to be claimed.
141+
function nextTokenIdToClaim() public view virtual returns (uint256) {
142+
return _currentIndex;
143+
}
144+
140145
/*///////////////////////////////////////////////////////////////
141146
Delayed reveal logic
142147
//////////////////////////////////////////////////////////////*/

0 commit comments

Comments
 (0)