MEDIUM severity: The vulnerability in the Vault Share/Strategy Token Calculation allows an early user to manipulate t. The vulnerability in the Vault Share/Strategy Token Calculation allows an early user to manipulate the price per share and profit from late users' deposits due to the precision loss caused by the large value of the price per share. This issue affects MetaStable2 and Boosted3 balancer leverage vaults...

Vulnerable code:
```\nstrategyToken = (totalBPTHeld == 0)? bptClaim : (bptClaim * totalStrategyToken) / totalBPTHeld\n```\n```\nFile: StrategyUtils.sol\n\n@notice Converts BPT to strategy tokens\nfunction _convertBPTClaimToStrategyTokens(StrategyContext memory context, uint256 bptClaim)\n    internal\n    pure\n    returns (uint256 strategyTokenAmount)\n{\n    if (context.totalBPTHeld == 0) {\n        return (bptClaim * uint256(Constants.INTERNAL_TOKEN_PRECISION)) / \n            BalancerConstants.BALANCER_PRECISION;\n    }\n\n    strategyTokenAmount = (bptClaim * context.vaultState.totalStrategyTokenGlobal) / context.totalBPTHeld;\n}\n```\n```\nstrategyToken = (bptClaim * totalStrategyToken) / totalBPTHeld\n\nstrategy_token = (19999 * 1) / 10000\nstrategy_token = 1\n```\n```\nbptReceived = (strategyToken * totalBPTHeld) / totalStrategyToken\nbptReceived = (strategyToken * 29999) / totalStrategyToken\n```\n```\nstrategyToken = (bptClaim * totalStrategyToken) / totalBPTHeld\nstrategy_token = (9999 * totalStrategyToken) / 10000\n```\n```\nFile: PoolMixin.sol\n\nfunction _baseStrategyContext() internal view returns (StrategyContext memory) {\n    return StrategyContext({\n        totalBPTHeld: _bptHeld(),\n        settlementPeriodInSeconds: SETTLEMENT_PERIOD_IN_SECONDS,\n        tradingModule: TRADING_MODULE,\n        vaultSettings: BalancerVaultStorage.getStrategyVaultSettings(),\n        vaultState: BalancerVaultStorage.getStrategyVaultState(),\n        feeReceiver: FEE_RECEIVER\n    });\n```\n```\nFile: PoolMixin.sol\n\nfunction _bptHeld() internal view returns (uint256) {\n    return AURA_REWARD_POOL.balanceOf(address(this));\n}\n```\n```\nFile: BaseRewardPool4626.sol\n\nfunction balanceOf(address account) public view override(BaseRewardPool, IERC20) returns (uint256) {\n    return BaseRewardPool.balanceOf(account);\n}\n```\n```\nfunction balanceOf(address account) public view virtual returns (uint256) {\n    return _balances[account];\n}\n```\n```\nFile: BaseRewardPool4626.sol\n\nfunction deposit(uint256 assets, address receiver) public virtual override nonReentrant returns (uint256) {\n    IERC20(asset).safeTransferFrom(msg.sender, address(this), assets);\n\n    uint256 balBefore = stakingToken.balanceOf(address(this));\n    IDeposit(operator).deposit(pid, assets, false);\n    uint256 balAfter = stakingToken.balanceOf(address(this));\n\n    require(balAfter.sub(balBefore) >= assets, "!deposit");\n\n    _processStake(assets, receiver);\n\n    emit Deposit(msg.sender, receiver, assets, assets);\n    emit Staked(receiver, assets);\n    return assets;\n}\n```\n```\n/**\n* @dev Generic internal staking function that basically does 3 things: update rewards based\n*      on previous balance, trigger also on any child contracts, then update balances.\n* @param _amount    Units to add to the users balance\n* @param _receiver  Address of user who will receive the stake\n*/\nfunction _processStake(uint256 _amount, address _receiver) internal updateReward(_receiver) {\n    require(_amount > 0, 'RewardPool : Cannot stake 0');\n\n    for (uint i = 0; i < extraRewards.length; i++) {\n        IRewards(extraRewards[i]).stake(_receiver, _amount);\n    }\n\n    _totalSupply = _totalSupply.add(_amount);\n    _balances[_receiver] = _balances[_receiver].add(_amount);\n}\n```