You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
630 lines
14 KiB
Markdown
630 lines
14 KiB
Markdown
2 years ago
|
# ERC721A
|
||
|
|
||
|
[`erc721a/contracts/ERC721A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/ERC721A.sol)
|
||
|
|
||
|
Implementation of [ERC721](https://eips.ethereum.org/EIPS/eip-721) Non-Fungible Token Standard, including the Metadata extension. Built to optimize for lower gas during batch mints.
|
||
|
|
||
|
Token IDs are minted sequentially (e.g. 0, 1, 2, 3...) starting from `_startTokenId()`.
|
||
|
|
||
|
An owner cannot have more than `2**64 - 1` (max value of `uint64`) tokens.
|
||
|
|
||
|
Inherits:
|
||
|
|
||
|
- [IERC721A](interfaces.md#ierc721a)
|
||
|
|
||
|
## Structs
|
||
|
|
||
|
### TokenOwnership
|
||
|
|
||
|
```solidity
|
||
|
struct TokenOwnership {
|
||
|
// The address of the owner.
|
||
|
address addr;
|
||
|
// Keeps track of the start time of ownership with minimal overhead for tokenomics.
|
||
|
uint64 startTimestamp;
|
||
|
// Whether the token has been burned.
|
||
|
bool burned;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Holds ownership data for each token.
|
||
|
|
||
|
`startTimestamp` is the timestamp when the token is minted to, transferred to, or burned by `addr`.
|
||
|
|
||
|
|
||
|
## Functions
|
||
|
|
||
|
### constructor
|
||
|
|
||
|
```solidity
|
||
|
constructor(string memory name_, string memory symbol_)
|
||
|
```
|
||
|
|
||
|
Initializes the contract by setting a `name` and a `symbol` to the token collection.
|
||
|
|
||
|
### supportsInterface
|
||
|
|
||
|
`IERC165-supportsInterface`
|
||
|
|
||
|
```solidity
|
||
|
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](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) to learn more about how these ids are created.
|
||
|
|
||
|
See [migration](migration.md#supportsInterface) for `supportsInterface`.
|
||
|
|
||
|
### totalSupply
|
||
|
|
||
|
`IERC721Enumerable-totalSupply`
|
||
|
|
||
|
```solidity
|
||
|
function totalSupply() public view returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the total number of tokens in existence.
|
||
|
|
||
|
Burned tokens will reduce the count.
|
||
|
|
||
|
To get the total number of tokens minted, please see [`_totalMinted`](#_totalMinted).
|
||
|
|
||
|
### balanceOf
|
||
|
|
||
|
`IERC721-balanceOf`
|
||
|
|
||
|
```solidity
|
||
|
function balanceOf(address owner) public view override returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the number of tokens in `owner`'s account.
|
||
|
|
||
|
### ownerOf
|
||
|
|
||
|
`IERC721-ownerOf`
|
||
|
|
||
|
```solidity
|
||
|
function ownerOf(uint256 tokenId) public view override returns (address)
|
||
|
```
|
||
|
|
||
|
Returns the owner of the `tokenId` token.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- `tokenId` must exist.
|
||
|
|
||
|
### name
|
||
|
|
||
|
`IERC721Metadata-name`
|
||
|
|
||
|
```solidity
|
||
|
function name() public view virtual override returns (string memory)
|
||
|
```
|
||
|
|
||
|
Returns the token collection name.
|
||
|
|
||
|
### symbol
|
||
|
|
||
|
`IERC721Metadata-symbol`
|
||
|
|
||
|
```solidity
|
||
|
function symbol() public view virtual override returns (string memory)
|
||
|
```
|
||
|
|
||
|
Returns the token collection symbol.
|
||
|
|
||
|
### tokenURI
|
||
|
|
||
|
`IERC721Metadata-tokenURI`
|
||
|
|
||
|
```solidity
|
||
|
function tokenURI(uint256 tokenId) public view virtual override returns (string memory)
|
||
|
```
|
||
|
|
||
|
Returns the Uniform Resource Identifier (URI) for `tokenId` token.
|
||
|
|
||
|
See [`_baseURI`](#_baseURI) and [`_toString`](#_toString).
|
||
|
|
||
|
|
||
|
### approve
|
||
|
|
||
|
`IERC721-approve`
|
||
|
|
||
|
```solidity
|
||
|
function approve(address to, uint256 tokenId) public override
|
||
|
```
|
||
|
|
||
|
Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred.
|
||
|
|
||
|
Only a single account can be approved at a time, so approving the zero address clears previous approvals.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- The caller must own the token or be an approved operator.
|
||
|
- `tokenId` must exist.
|
||
|
|
||
|
Emits an `Approval` event.
|
||
|
|
||
|
### getApproved
|
||
|
|
||
|
```solidity
|
||
|
function getApproved(uint256 tokenId) public view override returns (address)
|
||
|
```
|
||
|
|
||
|
`IERC721-getApproved`
|
||
|
|
||
|
Returns the account approved for `tokenId` token.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- `tokenId` must exist.
|
||
|
|
||
|
### setApprovalForAll
|
||
|
|
||
|
`IERC721-setApprovalForAll`
|
||
|
|
||
|
```solidity
|
||
|
function setApprovalForAll(
|
||
|
address operator,
|
||
|
bool approved
|
||
|
) public virtual override
|
||
|
```
|
||
|
|
||
|
Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- The `operator` cannot be the caller.
|
||
|
|
||
|
Emits an `ApprovalForAll` event.
|
||
|
|
||
|
### isApprovedForAll
|
||
|
|
||
|
`IERC721-isApprovedForAll`
|
||
|
|
||
|
```solidity
|
||
|
function isApprovedForAll(
|
||
|
address owner,
|
||
|
address operator
|
||
|
) public view virtual override returns (bool)
|
||
|
```
|
||
|
|
||
|
Returns if the `operator` is allowed to manage all of the assets of owner.
|
||
|
|
||
|
See [`setApprovalForAll`](#setApprovalForAll).
|
||
|
|
||
|
### transferFrom
|
||
|
|
||
|
`IERC721-transferFrom`
|
||
|
|
||
|
```solidity
|
||
|
function transferFrom(
|
||
|
address from,
|
||
|
address to,
|
||
|
uint256 tokenId
|
||
|
) public virtual override
|
||
|
```
|
||
|
|
||
|
Transfers `tokenId` token from `from` to `to`.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- `from` cannot be the zero address.
|
||
|
- `to` cannot be the zero address.
|
||
|
- `tokenId` token must be owned by `from`.
|
||
|
- If the caller is not `from`, it must be approved to move this token by either `approve` or `setApprovalForAll`.
|
||
|
|
||
|
Emits a `Transfer` event.
|
||
|
|
||
|
### safeTransferFrom
|
||
|
|
||
|
`IERC721-safeTransferFrom`
|
||
|
|
||
|
```solidity
|
||
|
function safeTransferFrom(
|
||
|
address from,
|
||
|
address to,
|
||
|
uint256 tokenId,
|
||
|
bytes memory _data
|
||
|
) public virtual override
|
||
|
```
|
||
|
|
||
|
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.
|
||
|
|
||
|
The `data` parameter is forwarded in `IERC721Receiver.onERC721Received` to contract recipients (optional, default: `""`).
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- `from` cannot be the zero address.
|
||
|
- `to` cannot be the zero address.
|
||
|
- `tokenId` token must be owned by `from`.
|
||
|
- If the caller is not `from`, it must be approved to move this token by either `approve` or `setApprovalForAll`.
|
||
|
- If `to` refers to a smart contract, it must implement `IERC721Receiver.onERC721Received`, which is called upon a safe transfer.
|
||
|
|
||
|
Emits a `Transfer` event.
|
||
|
|
||
|
|
||
|
### \_startTokenId
|
||
|
|
||
|
```solidity
|
||
|
function _startTokenId() internal view virtual returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the starting token ID (default: `0`).
|
||
|
|
||
|
To change the starting token ID, override this function to return a different constant.
|
||
|
|
||
|
|
||
|
### \_nextTokenId
|
||
|
|
||
|
```solidity
|
||
|
function _nextTokenId() internal view virtual returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the next token ID to be minted.
|
||
|
|
||
|
|
||
|
### \_totalMinted
|
||
|
|
||
|
```solidity
|
||
|
function _totalMinted() internal view returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the total amount of tokens minted.
|
||
|
|
||
|
### \_numberMinted
|
||
|
|
||
|
```solidity
|
||
|
function _numberMinted(address owner) internal view returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the number of tokens minted by or on behalf of `owner`.
|
||
|
|
||
|
### \_totalBurned
|
||
|
|
||
|
```solidity
|
||
|
function _totalBurned() internal view returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the total amount of tokens burned.
|
||
|
|
||
|
|
||
|
### \_numberBurned
|
||
|
|
||
|
```solidity
|
||
|
function _numberBurned(address owner) internal view returns (uint256)
|
||
|
```
|
||
|
|
||
|
Returns the number of tokens burned by or on behalf of `owner`.
|
||
|
|
||
|
### \_getAux
|
||
|
|
||
|
```solidity
|
||
|
function _getAux(address owner) internal view returns (uint64)
|
||
|
```
|
||
|
|
||
|
Returns the auxiliary data for `owner` (e.g. number of whitelist mint slots used).
|
||
|
|
||
|
### \_setAux
|
||
|
|
||
|
```solidity
|
||
|
function _setAux(address owner, uint64 aux) internal
|
||
|
```
|
||
|
|
||
|
Sets the auxiliary data for `owner` (e.g. number of whitelist mint slots used).
|
||
|
|
||
|
If there are multiple variables, please pack them into a `uint64`.
|
||
|
|
||
|
|
||
|
### \_ownershipOf
|
||
|
|
||
|
```solidity
|
||
|
function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory)
|
||
|
```
|
||
|
|
||
|
Returns the token ownership data for `tokenId`. See [`TokenOwnership`](#TokenOwnership).
|
||
|
|
||
|
The gas spent here starts off proportional to the maximum mint batch size.
|
||
|
|
||
|
It gradually moves to O(1) as tokens get transferred around in the collection over time.
|
||
|
|
||
|
|
||
|
### \_ownershipAt
|
||
|
|
||
|
```solidity
|
||
|
function _ownershipAt(uint256 index) internal view returns (TokenOwnership memory)
|
||
|
```
|
||
|
|
||
|
Returns the token ownership data at the `index` slot. See [`TokenOwnership`](#TokenOwnership).
|
||
|
|
||
|
The token ownership data may or may not be initialized.
|
||
|
|
||
|
|
||
|
### \_initializeOwnershipAt
|
||
|
|
||
|
```solidity
|
||
|
function _initializeOwnershipAt(uint256 index) internal
|
||
|
```
|
||
|
|
||
|
Initializes the token ownership data at the `index` slot, if it has not been initialized.
|
||
|
|
||
|
If the batch minted is very large, this function can be used to initialize some tokens to
|
||
|
reduce the first-time transfer costs.
|
||
|
|
||
|
|
||
|
### \_exists
|
||
|
|
||
|
```solidity
|
||
|
function _exists(uint256 tokenId) internal view returns (bool)
|
||
|
```
|
||
|
|
||
|
Returns whether `tokenId` exists.
|
||
|
|
||
|
Tokens can be managed by their owner or approved accounts via `approve` or `setApprovalForAll`.
|
||
|
|
||
|
Tokens start existing when they are minted via `_mint`.
|
||
|
|
||
|
### \_safeMint
|
||
|
|
||
|
```solidity
|
||
|
function _safeMint(
|
||
|
address to,
|
||
|
uint256 quantity,
|
||
|
bytes memory _data
|
||
|
) internal
|
||
|
```
|
||
|
|
||
|
The `data` parameter is forwarded in `IERC721Receiver.onERC721Received` to contract recipients (optional, default: `""`).
|
||
|
|
||
|
**Safe minting is reentrancy safe since V3.**
|
||
|
|
||
|
See [`_mint`](#_mint).
|
||
|
|
||
|
### \_mint
|
||
|
|
||
|
```solidity
|
||
|
function _mint(
|
||
|
address to,
|
||
|
uint256 quantity
|
||
|
) internal
|
||
|
```
|
||
|
|
||
|
Mints `quantity` tokens and transfers them to `to`.
|
||
|
|
||
|
> To prevent excessive first-time token transfer costs, please limit the `quantity` to a reasonable number (e.g. 30).
|
||
|
>
|
||
|
> Extremely large `quantity` amounts (e.g. > 5000) may result in some marketplaces and indexers to drop some `Transfer` events,
|
||
|
> and cause some mints to not appear.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- `to` cannot be the zero address.
|
||
|
- `quantity` must be greater than `0`.
|
||
|
|
||
|
Emits a `Transfer` event.
|
||
|
|
||
|
### \_mintERC2309
|
||
|
|
||
|
```solidity
|
||
|
function _mintERC2309(
|
||
|
address to,
|
||
|
uint256 quantity
|
||
|
) internal
|
||
|
```
|
||
|
|
||
|
Mints `quantity` tokens and transfers them to `to`.
|
||
|
|
||
|
This function is intended for efficient minting **only** during contract creation.
|
||
|
|
||
|
It emits only one `ConsecutiveTransfer` as defined in [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
|
||
|
instead of a sequence of `Transfer` event(s).
|
||
|
|
||
|
Calling this function outside of contract creation **will** make your contract non-compliant with the ERC721 standard.
|
||
|
|
||
|
For full ERC721 compliance, substituting ERC721 `Transfer` event(s) with the ERC2309
|
||
|
`ConsecutiveTransfer` event is only permissible during contract creation.
|
||
|
|
||
|
> To prevent overflows, the function limits `quantity` to a maximum of 5000.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- `to` cannot be the zero address.
|
||
|
- `quantity` must be greater than `0`.
|
||
|
|
||
|
Emits a `ConsecutiveTransfer` event.
|
||
|
|
||
|
### \_burn
|
||
|
|
||
|
```solidity
|
||
|
function _burn(uint256 tokenId, bool approvalCheck) internal virtual
|
||
|
```
|
||
|
|
||
|
Destroys `tokenId`.
|
||
|
|
||
|
The approval is cleared when the token is burned.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- `tokenId` must exist.
|
||
|
- If `approvalCheck` is `true`, the caller must own `tokenId` or be an approved operator.
|
||
|
|
||
|
Emits a `Transfer` event.
|
||
|
|
||
|
|
||
|
### \_baseURI
|
||
|
|
||
|
```solidity
|
||
|
function _baseURI() internal view virtual returns (string memory)
|
||
|
```
|
||
|
|
||
|
Base URI for computing `tokenURI`.
|
||
|
|
||
|
If set, the resulting URI for each token will be the concatenation of the `baseURI` and the `tokenId`.
|
||
|
|
||
|
Empty by default, it can be overridden in child contracts.
|
||
|
|
||
|
|
||
|
### \_beforeTokenTransfers
|
||
|
|
||
|
```solidity
|
||
|
function _beforeTokenTransfers(
|
||
|
address from,
|
||
|
address to,
|
||
|
uint256 startTokenId,
|
||
|
uint256 quantity
|
||
|
) internal virtual
|
||
|
```
|
||
|
|
||
|
Hook that is called before a set of serially-ordered token IDs are about to be transferred. This includes minting.
|
||
|
|
||
|
Also called before burning one token.
|
||
|
|
||
|
`startTokenId` - the first token ID to be transferred.
|
||
|
`quantity` - the amount to be transferred.
|
||
|
|
||
|
Calling conditions:
|
||
|
|
||
|
- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`.
|
||
|
- When `from` is zero, `tokenId` will be minted for `to`.
|
||
|
- When `to` is zero, `tokenId` will be burned by `from`.
|
||
|
- `from` and `to` are never both zero.
|
||
|
|
||
|
|
||
|
### \_afterTokenTransfers
|
||
|
|
||
|
```solidity
|
||
|
function _afterTokenTransfers(
|
||
|
address from,
|
||
|
address to,
|
||
|
uint256 startTokenId,
|
||
|
uint256 quantity
|
||
|
) internal virtual
|
||
|
```
|
||
|
|
||
|
Hook that is called after a set of serially-ordered token IDs are about to be transferred. This includes minting.
|
||
|
|
||
|
Also called after burning one token.
|
||
|
|
||
|
`startTokenId` - the first token ID to be transferred.
|
||
|
`quantity` - the amount to be transferred.
|
||
|
|
||
|
Calling conditions:
|
||
|
|
||
|
- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`.
|
||
|
- When `from` is zero, `tokenId` will be minted for `to`.
|
||
|
- When `to` is zero, `tokenId` will be burned by `from`.
|
||
|
- `from` and `to` are never both zero.
|
||
|
|
||
|
|
||
|
### \_toString
|
||
|
|
||
|
```solidity
|
||
|
function _toString(uint256 value) internal pure returns (string memory)
|
||
|
```
|
||
|
|
||
|
Converts a `uint256` to its ASCII `string` decimal representation.
|
||
|
|
||
|
This function is provided as a drop-in replacement for OpenZeppelin's `Strings.toString(uint256 value)`.
|
||
|
|
||
|
|
||
|
### \_msgSenderERC721A
|
||
|
|
||
|
```solidity
|
||
|
function _msgSenderERC721A() internal view virtual returns (address)
|
||
|
```
|
||
|
|
||
|
Returns the message sender (defaults to `msg.sender`).
|
||
|
|
||
|
If you are writing [GSN compatible contracts](https://docs.openzeppelin.com/contracts/2.x/gsn),
|
||
|
you need to override this function
|
||
|
(to return `_msgSender()` if using with OpenZeppelin).
|
||
|
|
||
|
### \_extraData
|
||
|
|
||
|
```solidity
|
||
|
function _extraData(
|
||
|
address from,
|
||
|
address to,
|
||
|
uint24 previousExtraData
|
||
|
) internal view virtual returns (uint24)
|
||
|
```
|
||
|
|
||
|
Called during each token transfer to set the 24bit `extraData` field.
|
||
|
|
||
|
This is an advanced storage hitchhiking feature for storing token related data.
|
||
|
|
||
|
Intended to be overridden by the deriving contract to return the value to be stored after transfer.
|
||
|
|
||
|
`previousExtraData` - the value of `extraData` before transfer.
|
||
|
|
||
|
Calling conditions:
|
||
|
|
||
|
- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`.
|
||
|
- When `from` is zero, `tokenId` will be minted for `to`.
|
||
|
- When `to` is zero, `tokenId` will be burned by `from`.
|
||
|
- `from` and `to` are never both zero.
|
||
|
|
||
|
### \_setExtraDataAt
|
||
|
|
||
|
```solidity
|
||
|
function _setExtraDataAt(uint256 index, uint24 extraData) internal
|
||
|
```
|
||
|
|
||
|
Directly sets the `extraData` for the ownership data at `index`.
|
||
|
|
||
|
This is an advanced storage hitchhiking feature for storing token related data.
|
||
|
|
||
|
Requirements:
|
||
|
|
||
|
- The token at `index` must be initialized.
|
||
|
For bulk mints, `index` is the value of [`_nextTokenId`](#_nextTokenId) before bulk minting.
|
||
|
|
||
|
|
||
|
## Events
|
||
|
|
||
|
### Transfer
|
||
|
|
||
|
`IERC721-Transfer`
|
||
|
|
||
|
```solidity
|
||
|
event Transfer(address from, address to, uint256 tokenId)
|
||
|
```
|
||
|
|
||
|
Emitted when `tokenId` token is transferred from `from` to `to`.
|
||
|
|
||
|
### Approval
|
||
|
|
||
|
`IERC721-Approval`
|
||
|
|
||
|
```solidity
|
||
|
event Approval(address owner, address approved, uint256 tokenId)
|
||
|
```
|
||
|
|
||
|
Emitted when `owner` enables `approved` to manage the `tokenId` token.
|
||
|
|
||
|
### ApprovalForAll
|
||
|
|
||
|
`IERC721-ApprovalForAll`
|
||
|
|
||
|
```solidity
|
||
|
event ApprovalForAll(address owner, address operator, bool approved)
|
||
|
```
|
||
|
|
||
|
Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
|
||
|
|
||
|
### ConsecutiveTransfer
|
||
|
|
||
|
`IERC2309-ConsecutiveTransfer`
|
||
|
|
||
|
```solidity
|
||
|
event ConsecutiveTransfer(
|
||
|
uint256 indexed fromTokenId,
|
||
|
uint256 toTokenId,
|
||
|
address indexed from,
|
||
|
address indexed to
|
||
|
)
|
||
|
```
|
||
|
|
||
|
Emitted when tokens from `fromTokenId` to `toTokenId` (inclusive) are transferred from `from` to `to`, during contract creation.
|