// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IMintable} from "../../interfaces/IMintable.sol"; import {Governable} from "../../core/Governable.sol"; contract EsToken2 is IERC20, IMintable, Governable { using SafeERC20 for IERC20; string public name; string public symbol; uint8 public decimals = 18; uint256 public override totalSupply; bool public inPrivateTransferMode; mapping(address => uint256) public balances; mapping(address => mapping(address => uint256)) public allowances; mapping(address => bool) public nonStakingAccounts; mapping(address => bool) public admins; mapping(address => bool) public override isMinter; mapping(address => bool) public isHandler; constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } modifier onlyMinter() { require(isMinter[msg.sender], "EsToken: forbidden"); _; } modifier onlyAdmin() { require(admins[msg.sender], "BaseToken: forbidden"); _; } function setMinter(address _minter, bool _isActive) external override onlyGov { isMinter[_minter] = _isActive; } function addAdmin(address _account) external onlyGov { admins[_account] = true; } function removeAdmin(address _account) external onlyGov { admins[_account] = false; } function mint(address _account, uint256 _amount) external override onlyMinter { _mint(_account, _amount); } function burn(address _account, uint256 _amount) external override onlyMinter { _burn(_account, _amount); } function setInPrivateTransferMode(bool _inPrivateTransferMode) external onlyGov { inPrivateTransferMode = _inPrivateTransferMode; } function setHandler(address _handler, bool _isActive) external onlyGov { isHandler[_handler] = _isActive; } function balanceOf(address _account) external view override returns (uint256) { return balances[_account]; } function stakedBalance(address _account) external view returns (uint256) { if (nonStakingAccounts[_account]) { return 0; } return balances[_account]; } function transfer(address _recipient, uint256 _amount) external override returns (bool) { _transfer(msg.sender, _recipient, _amount); return true; } function allowance(address _owner, address _spender) external view override returns (uint256) { return allowances[_owner][_spender]; } function approve(address _spender, uint256 _amount) external override returns (bool) { _approve(msg.sender, _spender, _amount); return true; } function transferFrom(address _sender, address _recipient, uint256 _amount) external override returns (bool) { if (isHandler[msg.sender]) { _transfer(_sender, _recipient, _amount); return true; } require(allowances[_sender][msg.sender] >= _amount, "EsToken: transfer amount exceeds allowance"); uint256 nextAllowance = allowances[_sender][msg.sender] - _amount; _approve(_sender, msg.sender, nextAllowance); _transfer(_sender, _recipient, _amount); return true; } function _mint(address _account, uint256 _amount) internal { require(_account != address(0), "EsToken: mint to the zero address"); totalSupply = totalSupply + _amount; balances[_account] = balances[_account] + _amount; emit Transfer(address(0), _account, _amount); } function _burn(address _account, uint256 _amount) internal { require(_account != address(0), "EsToken: burn from the zero address"); require(balances[_account] >= _amount, "EsToken: burn amount exceeds balance"); balances[_account] = balances[_account] - _amount; totalSupply = totalSupply - _amount; emit Transfer(_account, address(0), _amount); } function _transfer(address _sender, address _recipient, uint256 _amount) private { require(_sender != address(0), "EsToken: transfer from the zero address"); require(_recipient != address(0), "EsToken: transfer to the zero address"); if (inPrivateTransferMode) { require(isHandler[msg.sender], "EsToken: msg.sender not whitelisted"); } require(balances[_sender] >= _amount, "EsToken: transfer amount exceeds balance"); balances[_sender] = balances[_sender] - _amount; balances[_recipient] = balances[_recipient] + _amount; emit Transfer(_sender, _recipient, _amount); } function _approve(address _owner, address _spender, uint256 _amount) private { require(_owner != address(0), "EsToken: approve from the zero address"); require(_spender != address(0), "EsToken: approve to the zero address"); allowances[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); } }