-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Ability to set starting token id for ERC721Consecutive #4097
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
b693f7f
bf8c076
31a565b
b651b93
854b461
1c7570d
ab40061
1835727
1fdcbff
44cc563
3f8b0f9
573fa0d
5d9b21b
0fcb048
dd1d6bf
361aa8d
114a3f6
6b4e4ee
78ed610
7959df3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,8 +15,10 @@ function toSingleton(address account) pure returns (address[] memory) { | |
|
|
||
| contract ERC721ConsecutiveTarget is StdUtils, ERC721Consecutive { | ||
| uint256 public totalMinted = 0; | ||
| uint96 public firstConsecutiveId = 0; | ||
|
|
||
| constructor(address[] memory receivers, uint256[] memory batches) ERC721("", "") { | ||
| constructor(address[] memory receivers, uint256[] memory batches, uint96 startingId) ERC721("", "") { | ||
| firstConsecutiveId = startingId; | ||
| for (uint256 i = 0; i < batches.length; i++) { | ||
| address receiver = receivers[i % receivers.length]; | ||
| uint96 batchSize = uint96(bound(batches[i], 0, _maxBatchSize())); | ||
|
|
@@ -28,36 +30,43 @@ contract ERC721ConsecutiveTarget is StdUtils, ERC721Consecutive { | |
| function burn(uint256 tokenId) public { | ||
| _burn(tokenId); | ||
| } | ||
|
|
||
| function _firstConsecutiveId() internal view virtual override returns (uint96) { | ||
| return firstConsecutiveId; | ||
| } | ||
| } | ||
|
|
||
| contract ERC721ConsecutiveTest is Test { | ||
| function test_balance(address receiver, uint256[] calldata batches) public { | ||
| function test_balance(address receiver, uint256[] calldata batches, uint96 startingId) public { | ||
| vm.assume(receiver != address(0)); | ||
| vm.assume(startingId < type(uint96).max - 5000); | ||
|
|
||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches); | ||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, startingId); | ||
|
|
||
| assertEq(token.balanceOf(receiver), token.totalMinted()); | ||
| } | ||
|
|
||
| function test_ownership(address receiver, uint256[] calldata batches, uint256[2] calldata unboundedTokenId) public { | ||
| function test_ownership(address receiver, uint256[] calldata batches, uint256[2] calldata unboundedTokenId, uint96 startingId) public { | ||
| vm.assume(receiver != address(0)); | ||
| vm.assume(startingId < type(uint96).max - 5000); | ||
|
|
||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches); | ||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, startingId); | ||
|
|
||
| if (token.totalMinted() > 0) { | ||
| uint256 validTokenId = bound(unboundedTokenId[0], 0, token.totalMinted() - 1); | ||
| uint256 validTokenId = bound(unboundedTokenId[0], startingId, startingId + token.totalMinted() - 1); | ||
| assertEq(token.ownerOf(validTokenId), receiver); | ||
| } | ||
|
|
||
| uint256 invalidTokenId = bound(unboundedTokenId[1], token.totalMinted(), type(uint256).max); | ||
| uint256 invalidTokenId = bound(unboundedTokenId[1], startingId + token.totalMinted(), startingId + token.totalMinted() + 1); | ||
| vm.expectRevert(); | ||
| token.ownerOf(invalidTokenId); | ||
| } | ||
|
|
||
| function test_burn(address receiver, uint256[] calldata batches, uint256 unboundedTokenId) public { | ||
| function test_burn(address receiver, uint256[] calldata batches, uint256 unboundedTokenId, uint96 startingId) public { | ||
| vm.assume(receiver != address(0)); | ||
| vm.assume(startingId < type(uint96).max - 5000); | ||
|
|
||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches); | ||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, startingId); | ||
|
|
||
| // only test if we minted at least one token | ||
| uint256 supply = token.totalMinted(); | ||
|
|
@@ -93,7 +102,7 @@ contract ERC721ConsecutiveTest is Test { | |
| batches[0] = bound(unboundedBatches[0], 1, 5000); | ||
| batches[1] = bound(unboundedBatches[1], 1, 5000); | ||
|
|
||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(receivers, batches); | ||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(receivers, batches, 0); | ||
|
|
||
| uint256 tokenId0 = bound(unboundedTokenId[0], 0, batches[0] - 1); | ||
| uint256 tokenId1 = bound(unboundedTokenId[1], 0, batches[1] - 1) + batches[0]; | ||
|
|
@@ -119,4 +128,28 @@ contract ERC721ConsecutiveTest is Test { | |
| assertEq(token.balanceOf(accounts[0]), batches[0]); | ||
| assertEq(token.balanceOf(accounts[1]), batches[1]); | ||
| } | ||
|
|
||
| function test_start_consecutive_id( | ||
| address receiver, | ||
| uint256[2] calldata unboundedBatches, | ||
| uint256[2] calldata unboundedTokenId, | ||
| uint96 startingId | ||
| ) public { | ||
| vm.assume(receiver != address(0)); | ||
| uint256 startingTokenId = bound(startingId, 1, 5000); | ||
|
|
||
| // We assume _maxBatchSize is 5000 (the default). This test will break otherwise. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this breaking? If it's breaking because of the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment about the breaking test is from a previous commit which I still can't decipher
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test tries to mint a batch that is too large. too large means bigger than
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, understood. Thanks for clarifying! |
||
| uint256[] memory batches = new uint256[](2); | ||
| batches[0] = bound(unboundedBatches[0], startingTokenId, 5000); | ||
| batches[1] = bound(unboundedBatches[1], startingTokenId, 5000); | ||
|
|
||
| ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, uint96(startingTokenId)); | ||
|
|
||
| uint256 tokenId0 = bound(unboundedTokenId[0], startingTokenId, batches[0]); | ||
| uint256 tokenId1 = bound(unboundedTokenId[1], startingTokenId, batches[1]); | ||
|
|
||
| assertEq(token.ownerOf(tokenId0), receiver); | ||
| assertEq(token.ownerOf(tokenId1), receiver); | ||
| assertEq(token.balanceOf(receiver), batches[0] + batches[1]); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think
0 to _firstConsecutiveId()should be accounted for the_totalConsecutiveSupply, it affects line 135, which will be excluding the after hook for real burnedtokenIdsFor example:
_firstConsecutiveId()with a5tokenIds from 5 to 9 (5 mints)2via normal minting_sequentialBurnon theownerOf(...)method, which is not what we wantI think this is what we should aim for:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make more sense for someone to consecutively mint token
10instead of2? I was thinking that there could be no minting below the first consecutive id.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would requiring that the tokenId be greater than the last batch minted one in the
_mintfunction be a viable option? It might be too inefficient...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is something we don't want, because it adds 2 (cold) sload to the mint operation, which we want to keep as cheap as possible.
Also, if we do that, it would be impossible to
_minta token that was first minted as part of a batch then burnt.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note that mint already check if the tokenId has an owner, and revert if that is the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, I'm still wrapping my head around the internals of this but I think I got it.