@@ -108,7 +108,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
108
108
* @dev See {IERC721-approve}.
109
109
*/
110
110
function approve (address to , uint256 tokenId ) public virtual override {
111
- address owner = ERC721 . ownerOf (tokenId);
111
+ address owner = ownerOf (tokenId);
112
112
require (to != owner, "ERC721: approval to current owner " );
113
113
114
114
require (
@@ -217,7 +217,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
217
217
* - `tokenId` must exist.
218
218
*/
219
219
function _isApprovedOrOwner (address spender , uint256 tokenId ) internal view virtual returns (bool ) {
220
- address owner = ERC721 . ownerOf (tokenId);
220
+ address owner = ownerOf (tokenId);
221
221
return (spender == owner || isApprovedForAll (owner, spender) || getApproved (tokenId) == spender);
222
222
}
223
223
@@ -295,21 +295,20 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
295
295
* Emits a {Transfer} event.
296
296
*/
297
297
function _burn (uint256 tokenId ) internal virtual {
298
- address owner = ERC721 . ownerOf (tokenId);
298
+ address owner = ownerOf (tokenId);
299
299
300
300
_beforeTokenTransfer (owner, address (0 ), tokenId, 1 );
301
301
302
302
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
303
- owner = ERC721 . ownerOf (tokenId);
303
+ owner = ownerOf (tokenId);
304
304
305
305
// Clear approvals
306
306
delete _tokenApprovals[tokenId];
307
307
308
- unchecked {
309
- // Cannot overflow, as that would require more tokens to be burned/transferred
310
- // out than the owner initially received through minting and transferring in.
311
- _balances[owner] -= 1 ;
312
- }
308
+ // Decrease balance with checked arithmetic, because an `ownerOf` override may
309
+ // invalidate the assumption that `_balances[from] >= 1`.
310
+ _balances[owner] -= 1 ;
311
+
313
312
delete _owners[tokenId];
314
313
315
314
emit Transfer (owner, address (0 ), tokenId);
@@ -329,26 +328,27 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
329
328
* Emits a {Transfer} event.
330
329
*/
331
330
function _transfer (address from , address to , uint256 tokenId ) internal virtual {
332
- require (ERC721 . ownerOf (tokenId) == from, "ERC721: transfer from incorrect owner " );
331
+ require (ownerOf (tokenId) == from, "ERC721: transfer from incorrect owner " );
333
332
require (to != address (0 ), "ERC721: transfer to the zero address " );
334
333
335
334
_beforeTokenTransfer (from, to, tokenId, 1 );
336
335
337
336
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
338
- require (ERC721 . ownerOf (tokenId) == from, "ERC721: transfer from incorrect owner " );
337
+ require (ownerOf (tokenId) == from, "ERC721: transfer from incorrect owner " );
339
338
340
339
// Clear approvals from the previous owner
341
340
delete _tokenApprovals[tokenId];
342
341
342
+ // Decrease balance with checked arithmetic, because an `ownerOf` override may
343
+ // invalidate the assumption that `_balances[from] >= 1`.
344
+ _balances[from] -= 1 ;
345
+
343
346
unchecked {
344
- // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
345
- // `from`'s balance is the number of token held, which is at least one before the current
346
- // transfer.
347
347
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
348
348
// all 2**256 token ids to be minted, which in practice is impossible.
349
- _balances[from] -= 1 ;
350
349
_balances[to] += 1 ;
351
350
}
351
+
352
352
_owners[tokenId] = to;
353
353
354
354
emit Transfer (from, to, tokenId);
@@ -363,7 +363,7 @@ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
363
363
*/
364
364
function _approve (address to , uint256 tokenId ) internal virtual {
365
365
_tokenApprovals[tokenId] = to;
366
- emit Approval (ERC721 . ownerOf (tokenId), to, tokenId);
366
+ emit Approval (ownerOf (tokenId), to, tokenId);
367
367
}
368
368
369
369
/**
0 commit comments