Wrong accounting of user's holdings allows theft of reward
In `deposit()`, `withdraw()` and `withdrawProfit()`, `rewarder.onReward()` is called for reward bookkeeping. It will transfer previous eligible rewards and update the current amount user has:\\n```\\n      user.amount = _amt;\\n      user.rewardDebt = (_amt * pool.accRewardPerShare) / ACC_TOKEN_PRECISION;\\n      user.rewardsOwed = rewardsOwed;\\n```\\n\\nIn `withdraw()`, there is a critical issue where `onReward()` is called too early:\\n```\\n      // Update rewarder for this user\\n          if (address(rewarder) != address(0)) {\\n      rewarder.onReward(0, msg.sender, msg.sender, pending, user.amount);\\n      }\\n      // Burn baby burn\\n            _burn(msg.sender, _shares);\\n      // User accounting\\n                uint256 userAmount = balanceOf(msg.sender);\\n      // - Underlying (Frontend ONLY)\\n            if (userAmount == 0) {\\n               user.amount = 0;\\n         } else {\\n            user.amount -= r;\\n         }\\n```\\n\\nThe new _amt which will be stored in reward contract's user.amount is vault's user.amount, before decrementing the withdrawn amount. Therefore, the withdrawn amount is still gaining rewards even though it's no longer in the contract. Effectively it is stealing the rewards of others, leading to reward insolvency. In order to exploit this flaw, attacker will deposit a larger amount and immediately withdraw it, except for one wei. When they would like to receive the rewards accrued for others, they will withdraw the remaining wei, which will trigger `onReward()`, which will calculate and send pending awards for the previously withdrawn amount.
Move the `onReward()` call to after user.amount is updated.
```\\n      user.amount = _amt;\\n      user.rewardDebt = (_amt * pool.accRewardPerShare) / ACC_TOKEN_PRECISION;\\n      user.rewardsOwed = rewardsOwed;\\n```\\n