Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/extensions/DECAPINATION.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/*
▓█████▄ ▓█████ ▄████▄ ▄▄▄ ██▓███ ██▓ ███▄ █ ▄▄▄ ▄▄▄█████▓ ██▓ ▒█████ ███▄ █
▒██▀ ██▌▓█ ▀ ▒██▀ ▀█ ▒████▄ ▓██░ ██▒▓██▒ ██ ▀█ █ ▒████▄ ▓ ██▒ ▓▒▓██▒▒██▒ ██▒ ██ ▀█ █
░██ █▌▒███ ▒▓█ ▄ ▒██ ▀█▄ ▓██░ ██▓▒▒██▒▓██ ▀█ ██▒▒██ ▀█▄ ▒ ▓██░ ▒░▒██▒▒██░ ██▒▓██ ▀█ ██▒
░▓█▄ ▌▒▓█ ▄ ▒▓▓▄ ▄██▒░██▄▄▄▄██ ▒██▄█▓▒ ▒░██░▓██▒ ▐▌██▒░██▄▄▄▄██░ ▓██▓ ░ ░██░▒██ ██░▓██▒ ▐▌██▒
░▒████▓ ░▒████▒▒ ▓███▀ ░ ▓█ ▓██▒▒██▒ ░ ░░██░▒██░ ▓██░ ▓█ ▓██▒ ▒██▒ ░ ░██░░ ████▓▒░▒██░ ▓██░
▒▒▓ ▒ ░░ ▒░ ░░ ░▒ ▒ ░ ▒▒ ▓▒█░▒▓▒░ ░ ░░▓ ░ ▒░ ▒ ▒ ▒▒ ▓▒█░ ▒ ░░ ░▓ ░ ▒░▒░▒░ ░ ▒░ ▒ ▒
░ ▒ ▒ ░ ░ ░ ░ ▒ ▒ ▒▒ ░░▒ ░ ▒ ░░ ░░ ░ ▒░ ▒ ▒▒ ░ ░ ▒ ░ ░ ▒ ▒░ ░ ░░ ░ ▒░
░ ░ ░ ░ ░ ░ ▒ ░░ ▒ ░ ░ ░ ░ ░ ▒ ░ ▒ ░░ ░ ░ ▒ ░ ░ ░
░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
░ ░
by decapination.eth and 0xdecapitator.eth
*/
import { ERC721SeaDrop, ERC721A, IERC721A } from "../ERC721SeaDrop.sol";
/**
* @title DECAPITATION
* @notice A ritualistic PFP collection where Dead Punks await liberation.
*
* @dev Built on ERC721SeaDrop with pausable transfers to create a
* controlled mint and reveal experience.
*
* == THE RITUAL ==
* Those who commit to the Ritual will receive a Dead Punk NFT. Your token
* will remain suspended between dimensions—owned but not yet free to roam
* the secondary markets.
*
* == THE SUSPENSION ==
* All transfers are bound by ancient forces (paused) to prevent bot sniping
* and forge community before the great liberation.
* - Transfers are PAUSED, not soulbound. You still own your NFT.
*
* == THE LIBERATION ==
* The spiritual leader (contract owner) will break the chains when the
* collection reaches mint-out OR when the public ritual expires—whichever
* comes first. At this moment, all Dead Punks will be set free into our
* bRAVE New World.
*
* == TRUST MODEL ==
* The spiritual leader holds the power to unpause and commits to liberating
* all Dead Punks immediately upon mint-out or ritual expiration.
*
* Welcome to the Ritual. Your Dead Punk awaits.
*/
contract DECAPINATION is ERC721SeaDrop {
/// @notice The sacred incantation of this ritual
string public constant RITUAL_INCANTATION = "LIBERATE THE DEAD PUNKS";
/// @notice Revert when transfers are paused.
error TransfersPaused();
/// @notice Emit an event when transfers are paused or unpaused.
event TransfersPausedChanged(bool paused);
/// @notice Boolean if transfers are paused.
bool public transfersPaused = true;
/**
* @notice Deploy the token contract with its name, symbol,
* and allowed SeaDrop addresses.
*/
constructor(
string memory name,
string memory symbol,
address[] memory allowedSeaDrop
) payable ERC721SeaDrop(name, symbol, allowedSeaDrop) {
emit TransfersPausedChanged(transfersPaused);
}
function updateTransfersPaused(bool paused) external onlyOwner {
transfersPaused = paused;
emit TransfersPausedChanged(paused);
}
function setApprovalForAll(
address operator,
bool approved
) public virtual override(ERC721A, IERC721A) {
if (transfersPaused) {
revert TransfersPaused();
}
super.setApprovalForAll(operator, approved);
}
function approve(
address to,
uint256 tokenId
) public virtual override(ERC721A, IERC721A) {
if (transfersPaused) {
revert TransfersPaused();
}
super.approve(to, tokenId);
}
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual override {
if (transfersPaused && from != address(0)) {
revert TransfersPaused();
}
super._beforeTokenTransfers(from, to, startTokenId, quantity);
}
}
"
},
"src/ERC721SeaDrop.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {
ERC721ContractMetadata,
ISeaDropTokenContractMetadata,
ERC721A,
IERC721A
} from "./ERC721ContractMetadata.sol";
import {
INonFungibleSeaDropToken
} from "./interfaces/INonFungibleSeaDropToken.sol";
import { ISeaDrop } from "./interfaces/ISeaDrop.sol";
import {
AllowListData,
PublicDrop,
TokenGatedDropStage,
SignedMintValidationParams
} from "./lib/SeaDropStructs.sol";
import {
ERC721SeaDropStructsErrorsAndEvents
} from "./lib/ERC721SeaDropStructsErrorsAndEvents.sol";
import { ReentrancyGuard } from "solmate/utils/ReentrancyGuard.sol";
import {
IERC165
} from "openzeppelin-contracts/utils/introspection/IERC165.sol";
/**
* @title ERC721SeaDrop
* @author James Wenzel (emo.eth)
* @author Ryan Ghods (ralxz.eth)
* @author Stephan Min (stephanm.eth)
* @author Michael Cohen (notmichael.eth)
* @custom:contributor Limit Break (@limitbreak)
* @notice ERC721SeaDrop is a token contract that contains methods
* to properly interact with SeaDrop.
* Implements Limit Break's Creator Token Standards transfer
* validation for royalty enforcement.
*/
contract ERC721SeaDrop is
ERC721ContractMetadata,
INonFungibleSeaDropToken,
ERC721SeaDropStructsErrorsAndEvents,
ReentrancyGuard
{
/// @notice Track the allowed SeaDrop addresses.
mapping(address => bool) internal _allowedSeaDrop;
/// @notice Track the enumerated allowed SeaDrop addresses.
address[] internal _enumeratedAllowedSeaDrop;
/**
* @dev Reverts if not an allowed SeaDrop contract.
* This function is inlined instead of being a modifier
* to save contract space from being inlined N times.
*
* @param seaDrop The SeaDrop address to check if allowed.
*/
function _onlyAllowedSeaDrop(address seaDrop) internal view {
if (_allowedSeaDrop[seaDrop] != true) {
revert OnlyAllowedSeaDrop();
}
}
/**
* @notice Deploy the token contract with its name, symbol,
* and allowed SeaDrop addresses.
*/
constructor(
string memory name,
string memory symbol,
address[] memory allowedSeaDrop
) payable ERC721ContractMetadata(name, symbol) {
// Put the length on the stack for more efficient access.
uint256 allowedSeaDropLength = allowedSeaDrop.length;
// Set the mapping for allowed SeaDrop contracts.
for (uint256 i = 0; i < allowedSeaDropLength; ) {
_allowedSeaDrop[allowedSeaDrop[i]] = true;
unchecked {
++i;
}
}
// Set the enumeration.
_enumeratedAllowedSeaDrop = allowedSeaDrop;
// Emit an event noting the contract deployment.
emit SeaDropTokenDeployed();
}
/**
* @notice Update the allowed SeaDrop contracts.
* Only the owner can use this function.
*
* @param allowedSeaDrop The allowed SeaDrop addresses.
*/
function updateAllowedSeaDrop(
address[] calldata allowedSeaDrop
) external virtual override onlyOwner {
_updateAllowedSeaDrop(allowedSeaDrop);
}
/**
* @notice Internal function to update the allowed SeaDrop contracts.
*
* @param allowedSeaDrop The allowed SeaDrop addresses.
*/
function _updateAllowedSeaDrop(address[] calldata allowedSeaDrop) internal {
// Put the length on the stack for more efficient access.
uint256 enumeratedAllowedSeaDropLength = _enumeratedAllowedSeaDrop
.length;
uint256 allowedSeaDropLength = allowedSeaDrop.length;
// Reset the old mapping.
for (uint256 i = 0; i < enumeratedAllowedSeaDropLength; ) {
_allowedSeaDrop[_enumeratedAllowedSeaDrop[i]] = false;
unchecked {
++i;
}
}
// Set the new mapping for allowed SeaDrop contracts.
for (uint256 i = 0; i < allowedSeaDropLength; ) {
_allowedSeaDrop[allowedSeaDrop[i]] = true;
unchecked {
++i;
}
}
// Set the enumeration.
_enumeratedAllowedSeaDrop = allowedSeaDrop;
// Emit an event for the update.
emit AllowedSeaDropUpdated(allowedSeaDrop);
}
/**
* @notice Burns `tokenId`. The caller must own `tokenId` or be an
* approved operator.
*
* @param tokenId The token id to burn.
*/
// solhint-disable-next-line comprehensive-interface
function burn(uint256 tokenId) external {
_burn(tokenId, true);
}
/**
* @dev Overrides the `_startTokenId` function from ERC721A
* to start at token id `1`.
*
* This is to avoid future possible problems since `0` is usually
* used to signal values that have not been set or have been removed.
*/
function _startTokenId() internal view virtual override returns (uint256) {
return 1;
}
/**
* @dev Overrides the `tokenURI()` function from ERC721A
* to return just the base URI if it is implied to not be a directory.
*
* This is to help with ERC721 contracts in which the same token URI
* is desired for each token, such as when the tokenURI is 'unrevealed'.
*/
function tokenURI(
uint256 tokenId
) public view virtual override(ERC721A, IERC721A) returns (string memory) {
if (!_exists(tokenId)) revert URIQueryForNonexistentToken();
string memory baseURI = _baseURI();
// Exit early if the baseURI is empty.
if (bytes(baseURI).length == 0) {
return "";
}
// Check if the last character in baseURI is a slash.
if (bytes(baseURI)[bytes(baseURI).length - 1] != bytes("/")[0]) {
return baseURI;
}
return string(abi.encodePacked(baseURI, _toString(tokenId)));
}
/**
* @notice Mint tokens, restricted to the SeaDrop contract.
*
* @dev NOTE: If a token registers itself with multiple SeaDrop
* contracts, the implementation of this function should guard
* against reentrancy. If the implementing token uses
* _safeMint(), or a feeRecipient with a malicious receive() hook
* is specified, the token or fee recipients may be able to execute
* another mint in the same transaction via a separate SeaDrop
* contract.
* This is dangerous if an implementing token does not correctly
* update the minterNumMinted and currentTotalSupply values before
* transferring minted tokens, as SeaDrop references these values
* to enforce token limits on a per-wallet and per-stage basis.
*
* ERC721A tracks these values automatically, but this note and
* nonReentrant modifier are left here to encourage best-practices
* when referencing this contract.
*
* @param minter The address to mint to.
* @param quantity The number of tokens to mint.
*/
function mintSeaDrop(
address minter,
uint256 quantity
) external virtual override nonReentrant {
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(msg.sender);
// Extra safety check to ensure the max supply is not exceeded.
if (_totalMinted() + quantity > maxSupply()) {
revert MintQuantityExceedsMaxSupply(
_totalMinted() + quantity,
maxSupply()
);
}
// Mint the quantity of tokens to the minter.
_safeMint(minter, quantity);
}
/**
* @notice Update the public drop data for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param publicDrop The public drop data.
*/
function updatePublicDrop(
address seaDropImpl,
PublicDrop calldata publicDrop
) external virtual override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the public drop data on SeaDrop.
ISeaDrop(seaDropImpl).updatePublicDrop(publicDrop);
}
/**
* @notice Update the allow list data for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param allowListData The allow list data.
*/
function updateAllowList(
address seaDropImpl,
AllowListData calldata allowListData
) external virtual override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the allow list on SeaDrop.
ISeaDrop(seaDropImpl).updateAllowList(allowListData);
}
/**
* @notice Update the token gated drop stage data for this nft contract
* on SeaDrop.
* Only the owner can use this function.
*
* Note: If two INonFungibleSeaDropToken tokens are doing
* simultaneous token gated drop promotions for each other,
* they can be minted by the same actor until
* `maxTokenSupplyForStage` is reached. Please ensure the
* `allowedNftToken` is not running an active drop during the
* `dropStage` time period.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param allowedNftToken The allowed nft token.
* @param dropStage The token gated drop stage data.
*/
function updateTokenGatedDrop(
address seaDropImpl,
address allowedNftToken,
TokenGatedDropStage calldata dropStage
) external virtual override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the token gated drop stage.
ISeaDrop(seaDropImpl).updateTokenGatedDrop(allowedNftToken, dropStage);
}
/**
* @notice Update the drop URI for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param dropURI The new drop URI.
*/
function updateDropURI(
address seaDropImpl,
string calldata dropURI
) external virtual override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the drop URI.
ISeaDrop(seaDropImpl).updateDropURI(dropURI);
}
/**
* @notice Update the creator payout address for this nft contract on
* SeaDrop.
* Only the owner can set the creator payout address.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param payoutAddress The new payout address.
*/
function updateCreatorPayoutAddress(
address seaDropImpl,
address payoutAddress
) external {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the creator payout address.
ISeaDrop(seaDropImpl).updateCreatorPayoutAddress(payoutAddress);
}
/**
* @notice Update the allowed fee recipient for this nft contract
* on SeaDrop.
* Only the owner can set the allowed fee recipient.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param feeRecipient The new fee recipient.
* @param allowed If the fee recipient is allowed.
*/
function updateAllowedFeeRecipient(
address seaDropImpl,
address feeRecipient,
bool allowed
) external virtual {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the allowed fee recipient.
ISeaDrop(seaDropImpl).updateAllowedFeeRecipient(feeRecipient, allowed);
}
/**
* @notice Update the server-side signers for this nft contract
* on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param signer The signer to update.
* @param signedMintValidationParams Minimum and maximum parameters to
* enforce for signed mints.
*/
function updateSignedMintValidationParams(
address seaDropImpl,
address signer,
SignedMintValidationParams memory signedMintValidationParams
) external virtual override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the signer.
ISeaDrop(seaDropImpl).updateSignedMintValidationParams(
signer,
signedMintValidationParams
);
}
/**
* @notice Update the allowed payers for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param payer The payer to update.
* @param allowed Whether the payer is allowed.
*/
function updatePayer(
address seaDropImpl,
address payer,
bool allowed
) external virtual override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the SeaDrop is allowed.
_onlyAllowedSeaDrop(seaDropImpl);
// Update the payer.
ISeaDrop(seaDropImpl).updatePayer(payer, allowed);
}
/**
* @notice Returns a set of mint stats for the address.
* This assists SeaDrop in enforcing maxSupply,
* maxTotalMintableByWallet, and maxTokenSupplyForStage checks.
*
* @dev NOTE: Implementing contracts should always update these numbers
* before transferring any tokens with _safeMint() to mitigate
* consequences of malicious onERC721Received() hooks.
*
* @param minter The minter address.
*/
function getMintStats(
address minter
)
external
view
override
returns (
uint256 minterNumMinted,
uint256 currentTotalSupply,
uint256 maxSupply
)
{
minterNumMinted = _numberMinted(minter);
currentTotalSupply = _totalMinted();
maxSupply = _maxSupply;
}
/**
* @notice Returns whether the interface is supported.
*
* @param interfaceId The interface id to check against.
*/
function supportsInterface(
bytes4 interfaceId
)
public
view
virtual
override(IERC165, ERC721ContractMetadata)
returns (bool)
{
return
interfaceId == type(INonFungibleSeaDropToken).interfaceId ||
interfaceId == type(ISeaDropTokenContractMetadata).interfaceId ||
// ERC721ContractMetadata returns supportsInterface true for
// EIP-2981
// ERC721A returns supportsInterface true for
// ERC165, ERC721, ERC721Metadata
super.supportsInterface(interfaceId);
}
/**
* @notice Configure multiple properties at a time.
*
* Note: The individual configure methods should be used
* to unset or reset any properties to zero, as this method
* will ignore zero-value properties in the config struct.
*
* @param config The configuration struct.
*/
function multiConfigure(
MultiConfigureStruct calldata config
) external onlyOwner {
if (config.maxSupply > 0) {
this.setMaxSupply(config.maxSupply);
}
if (bytes(config.baseURI).length != 0) {
this.setBaseURI(config.baseURI);
}
if (bytes(config.contractURI).length != 0) {
this.setContractURI(config.contractURI);
}
if (
_cast(config.publicDrop.startTime != 0) |
_cast(config.publicDrop.endTime != 0) ==
1
) {
this.updatePublicDrop(config.seaDropImpl, config.publicDrop);
}
if (bytes(config.dropURI).length != 0) {
this.updateDropURI(config.seaDropImpl, config.dropURI);
}
if (config.allowListData.merkleRoot != bytes32(0)) {
this.updateAllowList(config.seaDropImpl, config.allowListData);
}
if (config.creatorPayoutAddress != address(0)) {
this.updateCreatorPayoutAddress(
config.seaDropImpl,
config.creatorPayoutAddress
);
}
if (config.provenanceHash != bytes32(0)) {
this.setProvenanceHash(config.provenanceHash);
}
if (config.allowedFeeRecipients.length > 0) {
for (uint256 i = 0; i < config.allowedFeeRecipients.length; ) {
this.updateAllowedFeeRecipient(
config.seaDropImpl,
config.allowedFeeRecipients[i],
true
);
unchecked {
++i;
}
}
}
if (config.disallowedFeeRecipients.length > 0) {
for (uint256 i = 0; i < config.disallowedFeeRecipients.length; ) {
this.updateAllowedFeeRecipient(
config.seaDropImpl,
config.disallowedFeeRecipients[i],
false
);
unchecked {
++i;
}
}
}
if (config.allowedPayers.length > 0) {
for (uint256 i = 0; i < config.allowedPayers.length; ) {
this.updatePayer(
config.seaDropImpl,
config.allowedPayers[i],
true
);
unchecked {
++i;
}
}
}
if (config.disallowedPayers.length > 0) {
for (uint256 i = 0; i < config.disallowedPayers.length; ) {
this.updatePayer(
config.seaDropImpl,
config.disallowedPayers[i],
false
);
unchecked {
++i;
}
}
}
if (config.tokenGatedDropStages.length > 0) {
if (
config.tokenGatedDropStages.length !=
config.tokenGatedAllowedNftTokens.length
) {
revert TokenGatedMismatch();
}
for (uint256 i = 0; i < config.tokenGatedDropStages.length; ) {
this.updateTokenGatedDrop(
config.seaDropImpl,
config.tokenGatedAllowedNftTokens[i],
config.tokenGatedDropStages[i]
);
unchecked {
++i;
}
}
}
if (config.disallowedTokenGatedAllowedNftTokens.length > 0) {
for (
uint256 i = 0;
i < config.disallowedTokenGatedAllowedNftTokens.length;
) {
TokenGatedDropStage memory emptyStage;
this.updateTokenGatedDrop(
config.seaDropImpl,
config.disallowedTokenGatedAllowedNftTokens[i],
emptyStage
);
unchecked {
++i;
}
}
}
if (config.signedMintValidationParams.length > 0) {
if (
config.signedMintValidationParams.length !=
config.signers.length
) {
revert SignersMismatch();
}
for (
uint256 i = 0;
i < config.signedMintValidationParams.length;
) {
this.updateSignedMintValidationParams(
config.seaDropImpl,
config.signers[i],
config.signedMintValidationParams[i]
);
unchecked {
++i;
}
}
}
if (config.disallowedSigners.length > 0) {
for (uint256 i = 0; i < config.disallowedSigners.length; ) {
SignedMintValidationParams memory emptyParams;
this.updateSignedMintValidationParams(
config.seaDropImpl,
config.disallowedSigners[i],
emptyParams
);
unchecked {
++i;
}
}
}
}
}
"
},
"src/ERC721ContractMetadata.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {
ISeaDropTokenContractMetadata
} from "./interfaces/ISeaDropTokenContractMetadata.sol";
import { ERC721A } from "ERC721A/ERC721A.sol";
import {
ERC721AConduitPreapproved,
ERC721A,
IERC721A
} from "./lib/ERC721AConduitPreapproved.sol";
import { ERC721TransferValidator } from "./lib/ERC721TransferValidator.sol";
import {
ICreatorToken,
ILegacyCreatorToken
} from "./interfaces/ICreatorToken.sol";
import { ITransferValidator721 } from "./interfaces/ITransferValidator.sol";
import { TwoStepOwnable } from "utility-contracts/TwoStepOwnable.sol";
import { IERC2981 } from "openzeppelin-contracts/interfaces/IERC2981.sol";
import {
IERC165
} from "openzeppelin-contracts/utils/introspection/IERC165.sol";
/**
* @title ERC721ContractMetadata
* @author James Wenzel (emo.eth)
* @author Ryan Ghods (ralxz.eth)
* @author Stephan Min (stephanm.eth)
* @notice ERC721ContractMetadata is a token contract that extends ERC721A
* with additional metadata and ownership capabilities.
*/
contract ERC721ContractMetadata is
ERC721AConduitPreapproved,
ERC721TransferValidator,
TwoStepOwnable,
ISeaDropTokenContractMetadata
{
/// @notice Track the max supply.
uint256 _maxSupply;
/// @notice Track the base URI for token metadata.
string _tokenBaseURI;
/// @notice Track the contract URI for contract metadata.
string _contractURI;
/// @notice Track the provenance hash for guaranteeing metadata order
/// for random reveals.
bytes32 _provenanceHash;
/// @notice Track the royalty info: address to receive royalties, and
/// royalty basis points.
RoyaltyInfo _royaltyInfo;
/**
* @dev Reverts if the sender is not the owner or the contract itself.
* This function is inlined instead of being a modifier
* to save contract space from being inlined N times.
*/
function _onlyOwnerOrSelf() internal view {
if (
_cast(msg.sender == owner()) | _cast(msg.sender == address(this)) ==
0
) {
revert OnlyOwner();
}
}
/**
* @notice Deploy the token contract with its name and symbol.
*/
constructor(
string memory name,
string memory symbol
) payable ERC721AConduitPreapproved(name, symbol) {}
/**
* @notice Sets the base URI for the token metadata and emits an event.
*
* @param newBaseURI The new base URI to set.
*/
function setBaseURI(string calldata newBaseURI) external override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Set the new base URI.
_tokenBaseURI = newBaseURI;
// Emit an event with the update.
if (totalSupply() != 0) {
emit BatchMetadataUpdate(1, _nextTokenId() - 1);
}
}
/**
* @notice Sets the contract URI for contract metadata.
*
* @param newContractURI The new contract URI.
*/
function setContractURI(string calldata newContractURI) external override {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Set the new contract URI.
_contractURI = newContractURI;
// Emit an event with the update.
emit ContractURIUpdated(newContractURI);
}
/**
* @notice Emit an event notifying metadata updates for
* a range of token ids, according to EIP-4906.
*
* @param fromTokenId The start token id.
* @param toTokenId The end token id.
*/
function emitBatchMetadataUpdate(
uint256 fromTokenId,
uint256 toTokenId
) external {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Emit an event with the update.
emit BatchMetadataUpdate(fromTokenId, toTokenId);
}
/**
* @notice Sets the max token supply and emits an event.
*
* @param newMaxSupply The new max supply to set.
*/
function setMaxSupply(uint256 newMaxSupply) external {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Ensure the max supply does not exceed the maximum value of uint64.
if (newMaxSupply > 2 ** 64 - 1) {
revert CannotExceedMaxSupplyOfUint64(newMaxSupply);
}
// Ensure the max supply does not exceed the total minted.
if (newMaxSupply < _totalMinted()) {
revert NewMaxSupplyCannotBeLessThenTotalMinted(
newMaxSupply,
_totalMinted()
);
}
// Set the new max supply.
_maxSupply = newMaxSupply;
// Emit an event with the update.
emit MaxSupplyUpdated(newMaxSupply);
}
/**
* @notice Sets the provenance hash and emits an event.
*
* The provenance hash is used for random reveals, which
* is a hash of the ordered metadata to show it has not been
* modified after mint started.
*
* This function will revert after the first item has been minted.
*
* @param newProvenanceHash The new provenance hash to set.
*/
function setProvenanceHash(bytes32 newProvenanceHash) external {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Revert if any items have been minted.
if (_totalMinted() > 0) {
revert ProvenanceHashCannotBeSetAfterMintStarted();
}
// Keep track of the old provenance hash for emitting with the event.
bytes32 oldProvenanceHash = _provenanceHash;
// Set the new provenance hash.
_provenanceHash = newProvenanceHash;
// Emit an event with the update.
emit ProvenanceHashUpdated(oldProvenanceHash, newProvenanceHash);
}
/**
* @notice Sets the address and basis points for royalties.
*
* @param newInfo The struct to configure royalties.
*/
function setRoyaltyInfo(RoyaltyInfo calldata newInfo) external {
// Ensure the sender is only the owner or contract itself.
_onlyOwnerOrSelf();
// Revert if the new royalty address is the zero address.
if (newInfo.royaltyAddress == address(0)) {
revert RoyaltyAddressCannotBeZeroAddress();
}
// Revert if the new basis points is greater than 10_000.
if (newInfo.royaltyBps > 10_000) {
revert InvalidRoyaltyBasisPoints(newInfo.royaltyBps);
}
// Set the new royalty info.
_royaltyInfo = newInfo;
// Emit an event with the updated params.
emit RoyaltyInfoUpdated(newInfo.royaltyAddress, newInfo.royaltyBps);
}
/**
* @notice Returns the base URI for token metadata.
*/
function baseURI() external view override returns (string memory) {
return _baseURI();
}
/**
* @notice Returns the base URI for the contract, which ERC721A uses
* to return tokenURI.
*/
function _baseURI() internal view virtual override returns (string memory) {
return _tokenBaseURI;
}
/**
* @notice Returns the contract URI for contract metadata.
*/
function contractURI() external view override returns (string memory) {
return _contractURI;
}
/**
* @notice Returns the max token supply.
*/
function maxSupply() public view returns (uint256) {
return _maxSupply;
}
/**
* @notice Returns the provenance hash.
* The provenance hash is used for random reveals, which
* is a hash of the ordered metadata to show it is unmodified
* after mint has started.
*/
function provenanceHash() external view override returns (bytes32) {
return _provenanceHash;
}
/**
* @notice Returns the address that receives royalties.
*/
function royaltyAddress() external view returns (address) {
return _royaltyInfo.royaltyAddress;
}
/**
* @notice Returns the royalty basis points out of 10_000.
*/
function royaltyBasisPoints() external view returns (uint256) {
return _royaltyInfo.royaltyBps;
}
/**
* @notice Called with the sale price to determine how much royalty
* is owed and to whom.
*
* @ param _tokenId The NFT asset queried for royalty information.
* @param _salePrice The sale price of the NFT asset specified by
* _tokenId.
*
* @return receiver Address of who should be sent the royalty payment.
* @return royaltyAmount The royalty payment amount for _salePrice.
*/
function royaltyInfo(
uint256,
/* _tokenId */
uint256 _salePrice
) external view returns (address receiver, uint256 royaltyAmount) {
// Put the royalty info on the stack for more efficient access.
RoyaltyInfo storage info = _royaltyInfo;
// Set the royalty amount to the sale price times the royalty basis
// points divided by 10_000.
royaltyAmount = (_salePrice * info.royaltyBps) / 10_000;
// Set the receiver of the royalty.
receiver = info.royaltyAddress;
}
/**
* @notice Returns the transfer validation function used.
*/
function getTransferValidationFunction()
external
pure
returns (bytes4 functionSignature, bool isViewFunction)
{
functionSignature = ITransferValidator721.validateTransfer.selector;
isViewFunction = false;
}
/**
* @notice Set the transfer validator. Only callable by the token owner.
*/
function setTransferValidator(address newValidator) external onlyOwner {
// Set the new transfer validator.
_setTransferValidator(newValidator);
}
/**
* @dev Hook that is called before any token transfer.
* This includes minting and burning.
*/
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 /* quantity */
) internal virtual override {
if (from != address(0) && to != address(0)) {
// Call the transfer validator if one is set.
address transferValidator = _transferValidator;
if (transferValidator != address(0)) {
ITransferValidator721(transferValidator).validateTransfer(
msg.sender,
from,
to,
startTokenId
);
}
}
}
/**
* @notice Returns whether the interface is supported.
*
* @param interfaceId The interface id to check against.
*/
function supportsInterface(
bytes4 interfaceId
) public view virtual override(IERC165, ERC721A, IERC721A) returns (bool) {
return
interfaceId == type(IERC2981).interfaceId ||
interfaceId == type(ICreatorToken).interfaceId ||
interfaceId == type(ILegacyCreatorToken).interfaceId ||
interfaceId == 0x49064906 || // ERC-4906
super.supportsInterface(interfaceId);
}
/**
* @dev Internal pure function to cast a `bool` value to a `uint256` value.
*
* @param b The `bool` value to cast.
*
* @return u The `uint256` value.
*/
function _cast(bool b) internal pure returns (uint256 u) {
assembly {
u := b
}
}
}
"
},
"src/interfaces/INonFungibleSeaDropToken.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {
ISeaDropTokenContractMetadata
} from "./ISeaDropTokenContractMetadata.sol";
import {
AllowListData,
PublicDrop,
TokenGatedDropStage,
SignedMintValidationParams
} from "../lib/SeaDropStructs.sol";
interface INonFungibleSeaDropToken is ISeaDropTokenContractMetadata {
/**
* @dev Revert with an error if a contract is not an allowed
* SeaDrop address.
*/
error OnlyAllowedSeaDrop();
/**
* @dev Emit an event when allowed SeaDrop contracts are updated.
*/
event AllowedSeaDropUpdated(address[] allowedSeaDrop);
/**
* @notice Update the allowed SeaDrop contracts.
* Only the owner can use this function.
*
* @param allowedSeaDrop The allowed SeaDrop addresses.
*/
function updateAllowedSeaDrop(address[] calldata allowedSeaDrop) external;
/**
* @notice Mint tokens, restricted to the SeaDrop contract.
*
* @dev NOTE: If a token registers itself with multiple SeaDrop
* contracts, the implementation of this function should guard
* against reentrancy. If the implementing token uses
* _safeMint(), or a feeRecipient with a malicious receive() hook
* is specified, the token or fee recipients may be able to execute
* another mint in the same transaction via a separate SeaDrop
* contract.
* This is dangerous if an implementing token does not correctly
* update the minterNumMinted and currentTotalSupply values before
* transferring minted tokens, as SeaDrop references these values
* to enforce token limits on a per-wallet and per-stage basis.
*
* @param minter The address to mint to.
* @param quantity The number of tokens to mint.
*/
function mintSeaDrop(address minter, uint256 quantity) external;
/**
* @notice Returns a set of mint stats for the address.
* This assists SeaDrop in enforcing maxSupply,
* maxTotalMintableByWallet, and maxTokenSupplyForStage checks.
*
* @dev NOTE: Implementing contracts should always update these numbers
* before transferring any tokens with _safeMint() to mitigate
* consequences of malicious onERC721Received() hooks.
*
* @param minter The minter address.
*/
function getMintStats(address minter)
external
view
returns (
uint256 minterNumMinted,
uint256 currentTotalSupply,
uint256 maxSupply
);
/**
* @notice Update the public drop data for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param publicDrop The public drop data.
*/
function updatePublicDrop(
address seaDropImpl,
PublicDrop calldata publicDrop
) external;
/**
* @notice Update the allow list data for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param allowListData The allow list data.
*/
function updateAllowList(
address seaDropImpl,
AllowListData calldata allowListData
) external;
/**
* @notice Update the token gated drop stage data for this nft contract
* on SeaDrop.
* Only the owner can use this function.
*
* Note: If two INonFungibleSeaDropToken tokens are doing
* simultaneous token gated drop promotions for each other,
* they can be minted by the same actor until
* `maxTokenSupplyForStage` is reached. Please ensure the
* `allowedNftToken` is not running an active drop during the
* `dropStage` time period.
*
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param allowedNftToken The allowed nft token.
* @param dropStage The token gated drop stage data.
*/
function updateTokenGatedDrop(
address seaDropImpl,
address allowedNftToken,
TokenGatedDropStage calldata dropStage
) external;
/**
* @notice Update the drop URI for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param dropURI The new drop URI.
*/
function updateDropURI(address seaDropImpl, string calldata dropURI)
external;
/**
* @notice Update the creator payout address for this nft contract on
* SeaDrop.
* Only the owner can set the creator payout address.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param payoutAddress The new payout address.
*/
function updateCreatorPayoutAddress(
address seaDropImpl,
address payoutAddress
) external;
/**
* @notice Update the allowed fee recipient for this nft contract
* on SeaDrop.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param feeRecipient The new fee recipient.
*/
function updateAllowedFeeRecipient(
address seaDropImpl,
address feeRecipient,
bool allowed
) external;
/**
* @notice Update the server-side signers for this nft contract
* on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param signer The signer to update.
* @param signedMintValidationParams Minimum and maximum parameters
* to enforce for signed mints.
*/
function updateSignedMintValidationParams(
address seaDropImpl,
address signer,
SignedMintValidationParams memory signedMintValidationParams
) external;
/**
* @notice Update the allowed payers for this nft contract on SeaDrop.
* Only the owner can use this function.
*
* @param seaDropImpl The allowed SeaDrop contract.
* @param payer The payer to update.
* @param allowed Whether the payer is allowed.
*/
function updatePayer(
address seaDropImpl,
address payer,
bool allowed
) external;
}
"
},
"src/interfaces/ISeaDrop.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {
AllowListData,
MintParams,
PublicDrop,
TokenGatedDropStage,
TokenGatedMintParams,
SignedMintValidationParams
} from "../lib/SeaDropStructs.sol";
import { SeaDropErrorsAndEvents } from "../lib/SeaDropErrorsAndEvents.sol";
interface ISeaDrop is SeaDropErrorsAndEvents {
/**
* @notice Mint a public drop.
*
* @param nftContract The nft contract to mint.
* @param feeRecipient The fee recipient.
* @param minterIfNotPayer The mint recipient if different than the payer.
* @param quantity The number of tokens to mint.
*/
function mintPublic(
address nftContract,
address feeRecipient,
address minterIfNotPayer,
uint256 quantity
) external payable;
/**
* @notice Mint from an allow list.
*
* @param nftContract The nft contract to mint.
* @param feeRecipient The fee recipient.
* @param minterIfNotPayer The mint recipient if different than the payer.
* @param quantity The number of tokens to mint.
* @param mintParams The mint parameters.
* @param proof The proof for the leaf of the allow list.
*/
function mintAllowList(
address nftContract,
address feeRecipient,
address minterIfNotPayer,
uint256 quantity,
MintParams calldata mintParams,
bytes32[] calldata proof
) external payable;
/**
* @notice Mint with a server-side signature.
* Note that a signature can only be used once.
*
* @param nftContract The nft contract to mint.
* @param feeRecipient The fee recipient.
* @param minterIfNotPayer The mint recipient if different than the payer.
* @param quantity The number of tokens to mint.
* @param mintParams The mint parameters.
* @param salt The sale for the signed mint.
* @param signature The server-side signature, must be an allowed
* signer.
*/
function mintSigned(
address nftContract,
address feeRecipient,
address minterIfNotPayer,
uint256 quantity,
MintParams calldata mintParams,
uint256 salt,
bytes calldata signature
) external payable;
/**
* @notice Mint as an allowed token holder.
* This will mark the token id as redeemed and will revert if the
* same token id is attempted to be redeemed twice.
*
* @param nftContract The nft contract to mint.
* @param feeRecipient The fee recipient.
* @param minterIfNotPayer The mint recipient if different than the payer.
* @param mintParams The token gated mint params.
*/
function mintAllowedTokenHolder(
address nftContract,
address feeRecipient,
address minterIfNotPayer,
TokenGatedMintParams calldata mintParams
) external payable;
/**
* @notice Emits an event to notify update of the drop URI.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* @param dropURI The new drop URI.
*/
function updateDropURI(string calldata dropURI) external;
/**
* @notice Updates the public drop data for the nft contract
* and emits an event.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* @param publicDrop The public drop data.
*/
function updatePublicDrop(PublicDrop calldata publicDrop) external;
/**
* @notice Updates the allow list merkle root for the nft contract
* and emits an event.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* @param allowListData The allow list data.
*/
function updateAllowList(AllowListData calldata allowListData) external;
/**
* @notice Updates the token gated drop stage for the nft contract
* and emits an event.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* Note: If two INonFungibleSeaDropToken tokens are doing
* simultaneous token gated drop promotions for each other,
* they can be minted by the same actor until
* `maxTokenSupplyForStage` is reached. Please ensure the
* `allowedNftToken` is not running an active drop during
* the `dropStage` time period.
*
* @param allowedNftToken The token gated nft token.
* @param dropStage The token gated drop stage data.
*/
function updateTokenGatedDrop(
address allowedNftToken,
TokenGatedDropStage calldata dropStage
) external;
/**
* @notice Updates the creator payout address and emits an event.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* @param payoutAddress The creator payout address.
*/
function updateCreatorPayoutAddress(address payoutAddress) external;
/**
* @notice Updates the allowed fee recipient and emits an event.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* @param feeRecipient The fee recipient.
* @param allowed If the fee recipient is allowed.
*/
function updateAllowedFeeRecipient(address feeRecipient, bool allowed)
external;
/**
* @notice Updates the allowed server-side signers and emits an event.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* @param signer The signer to update.
* @param signedMintValidationParams Minimum and maximum parameters
* to enforce for signed mints.
*/
function updateSignedMintValidationParams(
address signer,
SignedMintValidationParams calldata signedMintValidationParams
) external;
/**
* @notice Updates the allowed payer and emits an event.
*
* This method assume msg.sender is an nft contract and its
* ERC165 interface id matches INonFungibleSeaDropToken.
*
* Note: Be sure only authorized users can call this from
* token contracts that implement INonFungibleSeaDropToken.
*
* @param payer The payer to add or remove.
* @param allowed Whether to add or remove the payer.
*/
function updatePayer(address payer, bool allowed) external;
/**
* @notice Returns the public drop data for the nft contract.
*
* @param nftContract The nft contract.
*/
function getPublicDrop(address nftContract)
external
view
returns (PublicDrop memory);
/**
* @notice Returns the creator payout address for the nft contract.
*
* @param nftContract The nft contract.
*/
function getCreatorPayoutAddress(address nftContract)
external
view
returns (address);
/**
* @notice Returns the allow list merkle root for the nft contract.
*
* @param nftContract The nft contract.
*/
function getAllowListMerkleRoot(address nftContract)
external
view
returns (bytes32);
/**
* @notice Returns if the specified fee recipient is allowed
* for the nft contract.
*
* @param nftContract The nft contract.
* @param feeRecipient The fee recipient.
*/
function getFeeRecipientIsAllowed(address nftContract, address feeRecipient)
external
view
returns (bool);
/**
* @notice Returns an enumeration of allowed fee recipients for an
* nft contract when fee recipients are enforced
*
* @param nftContract The nft contract.
*/
function getAllowedFeeRecipients(address nftContract)
external
view
returns (address[] memory);
/**
* @notice Returns the server-side signers for the nft contract.
*
* @param nftContract The nft contract.
*/
function getSigners(address nftContract)
external
view
returns (address[] memory);
/**
* @notice Returns the struct of SignedMintValidationParams for a signer.
*
* @param nftContract The nft contract.
* @param signer The signer.
*/
function getSignedMintValidationParams(address nftContract, address signer)
external
view
returns (SignedMintValidationParams memory);
/**
* @notice Returns the payers for the nft contract.
*
* @param nftContract The nft contract.
*/
function getPayers(address nftContract)
external
view
returns (address[] memory);
/**
* @notice Returns if the specified payer is allowed
* for the nft contract.
*
* @param nftContract The nft contract.
* @param payer The payer.
*/
function getPayerIsAllowed(address nftContract, address payer)
external
view
returns (bool);
/**
* @notice Returns the allowed token gated drop tokens for the nft contract.
*
* @param nftContract The nft contract.
*/
function getTokenGatedAllowedTokens(address nftContract)
external
view
returns (address[] memory);
/**
* @notice Returns the token gated drop data for the nft contract
* and token gated nft.
*
* @param nftContract The nft contract.
* @param allowedNftToken The token gated nft token.
*/
function getTokenGatedDrop(address nftContract, address allowedNftToken)
external
view
returns (TokenGatedDropStage memory);
/**
* @notice Returns whether the token id for a token gated drop has been
* redeemed.
*
* @param nftContract The nft contract.
* @param allowedNftToken The token gated nft token.
* @param allowedNftTokenId The token gated nft token id to check.
*/
function getAllowedNftTokenIdIsRedeemed(
address nftContract,
address allowedNftToken,
uint256 allowedNftTokenId
) external view returns (bool);
}
"
},
"src/lib/SeaDropStructs.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/**
* @notice A struct defining public drop data.
* Designed to fit efficiently in one storage slot.
*
* @param mintPrice The mint price per token. (Up to 1.2m
* of native token, e.g. ETH, MATIC)
* @param startTime The start time, ensure this is not zero.
* @param endTIme The end time, ensure this is not zero.
* @param maxTotalMintableByWallet Maximum total number of mints a user is
* allowed. (The limit for this field is
* 2^16 - 1)
* @param feeBps Fee out of 10_000 basis points to be
* collected.
* @param restrictFeeRecipients If false, allow any fee recipient;
* if true, check fee recipient is allowed.
*/
struct PublicDrop {
uint80 mintPrice; // 80/256 bits
uint48 startTime; // 128/256 bits
uint48 endTime; // 176/256 bits
uint16 maxTotalMintableByWallet; // 224/256 bits
uint16 feeBps; // 240/256 bits
bool restrictFeeRecipients; // 248/256 bits
}
/**
* @notice A struct defining token gated drop stage data.
* Designed to fit efficiently in one storage slot.
*
* @param mintPrice The mint price per token. (Up to 1.2m
* of native token, e.g.: ETH, MATIC)
* @param maxTotalMintableByWallet Maximum total number of mints a user is
* allowed. (The limit for this field is
* 2^16 - 1)
* @param startTime The start time, ensure this is not zero.
* @param endTime The end time, ensure this is not zero.
* @param dropStageIndex The drop stage index to emit with the event
* for analytical purposes. This should be
* non-zero since the public mint emits
* with index zero.
* @param maxTokenSupplyForStage The limit of token supply this stage can
* mint within. (The limit for this field is
* 2^16 - 1)
* @param feeBps Fee out of 10_000 basis points to be
* collected.
* @param restrictFeeRecipients If false, allow any fee recipient;
* if true, check fee recipient is allowed.
*/
struct TokenGatedDropStage {
uint80 mintPrice; // 80/256 bits
uint16 maxTotalMintableByWallet; // 96/256 bits
uint48 startTime; // 144/256 bits
uint48 endTime; // 192/256 bits
uint8 dropStageIndex; // non-zero. 200/256 bits
uint32 maxTokenSupplyForStage; // 232/256 bits
uint16 feeBps; // 248/256 bits
bool restrictFeeRecipients; // 256/256 bits
}
/**
* @notice A struct defining mint params for an allow list.
* An allow list leaf will be composed of `msg.sender` and
* the following params.
*
* Note: Since feeBps is encoded in the leaf, backend should ensure
* that feeBps is acceptable before generating a proof.
*
* @param mintPrice The mint price per token.
* @param maxTotalMintableByWallet Maximum total number of mints a user is
* allowed.
* @param startTime The start time, ensure this is not zero.
* @param endTime The end time, ensure this is not zero.
* @param dropStageIndex The drop stage index to emit with the event
* for analytical purposes. This should be
* non-zero since the public mint emits with
* index zero.
* @param maxTokenSupplyForStage The limit of token supply this stage can
* mint within.
* @param feeBps Fee out of 10_000 basis points to be
* collected.
* @param restrictFeeRecipients If false, allow any fee recipient;
* if true, check fee recipient is allowed.
*/
struct MintParams {
uint256 mintPrice;
uint256 maxTotalMintableByWallet;
uint256 startTime;
uint256 endTime;
uint256 dropStageIndex; // non-zero
uint256 maxTokenSupplyForStage;
uint256 feeBps;
bool restrictFeeRecipients;
}
/**
* @notice A struct defining token gated mint params.
*
* @param allowedNftToken The allowed nft token contract address.
* @param allowedNftTokenIds The token ids to redeem.
*/
struct TokenGatedMintParams {
address allowedNftToken;
uint256[] allowedNftTokenIds;
}
/**
* @notice A struct defining allow list data (for minting an allow list).
*
* @param merkleRoot The merkle root for the allow list.
* @param publicKeyURIs If the allowListURI is encrypted, a list of URIs
* pointing to the public keys. Empty if unencrypted.
* @param allowListURI The URI for the allow list.
*/
struct AllowListData {
bytes32 merkleRoot;
string[] publicKeyURIs;
string allowListURI;
}
/**
* @notice A struct defining minimum and maximum parameters to validate for
* signed mints, to minimize negative effects of a compromised signer.
*
* @param minMintPrice The minimum mint price allowed.
* @param maxMaxTotalMintableByWallet The maximum total number of mints allowed
* by a wallet.
* @param minStartTime The minimum start time allowed.
* @param maxEndTime The maximum end time allowed.
* @param maxMaxTokenSupplyForStage The maximum token supply allowed.
* @param minFeeBps The minimum fee allowed.
* @param maxFeeBps The maximum fee allowed.
*/
struct SignedMintValidationParams {
uint80 minMintPrice; // 80/256 bits
uint24 maxMaxTotalMintableByWallet; // 104/256 bits
uint40 minStartTime; // 144/256 bits
uint40 maxEndTime; // 184/256 bits
uint40 maxMaxTokenSupplyForStage; // 224/256 bits
uint16 minFeeBps; // 240/256 bits
uint16 maxFeeBps; // 256/256 bits
}"
},
"src/lib/ERC721SeaDropStructsErrorsAndEvents.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {
AllowListData,
PublicDrop,
SignedMintValidationParams,
TokenGatedDropStage
} from "./SeaDropStructs.sol";
interface ERC
Submitted on: 2025-10-02 10:01:45
Comments
Log in to comment.
No comments yet.