IERC20Permit.sol 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)
  3. pragma solidity ^0.8.20;
  4. /**
  5. * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
  6. * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
  7. *
  8. * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
  9. * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
  10. * need to send a transaction, and thus is not required to hold Ether at all.
  11. *
  12. * ==== Security Considerations
  13. *
  14. * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
  15. * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
  16. * considered as an intention to spend the allowance in any specific way. The second is that because permits have
  17. * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
  18. * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
  19. * generally recommended is:
  20. *
  21. * ```solidity
  22. * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
  23. * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
  24. * doThing(..., value);
  25. * }
  26. *
  27. * function doThing(..., uint256 value) public {
  28. * token.safeTransferFrom(msg.sender, address(this), value);
  29. * ...
  30. * }
  31. * ```
  32. *
  33. * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
  34. * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
  35. * {SafeERC20-safeTransferFrom}).
  36. *
  37. * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
  38. * contracts should have entry points that don't rely on permit.
  39. */
  40. interface IERC20Permit {
  41. /**
  42. * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
  43. * given ``owner``'s signed approval.
  44. *
  45. * IMPORTANT: The same issues {IERC20-approve} has related to transaction
  46. * ordering also apply here.
  47. *
  48. * Emits an {Approval} event.
  49. *
  50. * Requirements:
  51. *
  52. * - `spender` cannot be the zero address.
  53. * - `deadline` must be a timestamp in the future.
  54. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
  55. * over the EIP712-formatted function arguments.
  56. * - the signature must use ``owner``'s current nonce (see {nonces}).
  57. *
  58. * For more information on the signature format, see the
  59. * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
  60. * section].
  61. *
  62. * CAUTION: See Security Considerations above.
  63. */
  64. function permit(
  65. address owner,
  66. address spender,
  67. uint256 value,
  68. uint256 deadline,
  69. uint8 v,
  70. bytes32 r,
  71. bytes32 s
  72. ) external;
  73. /**
  74. * @dev Returns the current nonce for `owner`. This value must be
  75. * included whenever a signature is generated for {permit}.
  76. *
  77. * Every successful call to {permit} increases ``owner``'s nonce by one. This
  78. * prevents a signature from being used multiple times.
  79. */
  80. function nonces(address owner) external view returns (uint256);
  81. /**
  82. * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
  83. */
  84. // solhint-disable-next-line func-name-mixedcase
  85. function DOMAIN_SEPARATOR() external view returns (bytes32);
  86. }