Update permit docs with recommendations
This commit is contained in:
@ -15,11 +15,11 @@ There are a few core contracts that implement the behavior specified in the EIP:
|
|||||||
|
|
||||||
Additionally there are multiple custom extensions, including:
|
Additionally there are multiple custom extensions, including:
|
||||||
|
|
||||||
|
* {ERC20Permit}: gasless approval of tokens (standardized as ERC2612).
|
||||||
* {ERC20Burnable}: destruction of own tokens.
|
* {ERC20Burnable}: destruction of own tokens.
|
||||||
* {ERC20Capped}: enforcement of a cap to the total supply when minting tokens.
|
* {ERC20Capped}: enforcement of a cap to the total supply when minting tokens.
|
||||||
* {ERC20Pausable}: ability to pause token transfers.
|
* {ERC20Pausable}: ability to pause token transfers.
|
||||||
* {ERC20Snapshot}: efficient storage of past token balances to be later queried at any point in time.
|
* {ERC20Snapshot}: efficient storage of past token balances to be later queried at any point in time.
|
||||||
* {ERC20Permit}: gasless approval of tokens (standardized as ERC2612).
|
|
||||||
* {ERC20FlashMint}: token level support for flash loans through the minting and burning of ephemeral tokens (standardized as ERC3156).
|
* {ERC20FlashMint}: token level support for flash loans through the minting and burning of ephemeral tokens (standardized as ERC3156).
|
||||||
* {ERC20Votes}: support for voting and vote delegation.
|
* {ERC20Votes}: support for voting and vote delegation.
|
||||||
* {ERC20VotesComp}: support for voting and vote delegation (compatible with Compound's token, with uint96 restrictions).
|
* {ERC20VotesComp}: support for voting and vote delegation (compatible with Compound's token, with uint96 restrictions).
|
||||||
@ -43,14 +43,16 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel
|
|||||||
|
|
||||||
== Extensions
|
== Extensions
|
||||||
|
|
||||||
|
{{IERC20Permit}}
|
||||||
|
|
||||||
|
{{ERC20Permit}}
|
||||||
|
|
||||||
{{ERC20Burnable}}
|
{{ERC20Burnable}}
|
||||||
|
|
||||||
{{ERC20Capped}}
|
{{ERC20Capped}}
|
||||||
|
|
||||||
{{ERC20Pausable}}
|
{{ERC20Pausable}}
|
||||||
|
|
||||||
{{ERC20Permit}}
|
|
||||||
|
|
||||||
{{ERC20Snapshot}}
|
{{ERC20Snapshot}}
|
||||||
|
|
||||||
{{ERC20Votes}}
|
{{ERC20Votes}}
|
||||||
|
|||||||
@ -44,7 +44,7 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
|
|||||||
constructor(string memory name) EIP712(name, "1") {}
|
constructor(string memory name) EIP712(name, "1") {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev See {IERC20Permit-permit}.
|
* @inheritdoc IERC20Permit
|
||||||
*/
|
*/
|
||||||
function permit(
|
function permit(
|
||||||
address owner,
|
address owner,
|
||||||
@ -68,14 +68,14 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev See {IERC20Permit-nonces}.
|
* @inheritdoc IERC20Permit
|
||||||
*/
|
*/
|
||||||
function nonces(address owner) public view virtual override returns (uint256) {
|
function nonces(address owner) public view virtual override returns (uint256) {
|
||||||
return _nonces[owner].current();
|
return _nonces[owner].current();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
|
* @inheritdoc IERC20Permit
|
||||||
*/
|
*/
|
||||||
// solhint-disable-next-line func-name-mixedcase
|
// solhint-disable-next-line func-name-mixedcase
|
||||||
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
|
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
|
||||||
|
|||||||
@ -10,6 +10,34 @@ pragma solidity ^0.8.0;
|
|||||||
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
|
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
|
||||||
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
|
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
|
||||||
* need to send a transaction, and thus is not required to hold Ether at all.
|
* need to send a transaction, and thus is not required to hold Ether at all.
|
||||||
|
*
|
||||||
|
* ==== Security Considerations
|
||||||
|
*
|
||||||
|
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
|
||||||
|
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
|
||||||
|
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
|
||||||
|
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
|
||||||
|
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
|
||||||
|
* generally recommended is:
|
||||||
|
*
|
||||||
|
* ```solidity
|
||||||
|
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
|
||||||
|
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
|
||||||
|
* doThing(..., value);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* function doThing(..., uint256 value) public {
|
||||||
|
* token.safeTransferFrom(msg.sender, address(this), value);
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
|
||||||
|
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
|
||||||
|
* {SafeERC20-safeTransferFrom}).
|
||||||
|
*
|
||||||
|
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
|
||||||
|
* contracts should have entry points that don't rely on permit.
|
||||||
*/
|
*/
|
||||||
interface IERC20Permit {
|
interface IERC20Permit {
|
||||||
/**
|
/**
|
||||||
@ -32,6 +60,8 @@ interface IERC20Permit {
|
|||||||
* For more information on the signature format, see the
|
* For more information on the signature format, see the
|
||||||
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
|
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
|
||||||
* section].
|
* section].
|
||||||
|
*
|
||||||
|
* CAUTION: See Security Considerations above.
|
||||||
*/
|
*/
|
||||||
function permit(
|
function permit(
|
||||||
address owner,
|
address owner,
|
||||||
|
|||||||
Reference in New Issue
Block a user