contract TokenBase is StandardToken, TransferState, BulkTransfer, Reclaimable, BurnableToken, CustomLockable {
  //solhint-disable
  uint8 public constant decimals = 18;
  string public constant name = "xCrypt Token";
  string public constant symbol = "XCT";
  //solhint-enable

  uint256 internal constant MILLION = 1000000 * 1 ether;
  uint256 public constant MAX_SUPPLY = 200 * MILLION;
  uint256 public constant INITIAL_SUPPLY = 130 * MILLION;

  event Mint(address indexed to, uint256 amount);

  constructor() public {
    mintTokens(msg.sender, INITIAL_SUPPLY);
  }

  ///@notice Transfers the specified value of XCT tokens to the destination address.
  //Transfers can only happen when the transfer state is enabled.
  //Transfer state can only be enabled after the end of the crowdsale.
  ///@dev This function is overridden to leverage transfer state and lockable feature.
  ///@param _to The destination wallet address to transfer funds to.
  ///@param _value The amount of tokens to send to the destination address.
  function transfer(address _to, uint256 _value)
  public
  canTransfer(msg.sender)
  revertIfLocked(msg.sender)
  returns(bool) {
    require(_to != address(0), "Invalid address.");
    return super.transfer(_to, _value);
  }

  ///@notice Transfers tokens from a specified wallet address.
  ///@dev This function is overridden to leverage transfer state and lockable feature.
  ///@param _from The address to transfer funds from.
  ///@param _to The address to transfer funds to.
  ///@param _value The amount of tokens to transfer.
  function transferFrom(address _from, address _to, uint256 _value)
  public
  canTransfer(_from)
  revertIfLocked(_from)
  returns(bool) {
    require(_to != address(0), "Invalid address.");
    return super.transferFrom(_from, _to, _value);
  }

  ///@notice Approves a wallet address to spend on behalf of the sender.
  ///@dev This function is overridden to leverage transfer state and lockable feature.
  ///@param _spender The address which is approved to spend on behalf of the sender.
  ///@param _value The amount of tokens approve to spend.
  function approve(address _spender, uint256 _value)
  public
  canTransfer(msg.sender)
  revertIfLocked(msg.sender)
  returns(bool) {
    require(_spender != address(0), "Invalid address.");
    return super.approve(_spender, _value);
  }

  ///@notice Increases the approval of the spender.
  ///@dev This function is overridden to leverage transfer state and lockable feature.
  ///@param _spender The address which is approved to spend on behalf of the sender.
  ///@param _addedValue The added amount of tokens approved to spend.
  function increaseApproval(address _spender, uint256 _addedValue)
  public
  canTransfer(msg.sender)
  revertIfLocked(msg.sender)
  returns(bool) {
    require(_spender != address(0), "Invalid address.");
    return super.increaseApproval(_spender, _addedValue);
  }

  ///@notice Decreases the approval of the spender.
  ///@dev This function is overridden to leverage transfer state and lockable feature.
  ///@param _spender The address of the spender to decrease the allocation from.
  ///@param _subtractedValue The amount of tokens to subtract from the approved allocation.
  function decreaseApproval(address _spender, uint256 _subtractedValue)
  public
  canTransfer(msg.sender)
  revertIfLocked(msg.sender)
  returns(bool) {
    require(_spender != address(0), "Invalid address.");
    return super.decreaseApproval(_spender, _subtractedValue);
  }

  ///@notice Burns the coins held by the sender.
  ///@param _value The amount of coins to burn.
  ///@dev This function is overridden to leverage Pausable feature.
  function burn(uint256 _value) public whenNotPaused {
    super.burn(_value);
  }

  ///@notice Mints the supplied value of the tokens to the destination address.
  //Minting cannot be performed any further once the maximum supply is reached.
  //This function cannot be used by anyone except for this contract.
  ///@param _to The address which will receive the minted tokens.
  ///@param _value The amount of tokens to mint.
  function mintTokens(address _to, uint _value) internal returns(bool) {
    require(_to != address(0), "Invalid address.");
    require(totalSupply_.add(_value) <= MAX_SUPPLY, "Sorry but the total supply can't exceed the maximum supply.");

    balances[_to] = balances[_to].add(_value);
    totalSupply_ = totalSupply_.add(_value);

    emit Transfer(address(0), _to, _value);
    emit Mint(_to, _value);

    return true;
  }
}
///@title xCrypt Token Base Contract
///@author Binod Nirvan
///@notice XCRYPT is the first crypto ecosystem with a high added value
///with the heart in its exchange: Hybrid, ready for STO
///and for a marketplace made for the ERC721. We created this
///end to end system which includes a Debit Card
///and a Social Media Trading system which is
///an advanced investment solution, which enables trading
///on one account managed by a skillfull and experienced trader
///using his own funds and joint funds invested by other traders
///in his SMT account. This ecosystem is made to be at the same level
///as the world’s big players, and even surpass them, for we are already
///suitable in this field’s future.
function decreaseApproval(address _spender, uint256 _subtractedValue)
public
canTransfer(msg.sender)
revertIfLocked(msg.sender)
returns(bool) {
  require(_spender != address(0), "Invalid address.");
  return super.decreaseApproval(_spender, _subtractedValue);
}

///@notice Decreases the approval of the spender.
///@dev This function is overridden to leverage transfer state and lockable feature.
///@param _spender The address of the spender to decrease the allocation from.
///@param _subtractedValue The amount of tokens to subtract from the approved allocation.