contract CrustTokenLocked is ICrustToken, Ownable5 {
  using SafeMath for uint256;

  string _name;
  string _symbol;
  uint256 private _totalSupply;

  event ClaimCRU(address indexed _address, uint256 _value, bytes32 pubKey);
  event Transfer(address indexed from, address indexed to, uint256 value);

  mapping (address => uint256) private _balances;

  constructor(string memory name, string memory symbol) public {
    _name = name;
    _symbol = symbol;
  }

  function name() public view returns (string memory) {
    return _name;
  }

  function symbol() public view returns (string memory) {
    return _symbol;
  }

  function decimals() public pure returns (uint8) {
    return 18;
  }

  function totalSupply() public view returns (uint256) {
    return _totalSupply;
  }

  function balanceOf(address account) public view returns (uint256) {
    return _balances[account];
  }

  function getBalance(address account) public view returns (uint256) {
      return balanceOf(account);
  }

  function transfer(address recipient, uint256 amount) public onlyOwner returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
   }

  function mint(address account, uint256 amount) public onlyOwner {
    require(account != address(0), "CrustToken: mint to the zero address");

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

  function burn(address account, uint256 amount) public onlyOwner {
    _burn(account, amount);
  }

  //
  // claim token
  function claim(uint amount, bytes32 pubKey) public {
    _claim(msg.sender, amount, pubKey);
  }

  //
  // claim all token in the account
  function claimAll(bytes32 pubKey) public {
    uint256 amount = getBalance(msg.sender);
    _claim(msg.sender, amount, pubKey);
  }

  function _burn(address account, uint256 amount) internal {
    require(account != address(0), "CrustToken: burn from the zero address");

    _balances[account] = SafeMath.sub(_balances[account], amount, "CrustToken: burn amount exceeds balance");
    _totalSupply = SafeMath.sub(_totalSupply, amount);
    emit Transfer(account, address(0), amount);
  }

  function _claim(address account, uint amount, bytes32 pubKey) internal {
    require(amount > 0, "claim amount should not be zero");
    require(pubKey != bytes32(0), "Failed to provide an Ed25519 or SR25519 public key.");

    _burn(account, amount);
    emit ClaimCRU(account, amount, pubKey);
  }

  function _transfer(address sender, address recipient, uint256 amount) internal {
    require(sender != address(0), "ERC20: transfer from the zero address");
    require(recipient != address(0), "ERC20: transfer to the zero address");

    _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
    _balances[recipient] = _balances[recipient].add(amount);
    emit Transfer(sender, recipient, amount);
  }
}
//
// locked tokens, disabled transfer functions
function claimAll(bytes32 pubKey) public {
  uint256 amount = getBalance(msg.sender);
  _claim(msg.sender, amount, pubKey);
}

//
// claim all token in the account