ERC1363.sol 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.2.0-rc.0) (token/ERC20/extensions/ERC1363.sol)
  3. pragma solidity ^0.8.20;
  4. import {ERC20} from "../ERC20.sol";
  5. import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
  6. import {IERC1363} from "../../../interfaces/IERC1363.sol";
  7. import {ERC1363Utils} from "../utils/ERC1363Utils.sol";
  8. /**
  9. * @title ERC1363
  10. * @dev Extension of {ERC20} tokens that adds support for code execution after transfers and approvals
  11. * on recipient contracts. Calls after transfers are enabled through the {ERC1363-transferAndCall} and
  12. * {ERC1363-transferFromAndCall} methods while calls after approvals can be made with {ERC1363-approveAndCall}
  13. *
  14. * _Available since v5.1._
  15. */
  16. abstract contract ERC1363 is ERC20, ERC165, IERC1363 {
  17. /**
  18. * @dev Indicates a failure within the {transfer} part of a transferAndCall operation.
  19. * @param receiver Address to which tokens are being transferred.
  20. * @param value Amount of tokens to be transferred.
  21. */
  22. error ERC1363TransferFailed(address receiver, uint256 value);
  23. /**
  24. * @dev Indicates a failure within the {transferFrom} part of a transferFromAndCall operation.
  25. * @param sender Address from which to send tokens.
  26. * @param receiver Address to which tokens are being transferred.
  27. * @param value Amount of tokens to be transferred.
  28. */
  29. error ERC1363TransferFromFailed(address sender, address receiver, uint256 value);
  30. /**
  31. * @dev Indicates a failure within the {approve} part of a approveAndCall operation.
  32. * @param spender Address which will spend the funds.
  33. * @param value Amount of tokens to be spent.
  34. */
  35. error ERC1363ApproveFailed(address spender, uint256 value);
  36. /**
  37. * @inheritdoc IERC165
  38. */
  39. function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
  40. return interfaceId == type(IERC1363).interfaceId || super.supportsInterface(interfaceId);
  41. }
  42. /**
  43. * @dev Moves a `value` amount of tokens from the caller's account to `to`
  44. * and then calls {IERC1363Receiver-onTransferReceived} on `to`. Returns a flag that indicates
  45. * if the call succeeded.
  46. *
  47. * Requirements:
  48. *
  49. * - The target has code (i.e. is a contract).
  50. * - The target `to` must implement the {IERC1363Receiver} interface.
  51. * - The target must return the {IERC1363Receiver-onTransferReceived} selector to accept the transfer.
  52. * - The internal {transfer} must succeed (returned `true`).
  53. */
  54. function transferAndCall(address to, uint256 value) public returns (bool) {
  55. return transferAndCall(to, value, "");
  56. }
  57. /**
  58. * @dev Variant of {transferAndCall} that accepts an additional `data` parameter with
  59. * no specified format.
  60. */
  61. function transferAndCall(address to, uint256 value, bytes memory data) public virtual returns (bool) {
  62. if (!transfer(to, value)) {
  63. revert ERC1363TransferFailed(to, value);
  64. }
  65. ERC1363Utils.checkOnERC1363TransferReceived(_msgSender(), _msgSender(), to, value, data);
  66. return true;
  67. }
  68. /**
  69. * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
  70. * and then calls {IERC1363Receiver-onTransferReceived} on `to`. Returns a flag that indicates
  71. * if the call succeeded.
  72. *
  73. * Requirements:
  74. *
  75. * - The target has code (i.e. is a contract).
  76. * - The target `to` must implement the {IERC1363Receiver} interface.
  77. * - The target must return the {IERC1363Receiver-onTransferReceived} selector to accept the transfer.
  78. * - The internal {transferFrom} must succeed (returned `true`).
  79. */
  80. function transferFromAndCall(address from, address to, uint256 value) public returns (bool) {
  81. return transferFromAndCall(from, to, value, "");
  82. }
  83. /**
  84. * @dev Variant of {transferFromAndCall} that accepts an additional `data` parameter with
  85. * no specified format.
  86. */
  87. function transferFromAndCall(
  88. address from,
  89. address to,
  90. uint256 value,
  91. bytes memory data
  92. ) public virtual returns (bool) {
  93. if (!transferFrom(from, to, value)) {
  94. revert ERC1363TransferFromFailed(from, to, value);
  95. }
  96. ERC1363Utils.checkOnERC1363TransferReceived(_msgSender(), from, to, value, data);
  97. return true;
  98. }
  99. /**
  100. * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
  101. * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
  102. * Returns a flag that indicates if the call succeeded.
  103. *
  104. * Requirements:
  105. *
  106. * - The target has code (i.e. is a contract).
  107. * - The target `spender` must implement the {IERC1363Spender} interface.
  108. * - The target must return the {IERC1363Spender-onApprovalReceived} selector to accept the approval.
  109. * - The internal {approve} must succeed (returned `true`).
  110. */
  111. function approveAndCall(address spender, uint256 value) public returns (bool) {
  112. return approveAndCall(spender, value, "");
  113. }
  114. /**
  115. * @dev Variant of {approveAndCall} that accepts an additional `data` parameter with
  116. * no specified format.
  117. */
  118. function approveAndCall(address spender, uint256 value, bytes memory data) public virtual returns (bool) {
  119. if (!approve(spender, value)) {
  120. revert ERC1363ApproveFailed(spender, value);
  121. }
  122. ERC1363Utils.checkOnERC1363ApprovalReceived(_msgSender(), spender, value, data);
  123. return true;
  124. }
  125. }