contract TokenStore is ITokenStore, ITokenStoreGov, Operator {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    /* ================= STATES ================= */

    address public override token;

    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;

    bool public emergency = false;

    constructor(address _token) Operator() {
        token = _token;
    }

    /* ================= GOV - OWNER ONLY ================= */

    /**
     * @dev CAUTION: DO NOT USE IN NORMAL SITUATION
     * @notice Enable emergency withdraw
     */
    function reportEmergency() public override onlyOwner {
        emergency = true;
        emit EmergencyReported(_msgSender());
    }

    /**
     * @dev CAUTION: DO NOT USE IN NORMAL SITUATION
     * @notice Disable emergency withdraw
     */
    function resolveEmergency() public override onlyOwner {
        emergency = false;
        emit EmergencyResolved(_msgSender());
    }

    /**
     * @dev CAUTION: MUST USE 1:1 TOKEN MIGRATION
     */
    function setToken(address newToken) public override onlyOwner {
        address oldToken = token;
        token = newToken;
        IERC20(newToken).safeTransferFrom(
            msg.sender,
            address(this),
            totalSupply()
        );
        emit TokenChanged(_msgSender(), newToken, oldToken);
    }

    /* ================= CALLS - ANYONE ================= */

    /**
     * @return total staked token amount
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @param _owner staker address
     * @return staked amount of user
     */
    function balanceOf(address _owner) public view override returns (uint256) {
        return _balances[_owner];
    }

    /* ================= TXNS - OPERATOR ONLY ================= */

    /**
     * @param _owner stake address
     * @param _amount stake amount
     */
    function deposit(address _owner, uint256 _amount)
        public
        override
        onlyOperator
    {
        _totalSupply = _totalSupply.add(_amount);
        _balances[_owner] = _balances[_owner].add(_amount);
        IERC20(token).safeTransferFrom(_msgSender(), address(this), _amount);

        emit Deposit(_msgSender(), _owner, _amount);
    }

    /**
     * @param _owner stake address
     * @param _amount stake amount
     */
    function withdraw(address _owner, uint256 _amount)
        public
        override
        onlyOperator
    {
        _totalSupply = _totalSupply.sub(_amount);
        _balances[_owner] = _balances[_owner].sub(_amount);
        IERC20(token).safeTransfer(_msgSender(), _amount);

        emit Withdraw(_msgSender(), _owner, _amount);
    }

    /**
     * @notice Anyone can withdraw its balance even if is not the operator
     */
    function emergencyWithdraw() public override {
        require(emergency, 'TokenStore: not in emergency');

        uint256 balance = _balances[_msgSender()];
        _balances[_msgSender()] = 0;
        IERC20(token).safeTransfer(_msgSender(), balance);

        emit Withdraw(_msgSender(), _msgSender(), balance);
    }
}
function totalSupply() public view override returns (uint256) {
    return _totalSupply;
}

/**
 * @return total staked token amount
 */