diff --git a/CHANGELOG.md b/CHANGELOG.md index db5f434a1..0ff8a8658 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * `IERC20Metadata`: add a new extended interface that includes the optional `name()`, `symbol()` and `decimals()` functions. ([#2561](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2561)) * `ERC777`: make reception acquirement optional in `_mint`. ([#2552](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2552)) + * `ERC20Permit`: add a `_useNonce` to enable further usage of ERC712 signatures. ([#2565](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2565)) ## Unreleased diff --git a/contracts/token/ERC20/extensions/draft-ERC20Permit.sol b/contracts/token/ERC20/extensions/draft-ERC20Permit.sol index 1f5cdc2cb..4dcd9007a 100644 --- a/contracts/token/ERC20/extensions/draft-ERC20Permit.sol +++ b/contracts/token/ERC20/extensions/draft-ERC20Permit.sol @@ -47,7 +47,7 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { owner, spender, value, - _nonces[owner].current(), + _useNonce(owner), deadline ) ); @@ -57,14 +57,13 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); - _nonces[owner].increment(); _approve(owner, spender, value); } /** * @dev See {IERC20Permit-nonces}. */ - function nonces(address owner) public view override returns (uint256) { + function nonces(address owner) public view virtual override returns (uint256) { return _nonces[owner].current(); } @@ -75,4 +74,13 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } + + /** + * @dev "Consume a nonce": return the current value and increment. + */ + function _useNonce(address owner) internal virtual returns (uint256 current) { + Counters.Counter storage nonce = _nonces[owner]; + current = nonce.current(); + nonce.increment(); + } }