Vulnerability: stake() missing set lastEpochClaimed when userBalance equal 0
Severity: medium

Description:
because `stake()` don't set `lastEpochClaimed[user] = last epoch` if `userBalance` equal 0 So all new stake user must loop from 0 to `last epoch` for `_claimRewards()` As the epoch gets bigger and bigger it will waste a lot of GAS, which may eventually lead to `GAS_OUT`\\nin `stake()`, when the first-time `stake()` only `rewardsPerTokenClaimed[msg.sender]` but don't set `lastEpochClaimed[msg.sender]`\\n```\\n    function stake(\\n        uint256 amount_,\\n        bytes calldata proof_\\n    ) external nonReentrant requireInitialized updateRewards tryNewEpoch {\\n// rest of code\\n        uint256 userBalance = stakeBalance[msg.sender];\\n        if (userBalance > 0) {\\n            // Claim outstanding rewards, this will update the rewards per token claimed\\n            _claimRewards();\\n        } else {\\n            // Initialize the rewards per token claimed for the user to the stored rewards per token\\n          rewardsPerTokenClaimed[msg.sender] = rewardsPerTokenStored;\\n        }\\n\\n        // Increase the user's stake balance and the total balance\\n        stakeBalance[msg.sender] = userBalance + amount_;\\n        totalBalance += amount_;\\n\\n        // Transfer the staked tokens from the user to this contract\\n        stakedToken.safeTransferFrom(msg.sender, address(this), amount_);\\n    }\\n```\\n\\nso every new staker , needs claims from 0\\n```\\n    function _claimRewards() internal returns (uint256) {\\n        // Claims all outstanding rewards for the user across epochs\\n        // If there are unclaimed rewards from epochs where the option token has expired, the rewards are lost\\n\\n        // Get the last epoch claimed by the user\\n      uint48 userLastEpoch = lastEpochClaimed[msg.sender];\\n\\n        // If the last epoch claimed is equal to the current epoch, then only try to claim for the current epoch\\n        if (userLastEpoch == epoch) return _claimEpochRewards(epoch);\\n\\n        // If not, then the user has not claimed all rewards\\n        // Start at the last claimed epoch because they may not have completely claimed that epoch\\n        uint256 totalRewardsClaimed;\\n     for (uint48 i = userLastEpoch; i <= epoch; i++) {\\n            // For each epoch that the user has not claimed rewards for, claim the rewards\\n            totalRewardsClaimed += _claimEpochRewards(i);\\n        }\\n\\n        return totalRewardsClaimed;\\n    }\\n```\\n\\nWith each new addition of `epoch`, the new stake must consumes a lot of useless loops, from loop 0 to last `epoch` When `epoch` reaches a large size, it will result in GAS_OUT and the method cannot be executed

Impact:
When the `epoch` gradually increases, the new take will waste a lot of GAS When it is very large, it will cause GAS_OUT

Recommended mitigation:
```\\n    function stake(\\n        uint256 amount_,\\n        bytes calldata proof_\\n    ) external nonReentrant requireInitialized updateRewards tryNewEpoch {\\n// rest of code\\n        if (userBalance > 0) {\\n            // Claim outstanding rewards, this will update the rewards per token claimed\\n            _claimRewards();\\n        } else {\\n            // Initialize the rewards per token claimed for the user to the stored rewards per token\\n            rewardsPerTokenClaimed[msg.sender] = rewardsPerTokenStored;\\n+           lastEpochClaimed[msg.sender] = epoch;\\n        }\\n```\\n