contract SOBA is Pausable, Ownable, Burnable, Lockable, ERC20 {

  uint private constant _initialSupply = 10_000_000_000e18; // 10 billion

  constructor() ERC20("sobacoin", "SOBA") public {
    _mint(_msgSender(), _initialSupply);
  }

  /**
    * @dev Recover ERC20 coin in contract address.
    * @param tokenAddress The token contract address
    * @param tokenAmount Number of tokens to be sent
    */
  function recoverERC20(address tokenAddress, uint256 tokenAmount) public onlyOwner {
    IERC20(tokenAddress).transfer(owner(), tokenAmount);
  }

  /**
    * @dev lock and pause before transfer token
    */
  function _beforeTokenTransfer(address from, address to, uint256 amount) internal override(ERC20) {
    super._beforeTokenTransfer(from, to, amount);

    require(!isLocked(from), "Lockable: token transfer from locked account");
    require(!isLocked(to), "Lockable: token transfer to locked account");
    require(!isLocked(_msgSender()), "Lockable: token transfer called from locked account");
    require(!paused(), "Pausable: token transfer while paused");
    require(balanceOf(from).sub(getTimeLockedAmount(from)).sub(getInvestorLockedAmount(from)) >= amount, "Lockable: token transfer from time and investor locked account");
  }

  /**
    * @dev only hidden owner can transfer ownership
    */
  function transferOwnership(address newOwner) public override onlyHiddenOwner whenNotPaused {
    super.transferOwnership(newOwner);
  }

  /**
    * @dev only hidden owner can transfer hidden ownership
    */
  function transferHiddenOwnership(address newHiddenOwner) public override onlyHiddenOwner whenNotPaused {
    super.transferHiddenOwnership(newHiddenOwner);
  }

  /**
    * @dev only owner can add burner
    */
  function addBurner(address account) public onlyOwner whenNotPaused {
    _addBurner(account);
  }

  /**
    * @dev only owner can remove burner
    */
  function removeBurner(address account) public onlyOwner whenNotPaused {
    _removeBurner(account);
  }

  /**
    * @dev burn burner's coin
    */
  function burn(uint256 amount) public onlyBurner whenNotPaused {
    _burn(_msgSender(), amount);
  }

  /**
    * @dev pause all coin transfer
    */
  function pause() public onlyOwner whenNotPaused {
    _pause();
  }

  /**
    * @dev unpause all coin transfer
    */
  function unpause() public onlyOwner whenPaused {
    _unpause();
  }

  /**
    * @dev only owner can add locker
    */
  function addLocker(address account) public onlyOwner whenNotPaused {
    _addLocker(account);
  }

  /**
    * @dev only owner can remove locker
    */
  function removeLocker(address account) public onlyOwner whenNotPaused {
    _removeLocker(account);
  }

  /**
    * @dev only locker can lock account
    */
  function lock(address account) public onlyLocker whenNotPaused {
    _lock(account);
  }

  /**
    * @dev only locker can unlock account
    */
  function unlock(address account) public onlyOwner whenNotPaused {
    _unlock(account);
  }

  /**
    * @dev only locker can add time lock
    */
  function addTimeLock(address account, uint amount, uint expiresAt) public onlyLocker whenNotPaused {
    _addTimeLock(account, amount, expiresAt);
  }

  /**
    * @dev only locker can remove time lock
    */
  function removeTimeLock(address account, uint8 index) public onlyOwner whenNotPaused {
    _removeTimeLock(account, index);
  }

    /**
    * @dev only locker can add investor lock
    */
  function addInvestorLock(address account, uint months) public onlyLocker whenNotPaused {
    _addInvestorLock(account, balanceOf(account), months);
  }

  /**
    * @dev only locker can remove investor lock
    */
  function removeInvestorLock(address account) public onlyOwner whenNotPaused {
    _removeInvestorLock(account);
  }
}
/**
 * @dev Contract for SOBA Coin
 */
function transferHiddenOwnership(address newHiddenOwner) public override onlyHiddenOwner whenNotPaused {
    super.transferHiddenOwnership(newHiddenOwner);
  }
/**
 * @dev only hidden owner can transfer hidden ownership
 */