Skip to content

Commit dd2559a

Browse files
Krishang NadgaudaKrishang Nadgauda
authored andcommitted
SignatureDrop uses DropSinglePhase
1 parent d96518c commit dd2559a

File tree

2 files changed

+102
-123
lines changed

2 files changed

+102
-123
lines changed

contracts/drop/SignatureDrop.sol

Lines changed: 26 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import "../feature/DelayedReveal.sol";
3333
import "../feature/LazyMint.sol";
3434
import "../feature/PermissionsEnumerable.sol";
3535
import "../feature/SignatureMintERC721Upgradeable.sol";
36+
import "../feature/DropSinglePhase.sol";
3637

3738
contract SignatureDrop is
3839
Initializable,
@@ -44,8 +45,8 @@ contract SignatureDrop is
4445
DelayedReveal,
4546
LazyMint,
4647
PermissionsEnumerable,
48+
DropSinglePhase,
4749
SignatureMintERC721Upgradeable,
48-
IDropClaimCondition,
4950
ReentrancyGuardUpgradeable,
5051
ERC2771ContextUpgradeable,
5152
MulticallUpgradeable,
@@ -74,12 +75,6 @@ contract SignatureDrop is
7475
/// @dev The tokenId of the next NFT that will be minted / lazy minted.
7576
uint256 public nextTokenIdToMint;
7677

77-
/// @dev The active conditions for claiming lazy minted tokens.
78-
ClaimCondition public claimCondition;
79-
80-
/// @dev The ID for the active claim condition.
81-
bytes32 private conditionId;
82-
8378
/*///////////////////////////////////////////////////////////////
8479
Mappings
8580
//////////////////////////////////////////////////////////////*/
@@ -101,7 +96,6 @@ contract SignatureDrop is
10196
uint256 pricePerToken,
10297
address indexed currency
10398
);
104-
event ClaimConditionUpdated(ClaimCondition condition, bool resetEligibility);
10599

106100
/*///////////////////////////////////////////////////////////////
107101
Constructor + initializer logic
@@ -238,88 +232,36 @@ contract SignatureDrop is
238232
address receiver = _req.to == address(0) ? msg.sender : _req.to;
239233

240234
// Collect price
241-
collectPrice(_req.quantity, _req.currency, _req.pricePerToken);
235+
collectPriceOnClaim(_req.quantity, _req.currency, _req.pricePerToken);
242236

243237
// Mint tokens.
244238
_mint(receiver, _req.quantity);
245239

246240
emit TokensMinted(_msgSender(), _req.to, tokenIdToMint, _req.quantity, _req.pricePerToken, _req.currency);
247241
}
248242

249-
/// @dev Lets an account claim NFTs.
250-
function claim(
251-
address _receiver,
252-
uint256 _quantity,
253-
address _currency,
254-
uint256 _pricePerToken
255-
) external payable {
256-
ClaimCondition memory condition = claimCondition;
257-
258-
// Verify claim
259-
require(
260-
_currency == condition.currency && _pricePerToken == condition.pricePerToken,
261-
"invalid currency or price."
262-
);
263-
require(_quantity > 0 && _quantity <= condition.quantityLimitPerTransaction, "invalid quantity.");
264-
require(condition.supplyClaimed + _quantity <= condition.maxClaimableSupply, "exceed max claimable supply.");
265-
266-
uint256 tokenIdToClaim = _currentIndex;
267-
require(tokenIdToClaim + _quantity <= nextTokenIdToMint, "not enough minted tokens.");
268-
269-
uint256 lastClaimTimestampForClaimer = lastClaimTimestamp[msg.sender][conditionId];
270-
require(
271-
lastClaimTimestampForClaimer == 0 ||
272-
block.timestamp >= lastClaimTimestampForClaimer + condition.waitTimeInSecondsBetweenClaims,
273-
"cannot claim."
274-
);
275-
276-
// Collect price for claim.
277-
collectPrice(_quantity, _currency, _pricePerToken);
278-
279-
// Mark the claim.
280-
lastClaimTimestamp[msg.sender][conditionId] = block.timestamp;
281-
claimCondition.supplyClaimed += _quantity;
282-
283-
// Transfer tokens being claimed.
284-
_mint(_receiver, _quantity);
285-
286-
emit TokensMinted(_msgSender(), _receiver, tokenIdToClaim, _quantity, _pricePerToken, _currency);
287-
}
288-
289-
function setClaimCondition(ClaimCondition calldata _condition, bool _resetClaimEligibility)
290-
external
291-
onlyRole(DEFAULT_ADMIN_ROLE)
292-
{
293-
if (_resetClaimEligibility) {
294-
conditionId = keccak256(abi.encodePacked(msg.sender, block.number));
295-
}
296-
297-
ClaimCondition memory currentConditoin = claimCondition;
298-
299-
claimCondition = ClaimCondition({
300-
startTimestamp: block.timestamp,
301-
maxClaimableSupply: _condition.maxClaimableSupply,
302-
supplyClaimed: _resetClaimEligibility ? currentConditoin.supplyClaimed : _condition.supplyClaimed,
303-
quantityLimitPerTransaction: _condition.supplyClaimed,
304-
waitTimeInSecondsBetweenClaims: _condition.waitTimeInSecondsBetweenClaims,
305-
merkleRoot: _condition.merkleRoot,
306-
pricePerToken: _condition.pricePerToken,
307-
currency: _condition.currency
308-
});
309-
310-
emit ClaimConditionUpdated(_condition, _resetClaimEligibility);
311-
}
312-
313243
/*///////////////////////////////////////////////////////////////
314244
Internal functions
315245
//////////////////////////////////////////////////////////////*/
316246

247+
/// @dev Runs before every `claim` function call.
248+
function _beforeClaim(
249+
address,
250+
uint256 _quantity,
251+
address,
252+
uint256,
253+
AllowlistProof calldata,
254+
bytes memory
255+
) internal view override {
256+
require(_currentIndex + _quantity <= nextTokenIdToMint, "not enough minted tokens.");
257+
}
258+
317259
/// @dev Collects and distributes the primary sale value of NFTs being claimed.
318-
function collectPrice(
260+
function collectPriceOnClaim(
319261
uint256 _quantityToClaim,
320262
address _currency,
321263
uint256 _pricePerToken
322-
) internal {
264+
) internal override {
323265
if (_pricePerToken == 0) {
324266
return;
325267
}
@@ -345,6 +287,15 @@ contract SignatureDrop is
345287
);
346288
}
347289

290+
/// @dev Transfers the NFTs being claimed.
291+
function transferTokensOnClaim(
292+
address _to,
293+
uint256 _quantityBeingClaimed
294+
) internal override returns (uint256 startTokenId) {
295+
startTokenId = _currentIndex;
296+
_mint(_to, _quantityBeingClaimed);
297+
}
298+
348299
/// @dev Returns whether a given address is authorized to sign mint requests.
349300
function _isAuthorizedSigner(address _signer) internal view override returns (bool) {
350301
return hasRole(MINTER_ROLE, _signer);

contracts/feature/DropSinglePhase.sol

Lines changed: 76 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,45 @@ pragma solidity ^0.8.0;
33

44
import "./interface/IDropSinglePhase.sol";
55
import "../lib/MerkleProof.sol";
6+
import "./Context.sol";
67
import "@openzeppelin/contracts-upgradeable/utils/structs/BitMapsUpgradeable.sol";
78

8-
abstract contract DropSinglePhase is IDropSinglePhase {
9+
abstract contract DropSinglePhase is IDropSinglePhase, Context {
10+
911
using BitMapsUpgradeable for BitMapsUpgradeable.BitMap;
1012

11-
/// @dev The active conditions for claiming lazy minted tokens.
12-
ClaimCondition public claimCondition;
13+
/*///////////////////////////////////////////////////////////////
14+
State variables
15+
//////////////////////////////////////////////////////////////*/
1316

14-
mapping(bytes32 => mapping(address => uint256)) private lastClaimTimestamp;
15-
mapping(bytes32 => BitMapsUpgradeable.BitMap) private usedAllowlistSpot;
17+
/// @dev The active conditions for claiming tokens.
18+
ClaimCondition public claimCondition;
1619

1720
/// @dev The ID for the active claim condition.
1821
bytes32 private conditionId;
1922

20-
function _msgSender() internal virtual returns (address) {
21-
return msg.sender;
22-
}
23+
/*///////////////////////////////////////////////////////////////
24+
Mappings
25+
//////////////////////////////////////////////////////////////*/
2326

24-
function _beforeClaim(
25-
address _receiver,
26-
uint256 _quantity,
27-
address _currency,
28-
uint256 _pricePerToken,
29-
AllowlistProof calldata _allowlistProof,
30-
bytes memory _data
31-
) internal virtual;
27+
/**
28+
* @dev Map from an account and uid for a claim condition, to the last timestamp
29+
* at which the account claimed tokens under that claim condition.
30+
*/
31+
mapping(bytes32 => mapping(address => uint256)) private lastClaimTimestamp;
32+
33+
/**
34+
* @dev Map from a claim condition uid to whether an address in an allowlist
35+
* has already claimed tokens i.e. used their place in the allowlist.
36+
*/
37+
mapping(bytes32 => BitMapsUpgradeable.BitMap) private usedAllowlistSpot;
3238

33-
function _afterClaim(
34-
address _receiver,
35-
uint256 _quantity,
36-
address _currency,
37-
uint256 _pricePerToken,
38-
AllowlistProof calldata _allowlistProof,
39-
bytes memory _data
40-
) internal virtual;
4139

42-
/// @dev Lets an account claim NFTs.
40+
/*///////////////////////////////////////////////////////////////
41+
Drop logic
42+
//////////////////////////////////////////////////////////////*/
43+
44+
/// @dev Lets an account claim tokens.
4345
function claim(
4446
address _receiver,
4547
uint256 _quantity,
@@ -51,6 +53,7 @@ abstract contract DropSinglePhase is IDropSinglePhase {
5153
_beforeClaim(_receiver, _quantity, _currency, _pricePerToken, _allowlistProof, _data);
5254

5355
bytes32 activeConditionId = conditionId;
56+
5457
/**
5558
* We make allowlist checks (i.e. verifyClaimMerkleProof) before verifying the claim's general
5659
* validity (i.e. verifyClaim) because we give precedence to the check of allow list quantity
@@ -83,46 +86,40 @@ abstract contract DropSinglePhase is IDropSinglePhase {
8386
lastClaimTimestamp[activeConditionId][_msgSender()] = block.timestamp;
8487

8588
// If there's a price, collect price.
86-
collectPrice(_quantity, _currency, _pricePerToken);
89+
collectPriceOnClaim(_quantity, _currency, _pricePerToken);
8790

8891
// Mint the relevant NFTs to claimer.
89-
uint256 startTokenId = transferClaimedTokens(_receiver, _quantity);
92+
uint256 startTokenId = transferTokensOnClaim(_receiver, _quantity);
9093

9194
emit TokensClaimed(claimCondition, _msgSender(), _receiver, _quantity, startTokenId);
9295

9396
_afterClaim(_receiver, _quantity, _currency, _pricePerToken, _allowlistProof, _data);
9497
}
9598

96-
/// @dev Collects and distributes the primary sale value of NFTs being claimed.
97-
function collectPrice(
98-
uint256 _quantityToClaim,
99-
address _currency,
100-
uint256 _pricePerToken
101-
) internal virtual;
99+
/// @dev Lets a contract admin set claim conditions.
100+
function setClaimConditions(ClaimCondition calldata _condition, bool _resetClaimEligibility, bytes memory) external {
102101

103-
/// @dev Transfers the NFTs being claimed.
104-
function transferClaimedTokens(address _to, uint256 _quantityBeingClaimed)
105-
internal
106-
virtual
107-
returns (uint256 startTokenId);
102+
bytes32 targetConditionId = conditionId;
103+
uint256 supplyClaimedAlready = claimCondition.supplyClaimed;
108104

109-
function setClaimCondition(ClaimCondition calldata _condition, bool _resetClaimEligibility) external {
110105
if (_resetClaimEligibility) {
111-
conditionId = keccak256(abi.encodePacked(msg.sender, block.number));
106+
supplyClaimedAlready = 0;
107+
targetConditionId = keccak256(abi.encodePacked(msg.sender, block.number));
112108
}
113109

114-
ClaimCondition memory currentConditoin = claimCondition;
110+
require(supplyClaimedAlready <= _condition.maxClaimableSupply, "max supply claimed already");
115111

116112
claimCondition = ClaimCondition({
117113
startTimestamp: block.timestamp,
118114
maxClaimableSupply: _condition.maxClaimableSupply,
119-
supplyClaimed: _resetClaimEligibility ? currentConditoin.supplyClaimed : _condition.supplyClaimed,
115+
supplyClaimed: supplyClaimedAlready,
120116
quantityLimitPerTransaction: _condition.supplyClaimed,
121117
waitTimeInSecondsBetweenClaims: _condition.waitTimeInSecondsBetweenClaims,
122118
merkleRoot: _condition.merkleRoot,
123119
pricePerToken: _condition.pricePerToken,
124120
currency: _condition.currency
125121
});
122+
conditionId = targetConditionId;
126123

127124
emit ClaimConditionUpdated(_condition, _resetClaimEligibility);
128125
}
@@ -152,12 +149,6 @@ abstract contract DropSinglePhase is IDropSinglePhase {
152149
currentClaimPhase.supplyClaimed + _quantity <= currentClaimPhase.maxClaimableSupply,
153150
"exceed max claimable supply."
154151
);
155-
// require(nextTokenIdToClaim + _quantity <= nextTokenIdToMint, "not enough minted tokens.");
156-
// require(maxTotalSupply == 0 || nextTokenIdToClaim + _quantity <= maxTotalSupply, "exceed max total supply.");
157-
// require(
158-
// maxWalletClaimCount == 0 || walletClaimCount[_claimer] + _quantity <= maxWalletClaimCount,
159-
// "exceed claim limit"
160-
// );
161152

162153
uint256 timestampOfLastClaim = lastClaimTimestamp[conditionId][_claimer];
163154
require(
@@ -189,4 +180,41 @@ abstract contract DropSinglePhase is IDropSinglePhase {
189180
);
190181
}
191182
}
183+
184+
/*///////////////////////////////////////////////////////////////
185+
Virtual functions: to be implemented in derived contract
186+
//////////////////////////////////////////////////////////////*/
187+
188+
/// @dev Runs before every `claim` function call.
189+
function _beforeClaim(
190+
address _receiver,
191+
uint256 _quantity,
192+
address _currency,
193+
uint256 _pricePerToken,
194+
AllowlistProof calldata _allowlistProof,
195+
bytes memory _data
196+
) internal virtual {}
197+
198+
/// @dev Runs after every `claim` function call.
199+
function _afterClaim(
200+
address _receiver,
201+
uint256 _quantity,
202+
address _currency,
203+
uint256 _pricePerToken,
204+
AllowlistProof calldata _allowlistProof,
205+
bytes memory _data
206+
) internal virtual {}
207+
208+
/// @dev Collects and distributes the primary sale value of NFTs being claimed.
209+
function collectPriceOnClaim(
210+
uint256 _quantityToClaim,
211+
address _currency,
212+
uint256 _pricePerToken
213+
) internal virtual;
214+
215+
/// @dev Transfers the NFTs being claimed.
216+
function transferTokensOnClaim(
217+
address _to,
218+
uint256 _quantityBeingClaimed
219+
) internal virtual returns (uint256 startTokenId);
192220
}

0 commit comments

Comments
 (0)