Skip to main content

ERC721 Drop

import "@thirdweb-dev/contracts/base/ERC721Drop.sol";

The ERC721Drop base contract allows you to create an NFT Drop that other wallets can claim.

It implements the ERC721A standard with the Lazy Mint, Delayed Reveal and Drop extensions; allowing you to batch lazy-mint NFTs and allow other wallets to claim them under the criteria of claim conditions, with an optional delayed reveal.

Detected Extensions​

Once deployed, you can use the features made available by these extensions on the SDK and dashboard:

Click on each feature to learn more about what functions are available.

Usage​

Import the contract and inherit from it.

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "@thirdweb-dev/contracts/base/ERC721Drop.sol";

contract MyNFT is ERC721Drop {
constructor(
address _defaultAdmin,
string memory _name,
string memory _symbol,
address _royaltyRecipient,
uint128 _royaltyBps,
address _primarySaleRecipient
)
ERC721Drop(
_defaultAdmin,
_name,
_symbol,
_royaltyRecipient,
_royaltyBps,
_primarySaleRecipient
)
{}
}

Functions to Override​

The following functions have been implemented on this contract & are available to be overridden to add custom logic:

tokenURI
/**
* @notice Returns the metadata URI for an NFT.
* @dev See `BatchMintMetadata` for handling of metadata in this contract.
*
* @param _tokenId The tokenId of an NFT.
*/
function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
(uint256 batchId, ) = _getBatchId(_tokenId);
string memory batchUri = _getBaseURI(_tokenId);

if (isEncryptedBatch(batchId)) {
return string(abi.encodePacked(batchUri, "0"));
} else {
return string(abi.encodePacked(batchUri, _tokenId.toString()));
}
}
lazyMint
    /**
* @notice Lets an authorized address lazy mint a given amount of NFTs.
*
* @param _amount The number of NFTs to lazy mint.
* @param _baseURIForTokens The placeholder base URI for the 'n' number of NFTs being lazy minted, where the
* metadata for each of those NFTs is `${baseURIForTokens}/${tokenId}`.
* @param _data The encrypted base URI + provenance hash for the batch of NFTs being lazy minted.
* @return batchId A unique integer identifier for the batch of NFTs lazy minted together.
*/
function lazyMint(
uint256 _amount,
string calldata _baseURIForTokens,
bytes calldata _data
) public override returns (uint256 batchId) {
if (_data.length > 0) {
(bytes memory encryptedURI, bytes32 provenanceHash) = abi.decode(_data, (bytes, bytes32));
if (encryptedURI.length != 0 && provenanceHash != "") {
_setEncryptedData(nextTokenIdToLazyMint + _amount, _data);
}
}

return LazyMint.lazyMint(_amount, _baseURIForTokens, _data);
}
reveal
    /**
* @notice Lets an authorized address reveal a batch of delayed reveal NFTs.
*
* @param _index The ID for the batch of delayed-reveal NFTs to reveal.
* @param _key The key with which the base URI for the relevant batch of NFTs was encrypted.
*/
function reveal(uint256 _index, bytes calldata _key) public virtual override returns (string memory revealedURI) {
require(_canReveal(), "Not authorized");

uint256 batchId = getBatchIdAtIndex(_index);
revealedURI = getRevealURI(batchId, _key);

_setEncryptedData(batchId, "");
_setBaseURI(batchId, revealedURI);

emit TokenURIRevealed(_index, revealedURI);
}
burn
    /**
* @notice Lets an owner or approved operator burn the NFT of the given tokenId.
* @dev ERC721A's `_burn(uint256,bool)` internally checks for token approvals.
*
* @param _tokenId The tokenId of the NFT to burn.
*/
function burn(uint256 _tokenId) external virtual {
_burn(_tokenId, true);
}
_beforeClaim
/// @dev Runs before every `claim` function call.
function _beforeClaim(
address,
uint256 _quantity,
address,
uint256,
AllowlistProof calldata,
bytes memory
) internal view virtual override {
if (_currentIndex + _quantity > nextTokenIdToLazyMint) {
revert("Not enough minted tokens");
}
}
_collectPriceOnClaim
/// @dev Collects and distributes the primary sale value of NFTs being claimed.
function _collectPriceOnClaim(
address _primarySaleRecipient,
uint256 _quantityToClaim,
address _currency,
uint256 _pricePerToken
) internal virtual override {
if (_pricePerToken == 0) {
return;
}

uint256 totalPrice = _quantityToClaim * _pricePerToken;

if (_currency == CurrencyTransferLib.NATIVE_TOKEN) {
if (msg.value != totalPrice) {
revert("Must send total price");
}
}

address saleRecipient = _primarySaleRecipient == address(0) ? primarySaleRecipient() : _primarySaleRecipient;
CurrencyTransferLib.transferCurrency(_currency, msg.sender, saleRecipient, totalPrice);
}
_transferTokensOnClaim
  /// @dev Transfers the NFTs being claimed.
function _transferTokensOnClaim(address _to, uint256 _quantityBeingClaimed)
internal
virtual
override
returns (uint256 startTokenId)
{
startTokenId = _currentIndex;
_safeMint(_to, _quantityBeingClaimed);
}