ERC721Utils.sol 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.1.0-rc.0) (token/ERC721/utils/ERC721Utils.sol)
  3. pragma solidity ^0.8.20;
  4. import {IERC721Receiver} from "../IERC721Receiver.sol";
  5. import {IERC721Errors} from "../../../interfaces/draft-IERC6093.sol";
  6. /**
  7. * @dev Library that provide common ERC-721 utility functions.
  8. *
  9. * See https://eips.ethereum.org/EIPS/eip-721[ERC-721].
  10. *
  11. * _Available since v5.1._
  12. */
  13. library ERC721Utils {
  14. /**
  15. * @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}
  16. * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
  17. *
  18. * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
  19. * Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept
  20. * the transfer.
  21. */
  22. function checkOnERC721Received(
  23. address operator,
  24. address from,
  25. address to,
  26. uint256 tokenId,
  27. bytes memory data
  28. ) internal {
  29. if (to.code.length > 0) {
  30. try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {
  31. if (retval != IERC721Receiver.onERC721Received.selector) {
  32. // Token rejected
  33. revert IERC721Errors.ERC721InvalidReceiver(to);
  34. }
  35. } catch (bytes memory reason) {
  36. if (reason.length == 0) {
  37. // non-IERC721Receiver implementer
  38. revert IERC721Errors.ERC721InvalidReceiver(to);
  39. } else {
  40. assembly ("memory-safe") {
  41. revert(add(32, reason), mload(reason))
  42. }
  43. }
  44. }
  45. }
  46. }
  47. }