You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
370 lines
13 KiB
370 lines
13 KiB
// SPDX-License-Identifier: MIT
|
|
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
|
|
|
|
pragma solidity ^0.8.19;
|
|
|
|
import {IERC20} from "./IERC20.sol";
|
|
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
|
|
import {Context} from "../../utils/Context.sol";
|
|
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
|
|
|
|
/**
|
|
* @dev Implementation of the {IERC20} interface.
|
|
*
|
|
* This implementation is agnostic to the way tokens are created. This means
|
|
* that a supply mechanism has to be added in a derived contract using {_mint}.
|
|
*
|
|
* TIP: For a detailed writeup see our guide
|
|
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
|
|
* to implement supply mechanisms].
|
|
*
|
|
* The default value of {decimals} is 18. To change this, you should override
|
|
* this function so it returns a different value.
|
|
*
|
|
* We have followed general OpenZeppelin Contracts guidelines: functions revert
|
|
* instead returning `false` on failure. This behavior is nonetheless
|
|
* conventional and does not conflict with the expectations of ERC20
|
|
* applications.
|
|
*
|
|
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
|
|
* This allows applications to reconstruct the allowance for all accounts just
|
|
* by listening to said events. Other implementations of the EIP may not emit
|
|
* these events, as it isn't required by the specification.
|
|
*
|
|
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
|
|
* functions have been added to mitigate the well-known issues around setting
|
|
* allowances. See {IERC20-approve}.
|
|
*/
|
|
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
|
|
mapping(address => uint256) private _balances;
|
|
|
|
mapping(address => mapping(address => uint256)) private _allowances;
|
|
|
|
uint256 private _totalSupply;
|
|
|
|
string private _name;
|
|
string private _symbol;
|
|
|
|
/**
|
|
* @dev Indicates a failed `decreaseAllowance` request.
|
|
*/
|
|
error ERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
|
|
|
|
/**
|
|
* @dev Sets the values for {name} and {symbol}.
|
|
*
|
|
* All two of these values are immutable: they can only be set once during
|
|
* construction.
|
|
*/
|
|
constructor(string memory name_, string memory symbol_) {
|
|
_name = name_;
|
|
_symbol = symbol_;
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the name of the token.
|
|
*/
|
|
function name() public view virtual returns (string memory) {
|
|
return _name;
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the symbol of the token, usually a shorter version of the
|
|
* name.
|
|
*/
|
|
function symbol() public view virtual returns (string memory) {
|
|
return _symbol;
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the number of decimals used to get its user representation.
|
|
* For example, if `decimals` equals `2`, a balance of `505` tokens should
|
|
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
|
|
*
|
|
* Tokens usually opt for a value of 18, imitating the relationship between
|
|
* Ether and Wei. This is the default value returned by this function, unless
|
|
* it's overridden.
|
|
*
|
|
* NOTE: This information is only used for _display_ purposes: it in
|
|
* no way affects any of the arithmetic of the contract, including
|
|
* {IERC20-balanceOf} and {IERC20-transfer}.
|
|
*/
|
|
function decimals() public view virtual returns (uint8) {
|
|
return 18;
|
|
}
|
|
|
|
/**
|
|
* @dev See {IERC20-totalSupply}.
|
|
*/
|
|
function totalSupply() public view virtual returns (uint256) {
|
|
return _totalSupply;
|
|
}
|
|
|
|
/**
|
|
* @dev See {IERC20-balanceOf}.
|
|
*/
|
|
function balanceOf(address account) public view virtual returns (uint256) {
|
|
return _balances[account];
|
|
}
|
|
|
|
/**
|
|
* @dev See {IERC20-transfer}.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - `to` cannot be the zero address.
|
|
* - the caller must have a balance of at least `value`.
|
|
*/
|
|
function transfer(address to, uint256 value) public virtual returns (bool) {
|
|
address owner = _msgSender();
|
|
_transfer(owner, to, value);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev See {IERC20-allowance}.
|
|
*/
|
|
function allowance(address owner, address spender) public view virtual returns (uint256) {
|
|
return _allowances[owner][spender];
|
|
}
|
|
|
|
/**
|
|
* @dev See {IERC20-approve}.
|
|
*
|
|
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
|
|
* `transferFrom`. This is semantically equivalent to an infinite approval.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - `spender` cannot be the zero address.
|
|
*/
|
|
function approve(address spender, uint256 value) public virtual returns (bool) {
|
|
address owner = _msgSender();
|
|
_approve(owner, spender, value);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev See {IERC20-transferFrom}.
|
|
*
|
|
* Emits an {Approval} event indicating the updated allowance. This is not
|
|
* required by the EIP. See the note at the beginning of {ERC20}.
|
|
*
|
|
* NOTE: Does not update the allowance if the current allowance
|
|
* is the maximum `uint256`.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - `from` and `to` cannot be the zero address.
|
|
* - `from` must have a balance of at least `value`.
|
|
* - the caller must have allowance for ``from``'s tokens of at least
|
|
* `value`.
|
|
*/
|
|
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
|
|
address spender = _msgSender();
|
|
_spendAllowance(from, spender, value);
|
|
_transfer(from, to, value);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev Atomically increases the allowance granted to `spender` by the caller.
|
|
*
|
|
* This is an alternative to {approve} that can be used as a mitigation for
|
|
* problems described in {IERC20-approve}.
|
|
*
|
|
* Emits an {Approval} event indicating the updated allowance.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - `spender` cannot be the zero address.
|
|
*/
|
|
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
|
|
address owner = _msgSender();
|
|
_approve(owner, spender, allowance(owner, spender) + addedValue);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev Atomically decreases the allowance granted to `spender` by the caller.
|
|
*
|
|
* This is an alternative to {approve} that can be used as a mitigation for
|
|
* problems described in {IERC20-approve}.
|
|
*
|
|
* Emits an {Approval} event indicating the updated allowance.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - `spender` cannot be the zero address.
|
|
* - `spender` must have allowance for the caller of at least
|
|
* `requestedDecrease`.
|
|
*
|
|
* NOTE: Although this function is designed to avoid double spending with {approval},
|
|
* it can still be frontrunned, preventing any attempt of allowance reduction.
|
|
*/
|
|
function decreaseAllowance(address spender, uint256 requestedDecrease) public virtual returns (bool) {
|
|
address owner = _msgSender();
|
|
uint256 currentAllowance = allowance(owner, spender);
|
|
if (currentAllowance < requestedDecrease) {
|
|
revert ERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
|
|
}
|
|
unchecked {
|
|
_approve(owner, spender, currentAllowance - requestedDecrease);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev Moves a `value` amount of tokens from `from` to `to`.
|
|
*
|
|
* This internal function is equivalent to {transfer}, and can be used to
|
|
* e.g. implement automatic token fees, slashing mechanisms, etc.
|
|
*
|
|
* Emits a {Transfer} event.
|
|
*
|
|
* NOTE: This function is not virtual, {_update} should be overridden instead.
|
|
*/
|
|
function _transfer(address from, address to, uint256 value) internal {
|
|
if (from == address(0)) {
|
|
revert ERC20InvalidSender(address(0));
|
|
}
|
|
if (to == address(0)) {
|
|
revert ERC20InvalidReceiver(address(0));
|
|
}
|
|
_update(from, to, value);
|
|
}
|
|
|
|
/**
|
|
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` (or `to`) is
|
|
* the zero address. All customizations to transfers, mints, and burns should be done by overriding this function.
|
|
*
|
|
* Emits a {Transfer} event.
|
|
*/
|
|
function _update(address from, address to, uint256 value) internal virtual {
|
|
if (from == address(0)) {
|
|
// Overflow check required: The rest of the code assumes that totalSupply never overflows
|
|
_totalSupply += value;
|
|
} else {
|
|
uint256 fromBalance = _balances[from];
|
|
if (fromBalance < value) {
|
|
revert ERC20InsufficientBalance(from, fromBalance, value);
|
|
}
|
|
unchecked {
|
|
// Overflow not possible: value <= fromBalance <= totalSupply.
|
|
_balances[from] = fromBalance - value;
|
|
}
|
|
}
|
|
|
|
if (to == address(0)) {
|
|
unchecked {
|
|
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
|
|
_totalSupply -= value;
|
|
}
|
|
} else {
|
|
unchecked {
|
|
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
|
|
_balances[to] += value;
|
|
}
|
|
}
|
|
|
|
emit Transfer(from, to, value);
|
|
}
|
|
|
|
/**
|
|
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
|
|
* Relies on the `_update` mechanism
|
|
*
|
|
* Emits a {Transfer} event with `from` set to the zero address.
|
|
*
|
|
* NOTE: This function is not virtual, {_update} should be overridden instead.
|
|
*/
|
|
function _mint(address account, uint256 value) internal {
|
|
if (account == address(0)) {
|
|
revert ERC20InvalidReceiver(address(0));
|
|
}
|
|
_update(address(0), account, value);
|
|
}
|
|
|
|
/**
|
|
* @dev Destroys a `value` amount of tokens from `account`, by transferring it to address(0).
|
|
* Relies on the `_update` mechanism.
|
|
*
|
|
* Emits a {Transfer} event with `to` set to the zero address.
|
|
*
|
|
* NOTE: This function is not virtual, {_update} should be overridden instead
|
|
*/
|
|
function _burn(address account, uint256 value) internal {
|
|
if (account == address(0)) {
|
|
revert ERC20InvalidSender(address(0));
|
|
}
|
|
_update(account, address(0), value);
|
|
}
|
|
|
|
/**
|
|
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
|
|
*
|
|
* This internal function is equivalent to `approve`, and can be used to
|
|
* e.g. set automatic allowances for certain subsystems, etc.
|
|
*
|
|
* Emits an {Approval} event.
|
|
*
|
|
* Requirements:
|
|
*
|
|
* - `owner` cannot be the zero address.
|
|
* - `spender` cannot be the zero address.
|
|
*/
|
|
function _approve(address owner, address spender, uint256 value) internal virtual {
|
|
_approve(owner, spender, value, true);
|
|
}
|
|
|
|
/**
|
|
* @dev Alternative version of {_approve} with an optional flag that can enable or disable the Approval event.
|
|
*
|
|
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
|
|
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
|
|
* `Approval` event during `transferFrom` operations.
|
|
*
|
|
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to true
|
|
* using the following override:
|
|
* ```
|
|
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
|
|
* super._approve(owner, spender, value, true);
|
|
* }
|
|
* ```
|
|
*
|
|
* Requirements are the same as {_approve}.
|
|
*/
|
|
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
|
|
if (owner == address(0)) {
|
|
revert ERC20InvalidApprover(address(0));
|
|
}
|
|
if (spender == address(0)) {
|
|
revert ERC20InvalidSpender(address(0));
|
|
}
|
|
_allowances[owner][spender] = value;
|
|
if (emitEvent) {
|
|
emit Approval(owner, spender, value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
|
|
*
|
|
* Does not update the allowance value in case of infinite allowance.
|
|
* Revert if not enough allowance is available.
|
|
*
|
|
* Might emit an {Approval} event.
|
|
*/
|
|
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
|
|
uint256 currentAllowance = allowance(owner, spender);
|
|
if (currentAllowance != type(uint256).max) {
|
|
if (currentAllowance < value) {
|
|
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
|
|
}
|
|
unchecked {
|
|
_approve(owner, spender, currentAllowance - value, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|