pragma solidity ^0.5.16;

contract MiniERC20 {
    using SafeMath_ for uint;

    string public name;
    string public symbol;
    uint8 public decimals;
    uint public totalSupply;
    mapping (address => uint) public balanceOf;
    mapping (address => mapping (address => uint)) public allowance;

    event Transfer(address indexed src, address indexed dst, uint amount);
    event Approval(address indexed owner, address indexed spender, uint amount);

    constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _totalSupply) public {
        totalSupply = _totalSupply;
        balanceOf[msg.sender] = _totalSupply;
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        emit Transfer(address(0), msg.sender, _totalSupply);
    }

    function transfer(address dst, uint amount) public returns (bool) {
        balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, "Insufficient balance");
        balanceOf[dst] = balanceOf[dst].add(amount, "Balance overflow");
        emit Transfer(msg.sender, dst, amount);
        return true;
    }

    function transferFrom(address src, address dst, uint amount) external returns (bool) {
        allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, "Insufficient allowance");
        balanceOf[src] = balanceOf[src].sub(amount, "Insufficient balance");
        balanceOf[dst] = balanceOf[dst].add(amount, "Balance overflow");
        emit Transfer(src, dst, amount);
        return true;
    }

    function approve(address spender, uint amount) external returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }
}

library SafeMath_ {
    function add(uint a, uint b) internal pure returns (uint c) {
        c = add(a, b, "SafeMath: addition overflow");
    }
    function add(uint a, uint b, string memory error) internal pure returns (uint c) {
        c = a + b;
        require(c >= a, error);
    }

    function sub(uint a, uint b) internal pure returns (uint c) {
        c = sub(a, b, "SafeMath: subtraction underflow");
    }
    function sub(uint a, uint b, string memory error) internal pure returns (uint c) {
        require(b <= a, error);
        c = a - b;
    }

    function mul(uint a, uint b) internal pure returns (uint c) {
        c = mul(a, b, "SafeMath: multiplication overflow");
    }
    function mul(uint a, uint b, string memory error) internal pure returns (uint c) {
        if (a == 0)
            return 0;
        c = a * b;
        require(c / a == b, error);
    }
}