ERC1155Utils.sol 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. library ERC1155Utils {
  11. /**
  12. * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155-onERC1155Received}
  13. * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
  14. *
  15. * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
  16. * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
  17. * the transfer.
  18. */
  19. function checkOnERC1155Received(
  20. address operator,
  21. address from,
  22. address to,
  23. uint256 id,
  24. uint256 value,
  25. bytes memory data
  26. ) internal {
  27. if (to.code.length > 0) {
  28. try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {
  29. if (response != IERC1155Receiver.onERC1155Received.selector) {
  30. // Tokens rejected
  31. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  32. }
  33. } catch (bytes memory reason) {
  34. if (reason.length == 0) {
  35. // non-IERC1155Receiver implementer
  36. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  37. } else {
  38. assembly ("memory-safe") {
  39. revert(add(32, reason), mload(reason))
  40. }
  41. }
  42. }
  43. }
  44. }
  45. /**
  46. * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155-onERC1155BatchReceived}
  47. * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
  48. *
  49. * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
  50. * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept
  51. * the transfer.
  52. */
  53. function checkOnERC1155BatchReceived(
  54. address operator,
  55. address from,
  56. address to,
  57. uint256[] memory ids,
  58. uint256[] memory values,
  59. bytes memory data
  60. ) internal {
  61. if (to.code.length > 0) {
  62. try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (
  63. bytes4 response
  64. ) {
  65. if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {
  66. // Tokens rejected
  67. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  68. }
  69. } catch (bytes memory reason) {
  70. if (reason.length == 0) {
  71. // non-IERC1155Receiver implementer
  72. revert IERC1155Errors.ERC1155InvalidReceiver(to);
  73. } else {
  74. assembly ("memory-safe") {
  75. revert(add(32, reason), mload(reason))
  76. }
  77. }
  78. }
  79. }
  80. }
  81. }