From e9f03bd211c414458bc0e5b8123f270ad119b052 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Fri, 30 Jun 2023 12:09:15 -0300 Subject: [PATCH 1/2] Exclude address(0) in ERC721._isApprovedOrOwner --- contracts/token/ERC721/ERC721.sol | 33 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index 4232c616e..fcaf04f2a 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -114,9 +114,6 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er */ function approve(address to, uint256 tokenId) public virtual { address owner = ownerOf(tokenId); - if (to == owner) { - revert ERC721InvalidOperator(owner); - } if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) { revert ERC721InvalidApprover(_msgSender()); @@ -131,7 +128,7 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er function getApproved(uint256 tokenId) public view virtual returns (address) { _requireMinted(tokenId); - return _tokenApprovals[tokenId]; + return _getApproved(tokenId); } /** @@ -220,16 +217,22 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er return _ownerOf(tokenId) != address(0); } + /** + * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted. + */ + function _getApproved(uint256 tokenId) internal view virtual returns (address) { + return _tokenApprovals[tokenId]; + } + /** * @dev Returns whether `spender` is allowed to manage `tokenId`. - * - * Requirements: - * - * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { - address owner = ownerOf(tokenId); - return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); + address owner = _ownerOf(tokenId); + return (owner != address(0) && + (spender == owner || + isApprovedForAll(owner, spender) || + (_getApproved(tokenId) == spender && spender != address(0)))); } /** @@ -386,8 +389,12 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { + address owner = ownerOf(tokenId); + if (to == owner || to == address(0)) { + revert ERC721InvalidOperator(to); + } _tokenApprovals[tokenId] = to; - emit Approval(ownerOf(tokenId), to, tokenId); + emit Approval(owner, to, tokenId); } /** @@ -396,8 +403,8 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { - if (owner == operator) { - revert ERC721InvalidOperator(owner); + if (operator == owner || operator == address(0)) { + revert ERC721InvalidOperator(operator); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); From de570d0d145ea0d594a40924b2edddf61e86d1cb Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Wed, 12 Jul 2023 13:42:46 +0200 Subject: [PATCH 2/2] allow using approve/_approve to clean approval --- contracts/token/ERC721/ERC721.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/token/ERC721/ERC721.sol b/contracts/token/ERC721/ERC721.sol index fcaf04f2a..fbeb3d641 100644 --- a/contracts/token/ERC721/ERC721.sol +++ b/contracts/token/ERC721/ERC721.sol @@ -114,9 +114,10 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er */ function approve(address to, uint256 tokenId) public virtual { address owner = ownerOf(tokenId); + address caller = _msgSender(); - if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) { - revert ERC721InvalidApprover(_msgSender()); + if (owner != caller && !isApprovedForAll(owner, caller)) { + revert ERC721InvalidApprover(caller); } _approve(to, tokenId); @@ -390,7 +391,7 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er */ function _approve(address to, uint256 tokenId) internal virtual { address owner = ownerOf(tokenId); - if (to == owner || to == address(0)) { + if (to == owner) { revert ERC721InvalidOperator(to); } _tokenApprovals[tokenId] = to;