SoundEditionV2
contracts/core/SoundEditionV2.sol
(opens in a new tab)
The Sound Protocol NFT contract.
Overview:
- Inherits ERC721A (opens in a new tab).
- Enables the owner, authorized minter contracts or administrators to batch mint NFTs. Authorization is granted by the owner via the
grantRoles
function inherited fromOwnableRoles
. - Token IDs are minted sequentially (e.g. 1, 2, 3...) starting from 1.
- Can optionally implement a
metadataModule
that effectively overrides the defaulttokenURI
function. - Can natively support range editions (opens in a new tab) via a dynamic maximum mintable supply (based on a
editionCutoffTime
), - Has a pseudorandom
mintRandomness
number optionally set on eachmint
call, which can be used for game mechanics. - Implements EIP-2981 Royalty Standard (opens in a new tab).
- Supports per-token tier.
Tiers:
- The zeroth tier is called the
GA_TIER
(short for General Admission). This is a special tier that uses default settings on the SoundEdition, as well as platform default settings on minters. - Tiers can range from 0 to 255 inclusive.
- Each tier contains its own max mintable range, cutoff time, and mint randomness.
Inherits:
Structs
TierInfo
struct TierInfo {
// The tier.
uint8 tier;
// The current max mintable amount.
uint32 maxMintable;
// The lower bound of the maximum number of tokens that can be minted for the tier.
uint32 maxMintableLower;
// The upper bound of the maximum number of tokens that can be minted for the tier.
uint32 maxMintableUpper;
// The timestamp (in seconds since unix epoch) after which the
// max amount of tokens mintable for the tier will drop from
// `maxMintableUpper` to `maxMintableLower`.
uint32 cutoffTime;
// The total number of tokens minted for the tier.
uint32 minted;
// The mint randomness for the tier.
uint256 mintRandomness;
// Whether the tier mints have concluded.
bool mintConcluded;
// Whether the tier has mint randomness enabled.
bool mintRandomnessEnabled;
// Whether the tier is frozen.
bool isFrozen;
}
The information pertaining to a tier.
TierCreation
struct TierCreation {
// The tier.
uint8 tier;
// The lower bound of the maximum number of tokens that can be minted for the tier.
uint32 maxMintableLower;
// The upper bound of the maximum number of tokens that can be minted for the tier.
uint32 maxMintableUpper;
// The timestamp (in seconds since unix epoch) after which the
// max amount of tokens mintable for the tier will drop from
// `maxMintableUpper` to `maxMintableLower`.
uint32 cutoffTime;
// Whether the tier has mint randomness enabled.
bool mintRandomnessEnabled;
// Whether the tier is frozen.
bool isFrozen;
}
A struct containing the arguments for creating a tier.
EditionInfo
struct EditionInfo {
// Base URI for the metadata.
string baseURI;
// Contract URI for OpenSea storefront.
string contractURI;
// Name of the collection.
string name;
// Symbol of the collection.
string symbol;
// Address that receives primary and secondary royalties.
address fundingRecipient;
// Address of the metadata module. Optional.
address metadataModule;
// Whether the metadata is frozen.
bool isMetadataFrozen;
// Whether the ability to create tiers is frozen.
bool isCreateTierFrozen;
// The royalty BPS (basis points).
uint16 royaltyBPS;
// Next token ID to be minted.
uint256 nextTokenId;
// Total number of tokens burned.
uint256 totalBurned;
// Total number of tokens minted.
uint256 totalMinted;
// Total number of tokens currently in existence.
uint256 totalSupply;
// An array of tier info. From lowest (0-indexed) to highest.
TierInfo[] tierInfo;
}
The information pertaining to this edition.
EditionInitialization
struct EditionInitialization {
// Name of the collection.
string name;
// Symbol of the collection.
string symbol;
// Address of the metadata module. Optional.
address metadataModule;
// Base URI for the metadata.
string baseURI;
// Contract URI for OpenSea storefront.
string contractURI;
// Address that receives primary and secondary royalties.
address fundingRecipient;
// The royalty BPS (basis points).
uint16 royaltyBPS;
// Whether the metadata is frozen.
bool isMetadataFrozen;
// Whether the ability to create tiers is frozen.
bool isCreateTierFrozen;
// An array of tier creation structs. From lowest (0-indexed) to highest.
TierCreation[] tierCreations;
}
A struct containing the arguments for initialization.
Write Functions
initialize
function initialize(EditionInitialization calldata init) external
Initializes the contract.
This function is called in the create
function of SoundCreatorV2, right after the creation of the SoundEdtion, within the same transaction.
Params: | |
---|---|
init | The initialization struct. |
mint
function mint(
uint8 tier,
address to,
uint256 quantity
) external payable returns (uint256 fromTokenId)
Mints quantity
tokens to addrress to
Each token will be assigned a token ID that is consecutively increasing.
Calling conditions:
- The caller must be the owner of the contract, or have either the
ADMIN_ROLE
,MINTER_ROLE
, which can be granted viagrantRoles
. Multiple minters, such as different minter contracts, can be authorized simultaneously.
Params: | |
---|---|
tier | The tier. |
to | Address to mint to. |
quantity | Number of tokens to mint. |
Returns the first token ID minted.
airdrop
function airdrop(
uint8 tier,
address[] calldata to,
uint256 quantity
) external returns (uint256 fromTokenId)
Mints quantity
tokens to each of the addresses in to
.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
, which can be granted viagrantRoles
.
Params: | |
---|---|
tier | The tier. |
to | Addresses to mint to. |
quantity | Number of tokens to mint. |
Returns the first token ID minted.
withdrawETH
function withdrawETH() external
Withdraws collected ETH royalties to the fundingRecipient.
withdrawERC20
function withdrawERC20(address[] calldata tokens) external
Withdraws collected ERC20 royalties to the fundingRecipient.
Params: | |
---|---|
tokens | array of ERC20 tokens to withdraw |
setMetadataModule
function setMetadataModule(address metadataModule) external
Sets metadata module.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
metadataModule | Address of metadata module. |
setBaseURI
function setBaseURI(string memory baseURI) external
Sets global base URI.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
baseURI | The base URI to be set. |
setContractURI
function setContractURI(string memory contractURI) external
Sets contract URI.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
contractURI | The contract URI to be set. |
freezeMetadata
function freezeMetadata() external
Freezes metadata by preventing any more changes to base URI.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
freezeCreateTier
function freezeCreateTier() external
Freezes any more new tiers from being added.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
setFundingRecipient
function setFundingRecipient(address fundingRecipient) external
Sets funding recipient address.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
fundingRecipient | Address to be set as the new funding recipient. |
createSplit
function createSplit(address splitMain, bytes calldata splitData)
external
returns (address split)
Creates a new split wallet via the SplitMain contract, then sets it as the fundingRecipient
.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
splitMain | The address of the SplitMain contract. |
splitData | The calldata to forward to the SplitMain contract to create a split. |
Returns the address of the new split contract.
setRoyalty
function setRoyalty(uint16 bps) external
Sets royalty amount in bps (basis points).
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
bps | The new royalty basis points to be set. |
freezeTier
function freezeTier(uint8 tier) external
Freezes the tier.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
tier | The tier. |
setMaxMintableRange
function setMaxMintableRange(
uint8 tier,
uint32 lower,
uint32 upper
) external
Sets the edition max mintable range.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
tier | The tier. |
lower | The lower limit of the maximum number of tokens that can be minted. |
upper | The upper limit of the maximum number of tokens that can be minted. |
setCutoffTime
function setCutoffTime(uint8 tier, uint32 cutoffTime) external
Sets the timestamp after which, the max mintable amount for the tier
drops from the upper limit to the lower limit.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
tier | The tier. |
cutoffTime | The timestamp. |
setMintRandomnessEnabled
function setMintRandomnessEnabled(bool enabled) external
Sets whether the mintRandomness
is enabled.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
tier | The tier. |
enabled | The boolean value. |
createTier
function createTier(TierCreation calldata creation) external
Adds a new tier.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
creation | The tier creation data. |
emitAllMetadataUpdate
function emitAllMetadataUpdate() external
Emits an event to signal to marketplaces to refresh all the metadata.
Read-only Functions
editionInfo
function editionInfo() external view returns (EditionInfo memory)
Returns the edition info.
tierInfo
function tierInfo(uint8 tier) external view returns (TierInfo memory info)
Params: | |
---|---|
tier | The tier. |
Returns the tier info.
GA_TIER
function GA_TIER() external pure returns (uint8)
Returns the GA tier, which is 0.
BPS_DENOMINATOR
function BPS_DENOMINATOR() external pure returns (uint8)
Returns the basis points denominator used in fee calculations, which is 10000.
MINTER_ROLE
function MINTER_ROLE() external view returns (uint256)
Returns the minter role flag.
ADMIN_ROLE
function ADMIN_ROLE() external view returns (uint256)
Returns the admin role flag.
tokenTier
function tokenTier(uint256 tokenId) external view returns (uint8)
Params: | |
---|---|
tokenId | The token ID. |
Returns the tier of the tokenId
.
explicitTokenTier
function explicitTokenTier(uint256 tokenId) external view returns (uint8)
Params: | |
---|---|
tokenId | The token ID. |
Returns the tier of the tokenId
.
Note: Will NOT revert if any
tokenId
does not exist.If the token has not been minted, the tier will be zero.
If the token is burned, the tier will be the tier before it was burned.
tierTokenIds
function tierTokenIds(uint8 tier) external view returns (uint256[] memory tokenIds)
Params: | |
---|---|
tier | The tier. |
Returns an array of all the token IDs in the tier.
tierTokenIdsIn
function tierTokenIdsIn(
uint8 tier,
uint256 start,
uint256 stop
) external view returns (uint256[] memory tokenIds)
Params: | |
---|---|
tier | The tier. |
start | The start of the range. Inclusive. |
stop | The stop of the range. Exclusive. |
Returns an array of all the token IDs in the tier, within the range [start, stop).
tierTokenIdIndex
function tierTokenIdIndex(uint256 tokenId) external view returns (uint256)
Params: | |
---|---|
tokenId | The token ID to find. |
Returns the index of tokenId
in it's tier token ID array.
If not found, returns type(uint256).max
.
maxMintable
function maxMintable(uint8 tier) external view returns (uint32)
Params: | |
---|---|
tier | The tier. |
Returns the maximum amount of tokens mintable for the tier.
maxMintableUpper
function maxMintableUpper(uint8 tier) external view returns (uint32)
Params: | |
---|---|
tier | The tier. |
Returns the upper bound for the maximum tokens that can be minted for the tier.
maxMintableLower
function maxMintableLower(uint8 tier) external view returns (uint32)
Params: | |
---|---|
tier | The tier. |
Returns the lower bound for the maximum tokens that can be minted for the tier.
cutoffTime
function cutoffTime(uint8 tier) external view returns (uint32)
Params: | |
---|---|
tier | The tier. |
Returns the timestamp after which maxMintable
drops from maxMintableUpper
to maxMintableLower
.
tierMinted
function tierMinted(uint8 tier) external view returns (uint32)
Params: | |
---|---|
tier | The tier. |
Returns the number of tokens minted for the tier.
supportsInterface
IERC165-supportsInterface
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool)
Returns true
if this contract implements the interface defined by interfaceId
.
See the corresponding EIP section (opens in a new tab) to learn more about how these ids are created.
Params: | |
---|---|
interfaceId | The 4 byte interface ID. |
Supported Interface IDs: | |
---|---|
IERC165 | 0x01ffc9a7 |
ERC721 | 0x80ac58cd |
ERC721Metadata | 0x5b5e139f |
ISoundEditionV2 | 0x7888cfe1 |
baseURI
function baseURI() external view returns (string memory)
Returns the base token URI for the collection.
contractURI
function contractURI() external view returns (string memory)
Returns the contract URI to be used by Opensea.
See: https://docs.opensea.io/docs/contract-level-metadata (opens in a new tab)
fundingRecipient
function fundingRecipient() external view returns (address)
Returns the address of the funding recipient.
editionMaxMintable
function editionMaxMintable() external view returns (uint32)
Returns the maximum amount of tokens mintable for this edition.
editionMaxMintableUpper
function editionMaxMintableUpper() external view returns (uint32)
Returns the upper bound for the maximum tokens that can be minted for this edition.
editionMaxMintableLower
function editionMaxMintableLower() external view returns (uint32)
Returns the lower bound for the maximum tokens that can be minted for this edition.
editionCutoffTime
function editionCutoffTime() external view returns (uint32)
Returns the timestamp after which editionMaxMintable
drops from editionMaxMintableUpper
to editionMaxMintableLower
.
metadataModule
function metadataModule() external view returns (address)
Returns the address of the metadata module.
mintRandomness
function mintRandomness() external view returns (uint256)
Returns the randomness based on latest block hash, which is stored upon each mint unless mintConcluded is true.
Used for game mechanics like the Sound Golden Egg. Returns 0 before revealed.
:warning: This value should NOT be used for any reward of significant monetary value, due to it being computed via a purely on-chain psuedorandom mechanism.
mintRandomnessEnabled
function mintRandomnessEnabled() external view returns (bool)
Returns whether the mintRandomness
has been enabled.
mintConcluded
function mintConcluded() external view returns (bool)
Returns whether the mint has been concluded.
royaltyBPS
function royaltyBPS() external view returns (uint16)
Returns the royalty basis points.
isMetadataFrozen
function isMetadataFrozen() external view returns (bool)
Returns whether the metadata module is frozen.
nextTokenId
function nextTokenId() external view returns (uint256)
Returns the next token ID to be minted.
numberMinted
function numberMinted(address owner) external view returns (uint256)
Returns the number of tokens minted by owner
.
Params: | |
---|---|
owner | Address to query for number minted. |
numberBurned
function numberBurned(address owner) external view returns (uint256)
Returns the number of tokens burned by owner
.
Params: | |
---|---|
owner | Address to query for number burned. |
totalMinted
function totalMinted() external view returns (uint256)
Returns the total amount of tokens minted.
totalBurned
function totalBurned() external view returns (uint256);
Returns the total amount of tokens burned.
Events
MetadataModuleSet
event MetadataModuleSet(address metadataModule)
Emitted when the metadata module is set.
Params: | |
---|---|
metadataModule | the address of the metadata module. |
BaseURISet
event BaseURISet(string baseURI)
Emitted when the baseURI
is set.
Params: | |
---|---|
baseURI | the base URI of the edition. |
ContractURISet
event ContractURISet(string contractURI)
Emitted when the contractURI
is set.
Params: | |
---|---|
contractURI | The contract URI of the edition. |
MetadataFrozen
event MetadataFrozen(address metadataModule, string baseURI, string contractURI)
Emitted when the metadata is frozen (e.g.: baseURI
can no longer be changed).
Params: | |
---|---|
metadataModule | The address of the metadata module. |
baseURI | The base URI of the edition. |
contractURI | The contract URI of the edition. |
CreateTierFrozen
event CreateTierFrozen()
Emitted when the ability to create tier is removed. event CreateTierFrozen();
FundingRecipientSet
event FundingRecipientSet(address recipient)
Emitted when the fundingRecipient
is set.
Params: | |
---|---|
recipient | The address of the funding recipient. |
RoyaltySet
event RoyaltySet(uint16 bps)
Emitted when the royaltyBPS
is set.
Params: | |
---|---|
bps | The new royalty, measured in basis points. |
MaxMintableRangeSet
event MaxMintableRangeSet(uint8 tier, uint32 lower, uint32 upper)
Emitted when the tier's maximum mintable token quantity range is set.
Params: | |
---|---|
tier | The tier. |
lower | The lower limit of the maximum number of tokens that can be minted. |
upper | The upper limit of the maximum number of tokens that can be minted. |
CutoffTimeSet
event CutoffTimeSet(uint8 tier, uint32 cutoff)
Emitted when the tier's cutoff time set.
Params: | |
---|---|
tier | The tier. |
cutoff | The timestamp. |
MintRandomnessEnabledSet
event MintRandomnessEnabledSet(uint8 tier, bool enabled)
Emitted when the mintRandomnessEnabled
for the tier is set.
Params: | |
---|---|
tier | The tier. |
enabled | The boolean value. |
SoundEditionInitialized
event SoundEditionInitialized(EditionInitialization init)
Emitted upon initialization.
Params: | |
---|---|
init | The initialization data. |
TierCreated
event TierCreated(TierCreation creation)
Emitted when a tier is created.
Params: | |
---|---|
creation | The tier creation data. |
TierFrozen
event TierFrozen(uint8 tier)
Emitted when a tier is frozen.
Params: | |
---|---|
tier | The tier. |
ETHWithdrawn
event ETHWithdrawn(address recipient, uint256 amount, address caller)
Emitted upon ETH withdrawal.
Params: | |
---|---|
recipient | The recipient of the withdrawal. |
amount | The amount withdrawn. |
caller | The account that initiated the withdrawal. |
ERC20Withdrawn
event ERC20Withdrawn(address recipient, address[] tokens, uint256[] amounts, address caller)
Emitted upon ERC20 withdrawal.
Params: | |
---|---|
recipient | The recipient of the withdrawal. |
tokens | The addresses of the ERC20 tokens. |
amounts | The amount of each token withdrawn. |
caller | The account that initiated the withdrawal. |
Minted
event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId)
Emitted upon a mint.
Params: | |
---|---|
tier | The tier. |
to | The address to mint to. |
quantity | The number of minted. |
fromTokenId | The first token ID minted. |
Airdropped
event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId)
Emitted upon an airdrop.
Params: | |
---|---|
tier | The tier. |
to | The recipients of the airdrop. |
quantity | The number of tokens airdropped to each address in to . |
fromTokenId | The first token ID minted to the first address in to . |
to
event BatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId)
EIP-4906 event to signal marketplaces to refresh the metadata.
Errors
MetadataIsFrozen
error MetadataIsFrozen()
The edition's metadata is frozen (e.g.: baseURI
can no longer be changed).
CreateTierIsFrozen
error CreateTierIsFrozen()
The ability to create tiers is frozen.
InvalidRoyaltyBPS
error InvalidRoyaltyBPS()
The given royaltyBPS
is invalid.
ZeroTiersProvided
error ZeroTiersProvided()
A minimum of one tier must be provided to initialize a Sound Edition.
ExceedsAvailableSupply
error ExceedsAvailableSupply()
The requested quantity exceeds the edition's remaining mintable token quantity.
InvalidFundingRecipient
error InvalidFundingRecipient()
The given fundingRecipient
address is invalid.
InvalidMaxMintableRange
error InvalidMaxMintableRange()
The maxMintableLower
must not be greater than maxMintableUpper
.
MintHasConcluded
error MintHasConcluded()
The mint has already concluded.
MintNotConcluded
error MintNotConcluded()
The mint has not concluded.
MintsAlreadyExist
error MintsAlreadyExist()
Cannot perform the operation after a token has been minted.
TierMintsAlreadyExist
error TierMintsAlreadyExist()
Cannot perform the operation after a token has been minted in the tier.
TokenIdsNotStrictlyAscending
error TokenIdsNotStrictlyAscending()
The token IDs must be in strictly ascending order.
TierDoesNotExist
error TierDoesNotExist()
The tier does not exist.
TierAlreadyExists
error TierAlreadyExists()
The tier already exists.
TierIsFrozen
error TierIsFrozen()
The tier is frozen.
InvalidTokenTier
error InvalidTokenTier()
One of more of the tokens do not have the correct token tier.
CannotBurnImmediately
error CannotBurnImmediately()
Please wait for a while before you burn.
TierQueryForNonexistentToken
error TierQueryForNonexistentToken()
The token for the tier query doesn't exist.