contract SmolTing is Ownable, MinterRole, CanTransferRole {
    using SafeMath for uint256;
    event Transfer(address indexed from, address indexed to, uint256 value);

    mapping (address => uint256) private _balances;

    uint256 private _totalSupply;
    uint256 private _totalClaimed;
    string public name = "smol ting";
    string public symbol = "TING";
    uint8 public decimals = 18;

    /**
     * @dev total number of tokens in existence.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    // returns the total claimed smol
    // this is just purely used to display the total smol claimed by users on the frontend
    function totalClaimed() public view returns (uint256) {
        return _totalClaimed;
    }

    // add smol claimed
    function addClaimed(uint256 _amount) public onlyCanTransfer {
        _totalClaimed = _totalClaimed.add(_amount);
    }

    // set smol claimed to a custom value, for if we wanna reset the counter anytime
    function setClaimed(uint256 _amount) public onlyCanTransfer {
        require(_amount >= 0, "nonono cant be negative");
        _totalClaimed = _amount;
    }

    // as this token is non tradable, only minters are allowed to transfer tokens between accounts
    function transfer(address receiver, uint numTokens) public onlyCanTransfer returns (bool) {
        require(numTokens <= _balances[msg.sender]);
        _balances[msg.sender] = _balances[msg.sender].sub(numTokens);
        _balances[receiver] = _balances[receiver].add(numTokens);
        emit Transfer(msg.sender, receiver, numTokens);
        return true;
    }

    // as this token is non tradable, only minters are allowed to transfer tokens between accounts
    function transferFrom(address owner, address buyer, uint numTokens) public onlyCanTransfer returns (bool) {
        require(numTokens <= _balances[owner]);

        _balances[owner] = _balances[owner].sub(numTokens);
        _balances[buyer] = _balances[buyer].add(numTokens);
        emit Transfer(owner, buyer, numTokens);
        return true;
    }

    /**
     * @dev gets the balance of the specified address.
     * @param owner the address to query the balance of.
     * @return a uint256 representing the amount owned by the passed address.
     */
    function balanceOf(address owner) public view returns (uint256) {
        return _balances[owner];
    }

    function mint(address _to, uint256 _amount) public onlyMinter {
        _mint(_to, _amount);
    }

    function burn(address _account, uint256 value) public onlyCanTransfer {
        require(_balances[_account] >= value, "ya no cant burn more than address has");
        _burn(_account, value);
    }

    /**
     * @dev internal function that mints an amount of the token and assigns it to
     * an account. this encapsulates the modification of balances such that the
     * proper events are emitted.
     * @param account the account that will receive the created tokens.
     * @param value the amount that will be created.
     */
    function _mint(address account, uint256 value) internal {
        require(account != address(0), "smolerc20: mint to the zero address");

        _totalSupply = _totalSupply.add(value);
        _balances[account] = _balances[account].add(value);
        emit Transfer(address(0), account, value);
    }

    /**
     * @dev internal function that burns an amount of the token of a given
     * account.
     * @param account The account whose tokens will be burnt.
     * @param value The amount that will be burnt.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0), "smolerc20: burn from the zero address");

        _totalSupply = _totalSupply.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Transfer(account, address(0), value);
    }
}
function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }
/**
 * @dev total number of tokens in existence.
 */