contract MintableToken is ERC865Token {
    using SafeMath for uint256;

    event Mint(address indexed to, uint256 amount);

    // Limit total supply to 10 billion
    uint256 public constant totalTokenLimit = 10000000000000000000000000000;

    // Max token left percent allow to mint, based on 100%
    uint256 public maxTokenRateToMint = 20;
    uint256 public canMintLimit = 0;


    /**
     * @dev Throws if total supply is higher than total token limit
     */
    modifier canMint()
    {

        // Address to mint must defined
        require(
            teamAddress != address(0) &&
            saleAddress != address(0)

        );

        // Total supply after mint must lower or equal total token limit
        require(totalSupply_ <= totalTokenLimit);
        require(balances[saleAddress] <= canMintLimit);
        _;
    }


    /**
     * @dev Function to mint tokens: mint 1000000000000000000000000000 every times
     * @return A boolean that indicates if the operation was successful.
     */
    function mint() onlyCLevel external {
        _mint(1000000000000000000000000000);
    }

    function _mint(uint256 _amount)
    canMint
    internal
    {
        uint256 saleAmount_ = _amount.mul(saleRate).div(100);
        uint256 teamAmount_ = _amount.mul(teamRate).div(100);

        totalSupply_ = totalSupply_.add(_amount);
        balances[saleAddress] = balances[saleAddress].add(saleAmount_);
        balances[teamAddress] = balances[teamAddress].add(teamAmount_);

        canMintLimit = balances[saleAddress]
        .mul(maxTokenRateToMint)
        .div(100);
        mintTxCount_++;

        emit Mint(saleAddress, saleAmount_);
        emit Mint(teamAddress, teamAmount_);
    }

    function getMaxTokenRateToMintHashing(uint256 _rate, uint256 _nonce) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(bytes4(0x486A0F45), _rate, _nonce));
    }

    function setMaxTokenRateToMint(
        uint256 _rate,
        bytes _sig
    ) external onlyCLevel {
        require(_rate <= 100);
        require(_rate >= 0);

        bytes32 hashedTx = getMaxTokenRateToMintHashing(_rate, nonces[msg.sender]);
        require(signedCLevel(hashedTx, _sig));
        nonces[msg.sender]++;

        maxTokenRateToMint = _rate;
        CLevelTxCount_++;
    }

    function getMintRatesHashing(uint256 _saleRate, uint256 _nonce) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(bytes4(0x486A0F46), _saleRate, _nonce));
    }

    function setMintRates(
        uint256 saleRate_,
        bytes _sig
    )
    external
    onlyCLevel
    {
        require(saleRate.add(teamRate) == 100);
        require(mintTxCount_ >= 3);

        bytes32 hashedTx = getMintRatesHashing(saleRate_, nonces[msg.sender]);
        require(signedCLevel(hashedTx, _sig));
        nonces[msg.sender]++;

        saleRate = saleRate_;
        CLevelTxCount_++;
    }
}
/**
 * @title Mintable token
 * @dev Simple ERC20 Token example, with mintable token creation
 * @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/120
 * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
 */
function mint() onlyCLevel external {
    _mint(1000000000000000000000000000);
}

/**
 * @dev Function to mint tokens: mint 1000000000000000000000000000 every times
 * @return A boolean that indicates if the operation was successful.
 */