diff --git a/contracts/ERC721A.sol b/contracts/ERC721A.sol index 43bbf1808..45688c350 100644 --- a/contracts/ERC721A.sol +++ b/contracts/ERC721A.sol @@ -18,6 +18,7 @@ error ApprovalToCurrentOwner(); error BalanceQueryForZeroAddress(); error MintToZeroAddress(); error MintZeroQuantity(); +error MintExistingId(); error OwnerQueryForNonexistentToken(); error TransferCallerNotOwnerNorApproved(); error TransferFromIncorrectOwner(); @@ -88,10 +89,10 @@ contract ERC721A is Context, ERC165, IERC721, IERC721Metadata { // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; - constructor(string memory name_, string memory symbol_) { + constructor(string memory name_, string memory symbol_, uint256 _startId) { _name = name_; _symbol = symbol_; - _currentIndex = _startTokenId(); + _currentIndex = _startId; } /** @@ -178,23 +179,21 @@ contract ERC721A is Context, ERC165, IERC721, IERC721Metadata { uint256 curr = tokenId; unchecked { - if (_startTokenId() <= curr && curr < _currentIndex) { - TokenOwnership memory ownership = _ownerships[curr]; - if (!ownership.burned) { + TokenOwnership memory ownership = _ownerships[curr]; + if (!ownership.burned) { + if (ownership.addr != address(0)) { + return ownership; + } + // Invariant: + // There will always be an ownership that has an address and is not burned + // before an ownership that does not have an address and is not burned. + // Hence, curr will not underflow. + while (true) { + curr--; + ownership = _ownerships[curr]; if (ownership.addr != address(0)) { return ownership; } - // Invariant: - // There will always be an ownership that has an address and is not burned - // before an ownership that does not have an address and is not burned. - // Hence, curr will not underflow. - while (true) { - curr--; - ownership = _ownerships[curr]; - if (ownership.addr != address(0)) { - return ownership; - } - } } } } @@ -429,6 +428,23 @@ contract ERC721A is Context, ERC165, IERC721, IERC721Metadata { _afterTokenTransfers(address(0), to, startTokenId, quantity); } + function _mintId(address to, uint256 _tokenId) internal { + if (to == address(0)) revert MintToZeroAddress(); + if(_ownerships[_tokenId].addr != address(0)) revert MintExistingId(); + + _beforeTokenTransfers(address(0), to, _tokenId, 1); + + _addressData[to].balance++; + _addressData[to].numberMinted++; + + _ownerships[_tokenId].addr = to; + _ownerships[_tokenId].startTimestamp = uint64(block.timestamp); + _ownerships[_tokenId].burned = false; + + _afterTokenTransfers(address(0), to, _tokenId, 1); + emit Transfer(address(0), to, _tokenId); + } + /** * @dev Transfers `tokenId` from `from` to `to`. * @@ -534,7 +550,7 @@ contract ERC721A is Context, ERC165, IERC721, IERC721Metadata { // Keep track of who burned the token, and the timestamp of burning. TokenOwnership storage currSlot = _ownerships[tokenId]; - currSlot.addr = from; + currSlot.addr = address(0); currSlot.startTimestamp = uint64(block.timestamp); currSlot.burned = true; diff --git a/package.json b/package.json index 82e9b204a..410cfbd14 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "erc721a", - "version": "3.2.0", + "name": "@hotcrosscom/erc721a", + "version": "3.3.0", "description": "ERC721A contract for Solidity", "files": [ "/contracts/**/*.sol", @@ -35,14 +35,14 @@ "prettier-plugin-solidity": "^1.0.0-beta.19", "solidity-coverage": "^0.7.20" }, - "repository": { - "type": "git", - "url": "git+https://github.com/chiru-labs/ERC721A.git" - }, - "author": "chiru-labs", - "license": "ISC", + "repository": "git@github.com:hotcrosscom/ERC721A.git", + "license": "MIT", "bugs": { - "url": "https://github.com/chiru-labs/ERC721A/issues" + "url": "https://github.com/hotcrosscom/ERC721A/issues" + }, + "publishConfig": { + "access": "public", + "registry": "https://npm.pkg.github.com" }, - "homepage": "https://github.com/chiru-labs/ERC721A#readme" + "homepage": "https://github.com/hotcrosscom/ERC721A#readme" }