question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ERC721: transferFrom with ApproveForAll emits event Approval

See original GitHub issue

When users sets approve for all his tokens, and then some operators call transferFrom for some specific token, than Approval event is emitted. According to ERC-721 standard Approval event should not be emitted, because approve state was not changed for specific token.

    /// @dev This emits when the approved address for an NFT is ***changed*** or
    ///  reaffirmed. The zero address indicates there is no approved address.
    ///  When a Transfer event emits, this also indicates that the approved
    ///  address for that NFT (if any) is reset to none.
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

I offer to change ERC721.sol function

    function _approve(address to, uint256 tokenId) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner
    }

to

    function _approve(address to, uint256 tokenId) private {
        if (_tokenApprovals[tokenId] != to) {
            _tokenApprovals[tokenId] = to;
            emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner
        }
    }

This will save gas on emitting and storing approve state.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
Amxxcommented, Jun 8, 2021

Coming back to @kindex

First of all, thank you for your issue. It really got us thinking and re-reading the ERC multiple time. We come to agree that the ERC is not clear, and that your comment is really pushing our interpretation of it.

Our analysis is:

  • If someone calls approve(...) external multiple times, we should be emitting the event multiple times
  • If _transfer is called, regardless of how it was called (safe/unsafe/by operator), we should reset the approval to 0. It is not clear if an Approval event should be emitted on top of the Transfer event (this is really unclear)

Your proposal would improve gas usage, but it would also break the first bullet point. It might be possible to improve event emission without breaking this, but it would require a non-trivial change of the codebase, for example changing the parameters of the internal _approve. This would be a breaking change for people building on top of this contract.

While we do care about gas costs, the complexity and the backward compatibility of the codebase are also very important, and we feel like it might not make sense to change things right now.

0reactions
fulldecentcommented, Jul 30, 2021

I agree that “this” in the following statement is unclear.

When a Transfer event emits, this also indicates that the approved address for that NFT (if any) is reset to none.

Sorry, my bad.

Read more comments on GitHub >

github_iconTop Results From Across the Web

HIP-376: Support Approve/Allowance/transferFrom standard ...
Standard ERC-721 Events will be emitted as appropriate. function approve(address to, uint256 tokenId) external;. Gives permission to to to transfer tokenId ...
Read more >
ERC721 unnecessarily emits an `Approval` event on transfers
ERC20 doesn't emit an Approval event every time transferFrom is called either.
Read more >
ERC 721 - OpenZeppelin Docs
ERC 721. This set of interfaces, contracts, and utilities are all related to the ... Events. Transfer(from, to, tokenId). Approval(owner, approved, tokenId).
Read more >
Deciphering ERC721 Token Standard & Fungibility of assets ...
This event is emitted whenever the ownership of any NFT is changed from on address to another. 2. Approval Event. event Approval(address indexed ......
Read more >
ERC721 Token Transfers and Approvals
To summarize : approve(address to, uint256 tokenId) : By calling this method, the sender authorizes the address to to transfer one of his ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found