ERC1155Utils.sol 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.1.0-rc.0) (token/ERC1155/utils/ERC1155Utils.sol)
  3. pragma solidity ^0.8.20;
  4. import {IERC1155Receiver} from "../IERC1155Receiver.sol";
  5. import {IERC1155Errors} from "../../../interfaces/draft-IERC6093.sol";
  6. /**
  7. * @dev Library that provide common ERC-1155 utility functions.
  8. *
  9. * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].
  10. *
  11. * _Available since v5.1._
  12. */
  13. library ERC1155Utils {
  14. /**
  15. * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155-onERC1155Received}
  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 {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
  20. * the transfer.
  21. */
  22. function checkOnERC1155Received(
  23. address operator,
  24. address from,
  25. address to,
  26. uint256 id,
  27. uint256 value,
  28. bytes memory data
  29. ) internal {
  30. if (to.code.length > 0) {
  31. try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
  32. if (response != IERC1155Receiver.onERC1155Received.selector) {
  33. // Tokens rejected
  34. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  35. }
  36. } catch (bytes memory reason) {
  37. if (reason.length == 0) {
  38. // non-IERC1155Receiver implementer
  39. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  40. } else {
  41. assembly ("memory-safe") {
  42. revert(add(32, reason), mload(reason))
  43. }
  44. }
  45. }
  46. }
  47. }
  48. /**
  49. * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155-onERC1155BatchReceived}
  50. * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
  51. *
  52. * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
  53. * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
  54. * the transfer.
  55. */
  56. function checkOnERC1155BatchReceived(
  57. address operator,
  58. address from,
  59. address to,
  60. uint256[] memory ids,
  61. uint256[] memory values,
  62. bytes memory data
  63. ) internal {
  64. if (to.code.length > 0) {
  65. try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (
  66. bytes4 response
  67. ) {
  68. if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
  69. // Tokens rejected
  70. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  71. }
  72. } catch (bytes memory reason) {
  73. if (reason.length == 0) {
  74. // non-IERC1155Receiver implementer
  75. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  76. } else {
  77. assembly ("memory-safe") {
  78. revert(add(32, reason), mload(reason))
  79. }
  80. }
  81. }
  82. }
  83. }
  84. }