ERC1363.sol 5.2 KB

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