import "@thirdweb-dev/contracts/extension/DelayedReveal.sol";

The DelayedReveal smart contract is an extension for any NFT contract. It lets you create batches of 'delayed-reveal' NFTs.

In order for ERC721Revealable or ERC1155Revealable extensions to be detected in the dashboard on your contract, the respective EIP (ERC721 or ERC1155 needs to be inherited.

View on GitHub


The DelayedReveal extension is an abstract contract, and expects you to implement the following functions by yourself:

revealexternalstring memoryReveals a batch of delayed reveal NFTs.

This is an example smart contract demonstrating how to inherit from this extension and override the functions to add (optional) custom functionality.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/base/ERC721LazyMint.sol";
import "@thirdweb-dev/contracts/extension/DelayedReveal.sol";
/// This is just an EXAMPLE contract that uses `DelayedReveal`.
contract MyContract is ERC721LazyMint, DelayedReveal {
using TWStrings for uint256;
string memory _name,
string memory _symbol,
address _royaltyRecipient,
uint128 _royaltyBps
) ERC721LazyMint(_name, _symbol, _royaltyRecipient, _royaltyBps) {}
* We override the `lazyMint` function, and use the `_data` parameter for storing encrypted metadata
* for 'delayed reveal' NFTs.
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(
(bytes, bytes32)
if (encryptedURI.length != 0 && provenanceHash != "") {
_setEncryptedData(nextTokenIdToLazyMint + _amount, _data);
return super.lazyMint(_amount, _baseURIForTokens, _data);
* We override `tokenURI` to return an appropriate URI for NFTs whose true metadata is encrypted.
function tokenURI(uint256 _tokenId)
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()));
* We only let the owner of the contract reveal the metadata for a batch of NFTs.
function reveal(uint256 _index, bytes calldata _key)
returns (string memory revealedURI)
require(msg.sender == owner(), "Not authorized");
uint256 batchId = getBatchIdAtIndex(_index);
revealedURI = getRevealURI(batchId, _key);
_setEncryptedData(batchId, "");
_setBaseURI(batchId, revealedURI);

Base Contracts Implementing This Extension

Full API Reference