ERC721.sol 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)
  3. pragma solidity ^0.8.20;
  4. import {IERC721} from "./IERC721.sol";
  5. import {IERC721Receiver} from "./IERC721Receiver.sol";
  6. import {IERC721Metadata} from "./extensions/IERC721Metadata.sol";
  7. import {Context} from "../../utils/Context.sol";
  8. import {Strings} from "../../utils/Strings.sol";
  9. import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
  10. import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol";
  11. /**
  12. * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
  13. * the Metadata extension, but not including the Enumerable extension, which is available separately as
  14. * {ERC721Enumerable}.
  15. */
  16. abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
  17. using Strings for uint256;
  18. // Token name
  19. string private _name;
  20. // Token symbol
  21. string private _symbol;
  22. mapping(uint256 tokenId => address) private _owners;
  23. mapping(address owner => uint256) private _balances;
  24. mapping(uint256 tokenId => address) private _tokenApprovals;
  25. mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
  26. /**
  27. * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
  28. */
  29. constructor(string memory name_, string memory symbol_) {
  30. _name = name_;
  31. _symbol = symbol_;
  32. }
  33. /**
  34. * @dev See {IERC165-supportsInterface}.
  35. */
  36. function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
  37. return
  38. interfaceId == type(IERC721).interfaceId ||
  39. interfaceId == type(IERC721Metadata).interfaceId ||
  40. super.supportsInterface(interfaceId);
  41. }
  42. /**
  43. * @dev See {IERC721-balanceOf}.
  44. */
  45. function balanceOf(address owner) public view virtual returns (uint256) {
  46. if (owner == address(0)) {
  47. revert ERC721InvalidOwner(address(0));
  48. }
  49. return _balances[owner];
  50. }
  51. /**
  52. * @dev See {IERC721-ownerOf}.
  53. */
  54. function ownerOf(uint256 tokenId) public view virtual returns (address) {
  55. address owner = _ownerOf(tokenId);
  56. if (owner == address(0)) {
  57. revert ERC721NonexistentToken(tokenId);
  58. }
  59. return owner;
  60. }
  61. /**
  62. * @dev See {IERC721Metadata-name}.
  63. */
  64. function name() public view virtual returns (string memory) {
  65. return _name;
  66. }
  67. /**
  68. * @dev See {IERC721Metadata-symbol}.
  69. */
  70. function symbol() public view virtual returns (string memory) {
  71. return _symbol;
  72. }
  73. /**
  74. * @dev See {IERC721Metadata-tokenURI}.
  75. */
  76. function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
  77. _requireMinted(tokenId);
  78. string memory baseURI = _baseURI();
  79. return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
  80. }
  81. /**
  82. * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
  83. * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
  84. * by default, can be overridden in child contracts.
  85. */
  86. function _baseURI() internal view virtual returns (string memory) {
  87. return "";
  88. }
  89. /**
  90. * @dev See {IERC721-approve}.
  91. */
  92. function approve(address to, uint256 tokenId) public virtual {
  93. address owner = ownerOf(tokenId);
  94. if (to == owner) {
  95. revert ERC721InvalidOperator(owner);
  96. }
  97. if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) {
  98. revert ERC721InvalidApprover(_msgSender());
  99. }
  100. _approve(to, tokenId);
  101. }
  102. /**
  103. * @dev See {IERC721-getApproved}.
  104. */
  105. function getApproved(uint256 tokenId) public view virtual returns (address) {
  106. _requireMinted(tokenId);
  107. return _tokenApprovals[tokenId];
  108. }
  109. /**
  110. * @dev See {IERC721-setApprovalForAll}.
  111. */
  112. function setApprovalForAll(address operator, bool approved) public virtual {
  113. _setApprovalForAll(_msgSender(), operator, approved);
  114. }
  115. /**
  116. * @dev See {IERC721-isApprovedForAll}.
  117. */
  118. function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
  119. return _operatorApprovals[owner][operator];
  120. }
  121. /**
  122. * @dev See {IERC721-transferFrom}.
  123. */
  124. function transferFrom(address from, address to, uint256 tokenId) public virtual {
  125. if (!_isApprovedOrOwner(_msgSender(), tokenId)) {
  126. revert ERC721InsufficientApproval(_msgSender(), tokenId);
  127. }
  128. _transfer(from, to, tokenId);
  129. }
  130. /**
  131. * @dev See {IERC721-safeTransferFrom}.
  132. */
  133. function safeTransferFrom(address from, address to, uint256 tokenId) public virtual {
  134. safeTransferFrom(from, to, tokenId, "");
  135. }
  136. /**
  137. * @dev See {IERC721-safeTransferFrom}.
  138. */
  139. function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
  140. if (!_isApprovedOrOwner(_msgSender(), tokenId)) {
  141. revert ERC721InsufficientApproval(_msgSender(), tokenId);
  142. }
  143. _safeTransfer(from, to, tokenId, data);
  144. }
  145. /**
  146. * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
  147. * are aware of the ERC721 protocol to prevent tokens from being forever locked.
  148. *
  149. * `data` is additional data, it has no specified format and it is sent in call to `to`.
  150. *
  151. * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
  152. * implement alternative mechanisms to perform token transfer, such as signature-based.
  153. *
  154. * Requirements:
  155. *
  156. * - `from` cannot be the zero address.
  157. * - `to` cannot be the zero address.
  158. * - `tokenId` token must exist and be owned by `from`.
  159. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
  160. *
  161. * Emits a {Transfer} event.
  162. */
  163. function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
  164. _transfer(from, to, tokenId);
  165. if (!_checkOnERC721Received(from, to, tokenId, data)) {
  166. revert ERC721InvalidReceiver(to);
  167. }
  168. }
  169. /**
  170. * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
  171. */
  172. function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
  173. return _owners[tokenId];
  174. }
  175. /**
  176. * @dev Returns whether `tokenId` exists.
  177. *
  178. * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
  179. *
  180. * Tokens start existing when they are minted (`_mint`),
  181. * and stop existing when they are burned (`_burn`).
  182. */
  183. function _exists(uint256 tokenId) internal view virtual returns (bool) {
  184. return _ownerOf(tokenId) != address(0);
  185. }
  186. /**
  187. * @dev Returns whether `spender` is allowed to manage `tokenId`.
  188. *
  189. * Requirements:
  190. *
  191. * - `tokenId` must exist.
  192. */
  193. function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
  194. address owner = ownerOf(tokenId);
  195. return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
  196. }
  197. /**
  198. * @dev Safely mints `tokenId` and transfers it to `to`.
  199. *
  200. * Requirements:
  201. *
  202. * - `tokenId` must not exist.
  203. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
  204. *
  205. * Emits a {Transfer} event.
  206. */
  207. function _safeMint(address to, uint256 tokenId) internal virtual {
  208. _safeMint(to, tokenId, "");
  209. }
  210. /**
  211. * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
  212. * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
  213. */
  214. function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
  215. _mint(to, tokenId);
  216. if (!_checkOnERC721Received(address(0), to, tokenId, data)) {
  217. revert ERC721InvalidReceiver(to);
  218. }
  219. }
  220. /**
  221. * @dev Mints `tokenId` and transfers it to `to`.
  222. *
  223. * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
  224. *
  225. * Requirements:
  226. *
  227. * - `tokenId` must not exist.
  228. * - `to` cannot be the zero address.
  229. *
  230. * Emits a {Transfer} event.
  231. */
  232. function _mint(address to, uint256 tokenId) internal virtual {
  233. if (to == address(0)) {
  234. revert ERC721InvalidReceiver(address(0));
  235. }
  236. if (_exists(tokenId)) {
  237. revert ERC721InvalidSender(address(0));
  238. }
  239. _beforeTokenTransfer(address(0), to, tokenId, 1);
  240. // Check that tokenId was not minted by `_beforeTokenTransfer` hook
  241. if (_exists(tokenId)) {
  242. revert ERC721InvalidSender(address(0));
  243. }
  244. unchecked {
  245. // Will not overflow unless all 2**256 token ids are minted to the same owner.
  246. // Given that tokens are minted one by one, it is impossible in practice that
  247. // this ever happens. Might change if we allow batch minting.
  248. // The ERC fails to describe this case.
  249. _balances[to] += 1;
  250. }
  251. _owners[tokenId] = to;
  252. emit Transfer(address(0), to, tokenId);
  253. _afterTokenTransfer(address(0), to, tokenId, 1);
  254. }
  255. /**
  256. * @dev Destroys `tokenId`.
  257. * The approval is cleared when the token is burned.
  258. * This is an internal function that does not check if the sender is authorized to operate on the token.
  259. *
  260. * Requirements:
  261. *
  262. * - `tokenId` must exist.
  263. *
  264. * Emits a {Transfer} event.
  265. */
  266. function _burn(uint256 tokenId) internal virtual {
  267. address owner = ownerOf(tokenId);
  268. _beforeTokenTransfer(owner, address(0), tokenId, 1);
  269. // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
  270. owner = ownerOf(tokenId);
  271. // Clear approvals
  272. delete _tokenApprovals[tokenId];
  273. // Decrease balance with checked arithmetic, because an `ownerOf` override may
  274. // invalidate the assumption that `_balances[from] >= 1`.
  275. _balances[owner] -= 1;
  276. delete _owners[tokenId];
  277. emit Transfer(owner, address(0), tokenId);
  278. _afterTokenTransfer(owner, address(0), tokenId, 1);
  279. }
  280. /**
  281. * @dev Transfers `tokenId` from `from` to `to`.
  282. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
  283. *
  284. * Requirements:
  285. *
  286. * - `to` cannot be the zero address.
  287. * - `tokenId` token must be owned by `from`.
  288. *
  289. * Emits a {Transfer} event.
  290. */
  291. function _transfer(address from, address to, uint256 tokenId) internal virtual {
  292. address owner = ownerOf(tokenId);
  293. if (owner != from) {
  294. revert ERC721IncorrectOwner(from, tokenId, owner);
  295. }
  296. if (to == address(0)) {
  297. revert ERC721InvalidReceiver(address(0));
  298. }
  299. _beforeTokenTransfer(from, to, tokenId, 1);
  300. // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
  301. owner = ownerOf(tokenId);
  302. if (owner != from) {
  303. revert ERC721IncorrectOwner(from, tokenId, owner);
  304. }
  305. // Clear approvals from the previous owner
  306. delete _tokenApprovals[tokenId];
  307. // Decrease balance with checked arithmetic, because an `ownerOf` override may
  308. // invalidate the assumption that `_balances[from] >= 1`.
  309. _balances[from] -= 1;
  310. unchecked {
  311. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
  312. // all 2**256 token ids to be minted, which in practice is impossible.
  313. _balances[to] += 1;
  314. }
  315. _owners[tokenId] = to;
  316. emit Transfer(from, to, tokenId);
  317. _afterTokenTransfer(from, to, tokenId, 1);
  318. }
  319. /**
  320. * @dev Approve `to` to operate on `tokenId`
  321. *
  322. * Emits an {Approval} event.
  323. */
  324. function _approve(address to, uint256 tokenId) internal virtual {
  325. _tokenApprovals[tokenId] = to;
  326. emit Approval(ownerOf(tokenId), to, tokenId);
  327. }
  328. /**
  329. * @dev Approve `operator` to operate on all of `owner` tokens
  330. *
  331. * Emits an {ApprovalForAll} event.
  332. */
  333. function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
  334. if (owner == operator) {
  335. revert ERC721InvalidOperator(owner);
  336. }
  337. _operatorApprovals[owner][operator] = approved;
  338. emit ApprovalForAll(owner, operator, approved);
  339. }
  340. /**
  341. * @dev Reverts if the `tokenId` has not been minted yet.
  342. */
  343. function _requireMinted(uint256 tokenId) internal view virtual {
  344. if (!_exists(tokenId)) {
  345. revert ERC721NonexistentToken(tokenId);
  346. }
  347. }
  348. /**
  349. * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address.
  350. * The call is not executed if the target address is not a contract.
  351. *
  352. * @param from address representing the previous owner of the given token ID
  353. * @param to target address that will receive the tokens
  354. * @param tokenId uint256 ID of the token to be transferred
  355. * @param data bytes optional data to send along with the call
  356. * @return bool whether the call correctly returned the expected magic value
  357. */
  358. function _checkOnERC721Received(
  359. address from,
  360. address to,
  361. uint256 tokenId,
  362. bytes memory data
  363. ) private returns (bool) {
  364. if (to.code.length > 0) {
  365. try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
  366. return retval == IERC721Receiver.onERC721Received.selector;
  367. } catch (bytes memory reason) {
  368. if (reason.length == 0) {
  369. revert ERC721InvalidReceiver(to);
  370. } else {
  371. /// @solidity memory-safe-assembly
  372. assembly {
  373. revert(add(32, reason), mload(reason))
  374. }
  375. }
  376. }
  377. } else {
  378. return true;
  379. }
  380. }
  381. /**
  382. * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
  383. * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
  384. *
  385. * Calling conditions:
  386. *
  387. * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
  388. * - When `from` is zero, the tokens will be minted for `to`.
  389. * - When `to` is zero, ``from``'s tokens will be burned.
  390. * - `from` and `to` are never both zero.
  391. * - `batchSize` is non-zero.
  392. *
  393. * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
  394. */
  395. function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
  396. /**
  397. * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
  398. * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
  399. *
  400. * Calling conditions:
  401. *
  402. * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
  403. * - When `from` is zero, the tokens were minted for `to`.
  404. * - When `to` is zero, ``from``'s tokens were burned.
  405. * - `from` and `to` are never both zero.
  406. * - `batchSize` is non-zero.
  407. *
  408. * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
  409. */
  410. function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}
  411. /**
  412. * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
  413. *
  414. * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
  415. * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
  416. * that `ownerOf(tokenId)` is `a`.
  417. */
  418. // solhint-disable-next-line func-name-mixedcase
  419. function __unsafe_increaseBalance(address account, uint256 value) internal {
  420. _balances[account] += value;
  421. }
  422. }