diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c2edb59785..06409f694c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ * `Address`: optimize `functionCall` functions by checking contract size only if there is no returned data. ([#3469](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3469)) * `GovernorCompatibilityBravo`: remove unused `using` statements ([#3506](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3506)) * `ERC20`: optimize `_transfer`, `_mint` and `_burn` by using `unchecked` arithmetic when possible. ([#3513](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3513)) + * `ERC721`: optimize transfers by making approval clearing implicit instead of emitting an event. ([#3481](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3481)) + +### Compatibility Note + +ERC-721 integrators that interpret contract state from events should make sure that they implement the clearing of approval that is implicit in every transfer according to the EIP. Previous versions of OpenZeppellin Contracts emitted an explicit `Approval` event even though it was not required by the specification, and this is no longer the case. ## 4.7.0 (2022-06-29) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 0a33e88841c..473e1d43ccc 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -338,7 +338,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner - _approve(address(0), tokenId); + delete _tokenApprovals[tokenId]; _balances[from] -= 1; _balances[to] += 1; diff --git a/test/token/ERC721/ERC721.behavior.js b/test/token/ERC721/ERC721.behavior.js index d6aa4e6b919..b0893bc5330 100644 --- a/test/token/ERC721/ERC721.behavior.js +++ b/test/token/ERC721/ERC721.behavior.js @@ -96,10 +96,6 @@ function shouldBehaveLikeERC721 (errorPrefix, owner, newOwner, approved, another expect(await this.token.getApproved(tokenId)).to.be.equal(ZERO_ADDRESS); }); - it('emits an Approval event', async function () { - expectEvent(receipt, 'Approval', { owner, approved: ZERO_ADDRESS, tokenId: tokenId }); - }); - it('adjusts owners balances', async function () { expect(await this.token.balanceOf(owner)).to.be.bignumber.equal('1'); });