Add a _spendAllowance function to ERC20 & ERC777 (#3170)
(cherry picked from commit c5a6cae898)
This commit is contained in:
committed by
Francisco Giordano
parent
234a971410
commit
494b1b9a39
@ -161,16 +161,8 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
|
||||
uint256 amount
|
||||
) public virtual override returns (bool) {
|
||||
address spender = _msgSender();
|
||||
uint256 currentAllowance = allowance(from, spender);
|
||||
if (currentAllowance != type(uint256).max) {
|
||||
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
|
||||
unchecked {
|
||||
_approve(from, spender, currentAllowance - amount);
|
||||
}
|
||||
}
|
||||
|
||||
_spendAllowance(from, spender, amount);
|
||||
_transfer(from, to, amount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -327,6 +319,28 @@ contract ERC20 is Context, IERC20, IERC20Metadata {
|
||||
emit Approval(owner, spender, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Spend `amount` form the allowance of `owner` toward `spender`.
|
||||
*
|
||||
* Does not update the allowance amount in case of infinite allowance.
|
||||
* Revert if not enough allowance is available.
|
||||
*
|
||||
* Might emit an {Approval} event.
|
||||
*/
|
||||
function _spendAllowance(
|
||||
address owner,
|
||||
address spender,
|
||||
uint256 amount
|
||||
) internal virtual {
|
||||
uint256 currentAllowance = allowance(owner, spender);
|
||||
if (currentAllowance != type(uint256).max) {
|
||||
require(currentAllowance >= amount, "ERC20: insufficient allowance");
|
||||
unchecked {
|
||||
_approve(owner, spender, currentAllowance - amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Hook that is called before any transfer of tokens. This includes
|
||||
* minting and burning.
|
||||
|
||||
@ -33,11 +33,7 @@ abstract contract ERC20Burnable is Context, ERC20 {
|
||||
* `amount`.
|
||||
*/
|
||||
function burnFrom(address account, uint256 amount) public virtual {
|
||||
uint256 currentAllowance = allowance(account, _msgSender());
|
||||
require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
|
||||
unchecked {
|
||||
_approve(account, _msgSender(), currentAllowance - amount);
|
||||
}
|
||||
_spendAllowance(account, _msgSender(), amount);
|
||||
_burn(account, amount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,13 +293,7 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
|
||||
_callTokensToSend(spender, holder, recipient, amount, "", "");
|
||||
|
||||
uint256 currentAllowance = _allowances[holder][spender];
|
||||
if (currentAllowance != type(uint256).max) {
|
||||
require(currentAllowance >= amount, "ERC777: transfer amount exceeds allowance");
|
||||
unchecked {
|
||||
_approve(holder, spender, currentAllowance - amount);
|
||||
}
|
||||
}
|
||||
_spendAllowance(holder, spender, amount);
|
||||
|
||||
_move(spender, holder, recipient, amount, "", "");
|
||||
|
||||
@ -526,6 +520,28 @@ contract ERC777 is Context, IERC777, IERC20 {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Spend `amount` form the allowance of `owner` toward `spender`.
|
||||
*
|
||||
* Does not update the allowance amount in case of infinite allowance.
|
||||
* Revert if not enough allowance is available.
|
||||
*
|
||||
* Might emit an {Approval} event.
|
||||
*/
|
||||
function _spendAllowance(
|
||||
address owner,
|
||||
address spender,
|
||||
uint256 amount
|
||||
) internal virtual {
|
||||
uint256 currentAllowance = allowance(owner, spender);
|
||||
if (currentAllowance != type(uint256).max) {
|
||||
require(currentAllowance >= amount, "ERC777: insufficient allowance");
|
||||
unchecked {
|
||||
_approve(owner, spender, currentAllowance - amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Hook that is called before any token transfer. This includes
|
||||
* calls to {send}, {transfer}, {operatorSend}, minting and burning.
|
||||
|
||||
Reference in New Issue
Block a user