// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IERC1363Receiver} from "../../../interfaces/IERC1363Receiver.sol"; import {IERC1363Spender} from "../../../interfaces/IERC1363Spender.sol"; /** * @dev Library that provides common ERC-1363 utility functions. * * See https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. */ library ERC1363Utils { /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1363InvalidReceiver(address receiver); /** * @dev Indicates a failure with the token `spender`. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC1363InvalidSpender(address spender); /** * @dev Performs a call to {IERC1363Receiver-onTransferReceived} on a target address. * * Requirements: * * - The target has code (i.e. is a contract). * - The target `to` must implement the {IERC1363Receiver} interface. * - The target must return the {IERC1363Receiver-onTransferReceived} selector to accept the transfer. */ function checkOnERC1363TransferReceived( address operator, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { revert ERC1363InvalidReceiver(to); } try IERC1363Receiver(to).onTransferReceived(operator, from, value, data) returns (bytes4 retval) { if (retval != IERC1363Receiver.onTransferReceived.selector) { revert ERC1363InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { revert ERC1363InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } /** * @dev Performs a call to {IERC1363Spender-onApprovalReceived} on a target address. * * Requirements: * * - The target has code (i.e. is a contract). * - The target `spender` must implement the {IERC1363Spender} interface. * - The target must return the {IERC1363Spender-onApprovalReceived} selector to accept the approval. */ function checkOnERC1363ApprovalReceived( address operator, address spender, uint256 value, bytes memory data ) internal { if (spender.code.length == 0) { revert ERC1363InvalidSpender(spender); } try IERC1363Spender(spender).onApprovalReceived(operator, value, data) returns (bytes4 retval) { if (retval != IERC1363Spender.onApprovalReceived.selector) { revert ERC1363InvalidSpender(spender); } } catch (bytes memory reason) { if (reason.length == 0) { revert ERC1363InvalidSpender(spender); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } }