contract PBKtoken is MintableToken, PausableToken, BurnableToken {
  string public name = "PlasmaBank token"; 
  string public symbol = "PBK";
  uint public decimals = 2;

  /// @dev whether an address is permitted to perform burn operations.
  mapping(address => bool) public isBurner;

  event ReceivedEther(address from, uint256 value);
  event WithdrewEther(address to, uint256 value);

  address PlasmaPrivateTokenSale            = 0xec0767B180C05B261A23744cCF8EB89b677dFeE1;
  address PlasmaPreTokenSaleReserve         = 0x2910dB084a467131C121626987b3F8b69ebaE82A;
  address PlasmaTokenSaleReserve            = 0x516154A8e9d365dC976f977E6815710b94B8C9f6;
  address PlasmaReserveForBonus             = 0x47e061914750f0Ee7C7675da0D62A59e2bd27dc4;
  address PlasmaReserveForBounty            = 0xdbf81Af07e37ec855653de1dB152E578d847f215;
  address PlasmaReserveForEarlyBirds        = 0x831360b8Dd93692d1A0Bdf7fdE8C037BaB1CE631;
  address PlasmaTeamOptionsReserveAddress   = 0x04D20280B1E870688B7552E14171923215D3411C;
  address PlasmaFrozenForInstitutionalSales = 0x88bF0Ae762B801943190D1B7D757103BA9Dd6eAb;
  address PlasmaReserveForAdvisors          = 0x6Df994BdCA65f6bdAb66c72cd3fE3666cc183E37;
  address PlasmaFoundationReserve           = 0xF0dbBDb93344Bc679F8f0CffAE187D324917F44b;
  address PlasmaFrozenForTopManagement      = 0x5ed22d37BB1A16a15E9a2dD6F46b9C891164916B;
  address PlasmaFrozenForTokenSale2020      = 0x67F585f3EB7363E26744aA19E8f217D70e7E0001;

  function PBKtoken() public {
    mint(PlasmaPrivateTokenSale,            500000000 * (10 ** decimals));
    mint(PlasmaPreTokenSaleReserve,         300000000 * (10 ** decimals));
    mint(PlasmaTokenSaleReserve,            3200000000 * (10 ** decimals));
    mint(PlasmaReserveForBonus,             100000000 * (10 ** decimals));
    mint(PlasmaReserveForBounty,            100000000 * (10 ** decimals));
    mint(PlasmaReserveForEarlyBirds,        200000000 * (10 ** decimals));
    mint(PlasmaTeamOptionsReserveAddress,   800000000 * (10 ** decimals));
    mint(PlasmaFrozenForInstitutionalSales, 500000000 * (10 ** decimals));
    mint(PlasmaReserveForAdvisors,          300000000 * (10 ** decimals));
    mint(PlasmaFoundationReserve,           1000000000 * (10 ** decimals));
    mint(PlasmaFrozenForTopManagement,      1500000000 * (10 ** decimals));
    mint(PlasmaFrozenForTokenSale2020,      1500000000 * (10 ** decimals));

    assert(totalSupply_ == 10000000000 * (10 ** decimals));
    
    finishMinting();
  }

  function transferTimelocked(address _to, uint256 _amount, uint256 _releaseTime) public
    returns (TokenTimelock) {

    TokenTimelock timelock = new TokenTimelock(this, _to, _releaseTime);
    transferFrom(msg.sender, timelock, _amount);

    return timelock;
  }

  /**
   * @dev Grant or remove burn permissions. Only owner can do that!
   */
  function grantBurner(address _burner, bool _value) public onlyOwner {
      isBurner[_burner] = _value;
  }

  /**
   * @dev Throws if called by any account other than the burner.
   */
  modifier onlyBurner() {
      require(isBurner[msg.sender]);
      _;
  }

  /**
   * @dev Burns a specific amount of tokens.
   * Only an address listed in `isBurner` can do this.
   * @param _value The amount of token to be burned.
   */
  function burn(uint256 _value) public onlyBurner {
      super.burn(_value);
  }

  // transfer balance to owner
  function withdrawEther(uint256 amount) public onlyOwner {
    owner.transfer(amount);
    WithdrewEther(msg.sender, amount);
  }

  // can accept ether
  function() payable private {
    ReceivedEther(msg.sender, msg.value);
  }
}
function grantBurner(address _burner, bool _value) public onlyOwner {
    isBurner[_burner] = _value;
}

/**
 * @dev Grant or remove burn permissions. Only owner can do that!
 */