remove _isApproedOrOwner in favor of _isApproved + refactor _checkOnERC721Received

This commit is contained in:
Hadrien Croubois
2023-07-12 10:01:30 +02:00
parent 7e9d024d08
commit 16f2f15673
2 changed files with 33 additions and 39 deletions

View File

@ -36,10 +36,7 @@ contract ERC721ConsecutiveEnumerableMock is ERC721Consecutive, ERC721Enumerable
return super._update(to, tokenId, operatorCheck); return super._update(to, tokenId, operatorCheck);
} }
function _increaseBalance( function _increaseBalance(address account, uint256 amount) internal virtual override(ERC721, ERC721Enumerable) {
address account,
uint256 amount
) internal virtual override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, amount); super._increaseBalance(account, amount);
} }
} }

View File

@ -175,9 +175,7 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er
*/ */
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual { function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId); transferFrom(from, to, tokenId);
if (!_checkOnERC721Received(from, to, tokenId, data)) { _checkOnERC721Received(from, to, tokenId, data);
revert ERC721InvalidReceiver(to);
}
} }
/** /**
@ -200,15 +198,28 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er
} }
/** /**
* @dev Returns whether `spender` is allowed to manage `tokenId`. * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
* *
* Requirements: * WARNING:
* * - ownership is not checked.
* - `tokenId` must exist. * - spender = address(0) will lead to this function returning true in unexpected situations.
*/ */
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { function _isApproved(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ownerOf(tokenId); return owner == spender || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender;
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); }
/**
* @dev Checks whether `spender` was approved by `owner` to operate on `tokenId` or is the owner of `tokenId`.
* Reverts if `spender` is not approved nor owner of `tokenId`.
*
* WARNING:
* - ownership is not checked.
*/
function _checkApproved(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isApproved(owner, spender, tokenId)) {
revert ERC721InsufficientApproval(spender, tokenId);
}
} }
/** /**
@ -220,16 +231,12 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er
* *
* Emits a {Transfer} event. * Emits a {Transfer} event.
*/ */
function _update( function _update(address to, uint256 tokenId, address operatorCheck) internal virtual returns (address) {
address to,
uint256 tokenId,
address operatorCheck
) internal virtual returns (address) {
address from = _ownerOf(tokenId); address from = _ownerOf(tokenId);
// Perform (optional) operator check // Perform (optional) operator check
if (operatorCheck != address(0) && from != operatorCheck && !isApprovedForAll(from, operatorCheck) && getApproved(tokenId) != operatorCheck) { if (operatorCheck != address(0)) {
revert ERC721InsufficientApproval(operatorCheck, tokenId); _checkApproved(from, operatorCheck, tokenId);
} }
// Execute the update // Execute the update
@ -295,9 +302,7 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er
*/ */
function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId); _mint(to, tokenId);
if (!_checkOnERC721Received(address(0), to, tokenId, data)) { _checkOnERC721Received(address(0), to, tokenId, data);
revert ERC721InvalidReceiver(to);
}
} }
/** /**
@ -361,9 +366,7 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er
*/ */
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId); _transfer(from, to, tokenId);
if (!_checkOnERC721Received(from, to, tokenId, data)) { _checkOnERC721Received(from, to, tokenId, data);
revert ERC721InvalidReceiver(to);
}
} }
/** /**
@ -399,24 +402,20 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er
} }
/** /**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
* The call is not executed if the target address is not a contract. * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.
* *
* @param from address representing the previous owner of the given token ID * @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens * @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred * @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call * @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/ */
function _checkOnERC721Received( function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.code.length > 0) { if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector; if (retval != IERC721Receiver.onERC721Received.selector) {
revert ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) { } catch (bytes memory reason) {
if (reason.length == 0) { if (reason.length == 0) {
revert ERC721InvalidReceiver(to); revert ERC721InvalidReceiver(to);
@ -427,8 +426,6 @@ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Er
} }
} }
} }
} else {
return true;
} }
} }