ERC1363.sol 5.3 KB

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