ERC721 optimised for sequential id and no burn
See original GitHub issueš§ Motivation
The high values for gas fees when minting has been a big issue. There have been some suggestions on how to lower these when using the ERC721
contract but then these are limited to the implementation of this same contract.
The ERC721
contract is rightfully a general implementation but thereās one case where it should be possible to considerably reduce the gas usage. I believe this is a very common case.
š Details
For the case when using sequential ids and thereās no support for burning tokens the following optimizations for ERC721
are possible:
_owners
can be an array instead of a mapping.
exists()
can just check if thetokenId
is smaller than_owners.length
mint()
can generate thetokenId
from the value of_owners.length
and_owners
can be updated by using_owners.push(to)
ERC721Enumerable
can also be optimized:
-
_allTokens
and_allTokensIndex
can be removed. -
totalSupply()
can return the_owners.length
fromERC721
exposed as an internal_totalSupply()
method.
tokenByIndex()
can simply return theindex
value
Conclusions
My tests show that gas usage for minting reduces from around 161k to around 101k. I believe this can be considered a significant improvement for a very common scenario.
Iād like to know your opinions and if I should consider submitting a PR.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:9 (7 by maintainers)
shameless advertisement for my generic subgraph
It indexes all ERC721 contracts on mainnet, and you can easily build equivalent instances for other chains using our @openzeppelin/subgraphs toolkit.
Hello @aalmada
There is a lot of discussion around the gas usage of ERC721 lately, and we appreciate the clarity of your approach. We understand that in very specific cases, our implementation is not the most gas effective. Sequential tokens minting with no burn is definitely one of these specific cases.
We care a lot about the versatility and backward compatibility of our codebase. For this reason, we donāt think it would be reasonable to deprecate our current proposal. AFAIK, nobody is asking for that anyway.
If we were to provide an implementation optimized for this specific case, we would be splitting our codebase, with unclear compatibility with ERC721 modules (voting being the last one). I donāt think this is optimal.
An opinion that we have shared, and that we will continue to share, is that ERC721Enumerable should not be used unless absolutely necessary. I have personally never seen any situation where it was actually needed. If you donāt include Enumerability, our (generic) implementation is as cheap as any other (that is focused on ābatch-mintingā) within the margin or error.
My answer to your issue would then be: