// SPDX-License-Identifier: MIT pragma solidity 0.7.6; import "@openzeppelin/contracts/utils/Context.sol"; import "./interfaces/IVeERC20.sol"; /// @title VeERC20 /// @notice Modified version of ERC20 where transfers and allowances are disabled. /// @dev Only minting and burning are allowed. The hook `_beforeTokenOperation` and /// `_afterTokenOperation` methods are called before and after minting/burning respectively. contract VeERC20 is Context, IVeERC20 { mapping(address => uint256) private _balances; uint256 private _totalSupply; string private _name; string private _symbol; /// @dev Emitted when `value` tokens are burned and minted event Burn(address indexed account, uint256 value); event Mint(address indexed beneficiary, uint256 value); /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * 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 value {ERC20} uses, unless this function is * 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 override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenOperation(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Mint(account, amount); _afterTokenOperation(account, _balances[account]); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenOperation(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); _balances[account] = accountBalance - amount; _totalSupply -= amount; emit Burn(account, amount); _afterTokenOperation(account, _balances[account]); } /** * @dev Hook that is called before any minting and burning. * @param from the account transferring tokens * @param to the account receiving tokens * @param amount the amount being minted or burned */ function _beforeTokenOperation( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any minting and burning. * @param account the account being affected * @param newBalance the new balance of `account` after minting/burning */ function _afterTokenOperation(address account, uint256 newBalance) internal virtual {} }