// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; import "../libs/SafeMathLib.sol"; /** * @title ERC20 token * * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol */ contract ERC20Token { using SafeMathLib for uint256; string public name; string public symbol; uint8 public decimals; uint256 public totalSupply; mapping(address => uint256) internal balances; mapping(address => mapping(address => uint256)) internal allowances; // events event Transfer( address indexed from, address indexed to, uint256 value ); event Approval( address indexed owner, address indexed spender, uint256 value ); /** * @dev internal constructor */ constructor() internal {} // external functions function transfer( address to, uint256 value ) external returns (bool) { _transfer(_getSender(), to, value); return true; } function transferFrom( address from, address to, uint256 value ) virtual external returns (bool) { address sender = _getSender(); _transfer(from, to, value); _approve(from, sender, allowances[from][sender].sub(value)); return true; } function approve( address spender, uint256 value ) virtual external returns (bool) { _approve(_getSender(), spender, value); return true; } // external functions (views) function balanceOf( address owner ) virtual external view returns (uint256) { return balances[owner]; } function allowance( address owner, address spender ) virtual external view returns (uint256) { return allowances[owner][spender]; } // internal functions function _transfer( address from, address to, uint256 value ) virtual internal { require( from != address(0), "ERC20Token: cannot transfer from 0x0 address" ); require( to != address(0), "ERC20Token: cannot transfer to 0x0 address" ); balances[from] = balances[from].sub(value); balances[to] = balances[to].add(value); emit Transfer(from, to, value); } function _approve( address owner, address spender, uint256 value ) virtual internal { require( owner != address(0), "ERC20Token: cannot approve from 0x0 address" ); require( spender != address(0), "ERC20Token: cannot approve to 0x0 address" ); allowances[owner][spender] = value; emit Approval(owner, spender, value); } function _mint( address owner, uint256 value ) virtual internal { require( owner != address(0), "ERC20Token: cannot mint to 0x0 address" ); require( value > 0, "ERC20Token: cannot mint 0 value" ); balances[owner] = balances[owner].add(value); totalSupply = totalSupply.add(value); emit Transfer(address(0), owner, value); } function _burn( address owner, uint256 value ) virtual internal { require( owner != address(0), "ERC20Token: cannot burn from 0x0 address" ); balances[owner] = balances[owner].sub( value, "ERC20Token: burn value exceeds balance" ); totalSupply = totalSupply.sub(value); emit Transfer(owner, address(0), value); } // internal functions (views) function _getSender() virtual internal view returns (address) { return msg.sender; } }