ERC1155Utils.sol 3.4 KB

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