// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;
import "./safemath.sol";
/**
* @title ERC20 standard token implementation.
* @dev Standard ERC20 token. This contract follows the implementation at https://goo.gl/mLbAPJ.
*/
contract Token {
using SafeMath for uint;
/*
* Token name.
*/
string internal tokenName;
/*
* Token symbol.
*/
string internal tokenSymbol;
/*
* Number of decimals.
*/
uint8 internal tokenDecimals;
/*
* Total supply of tokens.
*/
uint256 internal tokenTotalSupply;
/*
* Balance information map.
*/
mapping (address => uint256) internal balances;
/*
* Token allowance mapping.
*/
mapping (address => mapping (address => uint256)) internal allowed;
/*
* @dev Trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from,address indexed _to,uint256 _value);
/*
* @dev Trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner,address indexed _spender,uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _initialOwnerBalance) {
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenTotalSupply = _initialOwnerBalance;
balances[msg.sender] = _initialOwnerBalance;
}
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory _name){
_name = tokenName;
}
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory _symbol){
_symbol = tokenSymbol;
}
/*
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8 _decimals){
_decimals = tokenDecimals;
}
/*
* @dev Returns the total token supply.
*/
function totalSupply()external view returns (uint256 _totalSupply){
_totalSupply = tokenTotalSupply;
}
/*
* @dev Returns the account balance of another account with address _owner.
* @param _owner The address from which the balance will be retrieved.
*/
function balanceOf(address _owner) external view returns (uint256 _balance){
_balance = balances[_owner];
}
/*
* @dev Internal function used for all transfers
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function _transfer(address _from,address _to,uint256 _value) internal returns (bool _success){
//We use require instead of throw as throw is depricated
require(balances[_from] >= _value, "Balance not sufficient");
require(_from != _to, "Don't transfer money to yourself");
uint previousSenderBalance = balances[_from];
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
assert(balances[_from] == previousSenderBalance.sub(_value));
_success=true;
}
/*
* @dev internal version of approve to capsule common logic
* @param _spender The address of the account able to transfer the tokens.
* @param _owner The address of the owner account
* @param _value The amount of tokens to be approved for transfer.
*/
function _approve(address _owner, address _spender, uint256 _value) internal returns (bool _success) {
allowed[_owner][_spender] = _value;
emit Approval(_owner, _spender, _value);
_success=true;
}
/*
* @dev Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The
* function SHOULD throw if the "from" account balance does not have enough tokens to spend.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transfer(address payable _to, uint256 _value) public returns (bool _success){
_success=_transfer(msg.sender, _to, _value);
}
/*
* @dev Allows _spender to withdraw from your account multiple times, up to the _value amount. If
* this function is called again it overwrites the current allowance with _value. SHOULD emit the Approval event.
* @param _spender The address of the account able to transfer the tokens.
* @param _value The amount of tokens to be approved for transfer.
*/
function approve(address _spender,uint256 _value) public returns (bool _success) {
require(_spender != msg.sender, "Don't approve yourself");
_success=_approve (msg.sender, _spender, _value);
}
/*
* @dev Returns the amount which _spender is still allowed to withdraw from _owner.
* @param _owner The address of the account owning tokens.
* @param _spender The address of the account able to transfer the tokens.
*/
function allowance(address _owner,address _spender) external view returns (uint256 _remaining){
_remaining = allowed[_owner][_spender];
}
/*
* @dev Transfers _value amount of tokens from address _from to address _to, and MUST fire the
* Transfer event.
* @param _from The address of the sender.
* @param _to The address of the recipient.
* @param _value The amount of token to be transferred.
*/
function transferFrom(address _from,address _to,uint256 _value) public returns (bool _success){
//We use require instead of throw as throw is depricated
require(allowed[_from][msg.sender] >= _value, "Allowance not sufficient");
// Reduce the allowance
_approve(_from, msg.sender, allowed[_from][msg.sender].sub(_value));
// Do the transfer
_success=_transfer(_from, _to, _value);
}
}