SoundEdition
contracts/core/SoundEditionV1_1.sol
The Sound Protocol NFT contract.
Overview:
- An implementation of ERC721A.
- 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 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.
Inherits:
- ERC721AUpgradeable
- ERC721ABurnableUpgradeable
- ERC721AQueryableUpgradeable
- OwnableRoles from Solady
- OperatorFilterer from ClosedSea
Structs
EditionInfo
struct EditionInfo {
// Base URI for the tokenId.
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;
// The current max mintable amount;
uint32 editionMaxMintable;
// The lower limit of the maximum number of tokens that can be minted.
uint32 editionMaxMintableUpper;
// The upper limit of the maximum number of tokens that can be minted.
uint32 editionMaxMintableLower;
// The timestamp (in seconds since unix epoch) after which the
// max amount of tokens mintable will drop from
// `maxMintableUpper` to `maxMintableLower`.
uint32 editionCutoffTime;
// Address of metadata module, address(0x00) if not used.
address metadataModule;
// The current mint randomness value.
uint256 mintRandomness;
// The royalty BPS (basis points).
uint16 royaltyBPS;
// Whether the mint randomness is enabled.
bool mintRandomnessEnabled;
// Whether the mint has concluded.
bool mintConcluded;
// Whether the metadata has been frozen.
bool isMetadataFrozen;
// 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;
}
Holds information pertaining to the SoundEdition.
This struct is intended for off-chain queries, and can be retrieved via the editionInfo
function.
Write Functions
initialize
function initialize(
string memory name_,
string memory symbol_,
address metadataModule_,
string memory baseURI_,
string memory contractURI_,
address fundingRecipient_,
uint16 royaltyBPS_,
uint32 editionMaxMintableLower_,
uint32 editionMaxMintableUpper_,
uint32 editionCutoffTime_,
uint8 flags_
) external
Initializes the contract.
This function is called in the createSoundAndMints
function of SoundCreatorV1, right after the creation of the SoundEdtion, within the same transaction.
Params: | |
---|---|
name_ | Name of the collection. |
symbol_ | Symbol of the collection. |
metadataModule_ | Address of metadata module, address(0x00) if not used. |
baseURI_ | Base URI. |
contractURI_ | Contract URI for OpenSea storefront. |
fundingRecipient_ | Address that receives primary and secondary royalties. |
royaltyBPS_ | Royalty amount in bps (basis points). |
editionMaxMintableLower_ | The lower bound of the max mintable quantity for the edition. |
editionMaxMintableUpper_ | The upper bound of the max mintable quantity for the edition. |
editionCutoffTime_ | The timestamp after which editionMaxMintable drops from editionMaxMintableUpper to max(_totalMinted(), editionMaxMintableLower) . |
flags_ | The bitwise OR result of the initialization flags. See: METADATA_IS_FROZEN_FLAG See: MINT_RANDOMNESS_ENABLED_FLAG |
mint
function mint(address to, uint256 quantity) external payable returns (uint256)
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: | |
---|---|
to | Address to mint to. |
quantity | Number of tokens to mint. |
Returns the first token ID minted.
airdrop
function airdrop(address[] calldata to, uint256 quantity) external returns (uint256)
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: | |
---|---|
to | Address 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
.
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. |
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. |
setEditionMaxMintableRange
function setEditionMaxMintableRange(
uint32 editionMaxMintableLower_,
uint32 editionMaxMintableUpper_
) external
Sets the edition max mintable range.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
editionMaxMintableLower_ | The lower limit of the maximum number of tokens that can be minted. |
editionMaxMintableUpper_ | The upper limit of the maximum number of tokens that can be minted. |
setEditionCutoffTime
function setEditionCutoffTime(uint32 editionCutoffTime_) external
Sets the timestamp after which, the editionMaxMintable
drops from editionMaxMintableUpper
to editionMaxMintableLower
.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
editionCutoffTime_ | The timestamp. |
setMintRandomnessEnabled
function setMintRandomnessEnabled(bool mintRandomnessEnabled_) external
Sets whether the mintRandomness
is enabled.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
mintRandomnessEnabled_ | The boolean value. |
setOperatorFilteringEnabled
function setOperatorFilteringEnabled(bool operatorFilteringEnabled_) external
Sets whether OpenSea’s OperatorFilter registry is enabled.
Calling conditions:
- The caller must be the owner of the contract, or have the
ADMIN_ROLE
.
Params: | |
---|---|
operatorFilteringEnabled_ | The boolean value. |
setApprovalForAll
function setApprovalForAll(address operator, bool approved) external
Approves or removes operator
as an operator for the caller.
Operators can call transferFrom
or safeTransferFrom
for any token owned by the caller. If the OPERATOR_FILTERING_ENABLED_FLAG
is set,
this function will revert if the operator is not approved by the OperatorFilter registry.
Calling conditions:
- The
operator
cannot be the caller.
Params: | |
---|---|
operator | The operator address. |
approved | Whether or not the operator is approved. |
approve
function approve(address operator, bool approved) external
Gives permission to to
to transfer tokenId
token to another account. The approval is cleared when the token is transferred. Gives permission to to
to transfer tokenId
token to another account. The approval is cleared when the token is transferred. If the OPERATOR_FILTERING_ENABLED_FLAG
is set,
this function will revert if the operator is not approved by the OperatorFilter registry.
Calling conditions:
- The
operator
cannot be the caller.
Params: | |
---|---|
to | The permissioned operator. |
tokenId | The permissioned token. |
transferFrom
function transferFrom(address from, address to, uint256 tokenId) external payable
Transfers tokenId
token from from
to to
.
WARNING: Usage of this method is discouraged, use
safeTransferFrom
whenever possible.
Calling conditions:
from
cannot be the zero address.from
can only be approved operators (ifOPERATOR_FILTERING_ENABLED_FLAG
is set)to
cannot be the zero address.tokenId
token must be owned byfrom
.- If the caller is not
from
, it must be approved to move this token by eitherapprove
orsetApprovalForAll
.
Params: | |
---|---|
from | The sender. |
to | The receiver. |
tokenId | The permissioned token. |
safeTransferFrom
function safeTransferFrom(address from, address to, bytes calldata data) external payable
Safely transfers tokenId
token from from
to to
, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked.
Calling conditions:
from
cannot be the zero address.from
can only be approved operators (ifOPERATOR_FILTERING_ENABLED_FLAG
is set)to
cannot be the zero address.tokenId
token must exist and be owned byfrom
. If the caller is notfrom
, it must be have been allowed to move this token by eitherapprove
orsetApprovalForAll
. Ifto
refers to a smart contract, it must implementIERC721Receiver-onERC721Received
, which is called upon a safe transfer.
Params: | |
---|---|
from | The sender. |
to | The receiver. |
tokenId | The permissioned token. |
data | Optional data to be used by receiver if receiver is a smart contract. |
Read-only Functions
editionInfo
function editionInfo() external view returns (EditionInfo memory)
Returns the edition info.
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 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 |
ISoundEditionV1 | 0x50899e54 |
ISoundEditionV1_1 | 0x425aac3d |
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.
ADDRESS_BATCH_MINT_LIMIT
function ADDRESS_BATCH_MINT_LIMIT() external pure returns (uint256)
Returns the maximum limit for the mint or airdrop quantity
.
Prevents the first-time transfer costs for tokens near the end of large mint batches via ERC721A from becoming too expensive due to the need to scan many storage slots.
See: https://chiru-labs.github.io/ERC721A/#/tips?id=batch-size
Initialization flags
Each flag is a bit in the uint256 _flags
passed to the initialze
function.
METADATA_IS_FROZEN_FLAG
- If set, the metadata is frozen and cannot be changed.MINT_RANDOMNESS_ENABLED_FLAG
- If set, themintRandomness
function is enabled.OPERATOR_FILTERING_ENABLED_FLAG
- If set, the edition will be compatible with OpenSea’s OperatorFilter registry for creator fees.
Each flag’s base-10 value can be retrieved by calling its name as a function.
function METADATA_IS_FROZEN_FLAG() external pure returns (uint8);
function MINT_RANDOMNESS_ENABLED_FLAG() external pure returns (uint8);
function OPERATOR_FILTERING_ENABLED_FLAG() external pure returns (uint8);
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
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 a pseudorandom number 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 pseudorandom mechanism.
mintRandomnessEnabled
function mintRandomnessEnabled() external view returns (bool)
Returns whether the mintRandomness
has been enabled.
operatorFilteringEnabled
function operatorFilteringEnabled() external view returns (bool)
Returns whether the edition implements OpenSea’s OperatorFilter registry
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. |
FundingRecipientSet
event FundingRecipientSet(address fundingRecipient)
Emitted when the fundingRecipient
is set.
Params: | |
---|---|
fundingRecipient | 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. |
EditionMaxMintableRangeSet
event EditionMaxMintableRangeSet(
uint32 editionMaxMintableLower_,
uint32 editionMaxMintableUpper_
)
Emitted when the edition’s maximum mintable token quantity range is set.
Params: | |
---|---|
editionMaxMintableLower_ | The lower limit of the maximum number of tokens that can be minted. |
editionMaxMintableUpper_ | The upper limit of the maximum number of tokens that can be minted. |
EditionCutoffTimeSet
event EditionCutoffTimeSet(uint32 editionCutoffTime_)
Emitted when the edition’s cutoff time set.
Params: | |
---|---|
editionCutoffTime_ | The timestamp. |
MintRandomnessEnabledSet
event MintRandomnessEnabledSet(bool mintRandomnessEnabled_)
Emitted when the mintRandomnessEnabled
is set.
Params: | |
---|---|
mintRandomnessEnabled_ | The boolean value. |
SoundEditionInitialized
event SoundEditionInitialized(
address indexed edition_,
string name_,
string symbol_,
address metadataModule_,
string baseURI_,
string contractURI_,
address fundingRecipient_,
uint16 royaltyBPS_,
uint32 editionMaxMintableLower_,
uint32 editionMaxMintableUpper_,
uint32 editionCutoffTime_,
uint8 flags_
)
Emitted upon initialization.
Params: | |
---|---|
edition_ | The address of the edition. |
name_ | Name of the collection. |
symbol_ | Symbol of the collection. |
metadataModule_ | Address of metadata module, address(0) if not used. |
baseURI_ | Base URI. |
contractURI_ | Contract URI for OpenSea storefront. |
fundingRecipient_ | Address that receives primary and secondary royalties. |
royaltyBPS_ | Royalty amount in bps (basis points). |
editionMaxMintableLower_ | The lower bound of the max mintable quantity for the edition. |
editionMaxMintableUpper_ | The upper bound of the max mintable quantity for the edition. |
editionCutoffTime_ | The timestamp after which editionMaxMintable drops from editionMaxMintableUpper to max(_totalMinted(), editionMaxMintableLower) . |
flags_ | The bitwise OR result of the initialization flags. See: METADATA_IS_FROZEN_FLAG See: MINT_RANDOMNESS_ENABLED_FLAG |
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, uint256 amount, address caller)
Emitted upon ERC20 withdrawal.
Params: | |
---|---|
recipient | The recipient of the withdrawal.. |
tokens | The addresses of the ERC20 tokens. |
amount | The amount of each token withdrawn. |
caller | The account that initiated the withdrawal. |
Minted
event Minted(address to, uint256 quantity, uint256 fromTokenId);
Emitted upon a mint.
Params: | |
---|---|
to | The address to mint to. |
quantity | The number of minted. |
fromTokenId | The first token ID minted. |
Airdropped
event Minted(address to, uint256 quantity, uint256 fromTokenId);
Emitted upon an airdrop.
Params: | |
---|---|
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 . |
Errors
MetadataIsFrozen
error MetadataIsFrozen()
The edition’s metadata is frozen.
InvalidRoyaltyBPS
error InvalidRoyaltyBPS()
The given royaltyBPS
is invalid.
InvalidRandomnessLock
error InvalidRandomnessLock()
The given randomnessLockedAfterMinted
value is invalid.
ExceedsEditionAvailableSupply
error ExceedsEditionAvailableSupply(uint32 available)
The requested quantity exceeds the edition’s remaining mintable token quantity.
Params: | |
---|---|
available | The number of tokens remaining available for mint. |
InvalidAmount
error InvalidAmount()
The given amount is invalid.
InvalidFundingRecipient
error InvalidFundingRecipient()
The given fundingRecipient
address is invalid.
InvalidEditionMaxMintableRange
error InvalidEditionMaxMintableRange()
The editionMaxMintableLower
must not be greater than editionMaxMintableUpper
.
MaximumHasAlreadyBeenReached
error MaximumHasAlreadyBeenReached()
The editionMaxMintable
has already been reached.
ExceedsAddressBatchMintLimit
error ExceedsAddressBatchMintLimit()
The mint quantity
cannot exceed ADDRESS_BATCH_MINT_LIMIT
tokens.
MintRandomnessAlreadyRevealed
error MintRandomnessAlreadyRevealed()
The mint randomness has already been revealed.
NoAddressesToAirdrop
error NoAddressesToAirdrop()
No addresses to airdrop.
MintHasConcluded
error MintHasConcluded()
The mint has already concluded.
MintsAlreadyExist
error MintsAlreadyExist()
Cannot perform the operation after a token has been minted.