-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Optimize ERC721 (depends on #1030) #1031
Conversation
759247c
to
d3634eb
Compare
uint256 lastToken = ownedTokens[_from][lastTokenIndex]; | ||
|
||
ownedTokens[_from][removeTokenIndex] = lastToken; | ||
ownedTokens[_from][lastTokenIndex] = 0; |
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.
As per #977 this line should be safe to remove and save a bit more gas.
|
||
if (tokenApprovals[_tokenId] != address(0)) { | ||
tokenApprovals[_tokenId] = address(0); | ||
emit Approval(owner, address(0), _tokenId); |
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.
This line should get removed too now that #1039 has been merged.
Huge fan of this PR. Really helps from a readability perspective and reduces the coupling on the burn/mint logic. Great work. |
6b4931c
to
6b2d11b
Compare
@johnhforrest I addressed your comments and rebased. Thanks for reviewing! |
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.
LGTM!
Why did you remove |
@mg6maciej I didn't want to leave in any unused functions just for the sake of using them in derived contracts. If you're asking why they were removed in the first place, see the PR description. The gist of it is that they are horribly inefficient. |
I wouldn't want to force users to understand the internals of ERC721 implementation to use it. If you try to derive from this class, you will quickly see, why it's better to have |
Why not just split these functions out into a separate contract? I think they are useful, but I just don't think they should be used internally within Happy to add this if it is a blocker. |
6b2d11b
to
2db5bce
Compare
Hello @abandeali1, thank you for your contribution! I dug a bit deeper into what was causing the increased gas cost (since it seemed too high for it to come from just a couple extra This can be more easily fixed by adding a function to handle the special case of transferring (since Because that's a less disruptive change (we do want |
This PR depends on #1030 (happy to drop that commit if it's an issue).
🚀 Description
There are a ton of redundant checks and state reads in the current ERC721 implementations. I'm assuming that a lot of this is because everything is broken up into multiple function calls. Even though they read from a lot of the same state, the optimizer has trouble combining the SLOADs because they are occurring in different scopes.
By flattening all of the function calls in
transferFrom
, quick tests show that we save a whopping ~8000 gas per transfer (this is in addition to the ~2000 gas saved by dropping the modifiers in #1030).IMO, flattening the functions also makes actual token contracts more readable, as we are able to drop a lot of unused functions. The downside is that there is now a lot of redundant code in the mock contracts, but I think the tradeoff is massively worth it.
npm run lint:all:fix
).