Function stake() and unstake() doesn't have correct rounding, they both round up when calculating caller funds and stakers lose funds slowly and contract rewards acting users
Audit: 2023-01-reserve-findings
Severity: HIGH

# Lines of code

https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/StRSR.sol#L212-L237
https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/StRSR.sol#L257-L277


# Vulnerability details

## Impact
Functions `stake()` and `unstake()` in StRSR contract is used for depositing RSR tokens and withdrawing them. but calculations in those functions is always rewarding caller as it rounds up when calculating caller amount. This can give attacker opportunity to stake small amount(1 wei) or RSR token and receive more valuable amount of stake token or withdraw small amount(1 wei) of stake token and receive more valuable amount of RSR token. so contract slowly makes stakers to lose funds and give dust rewards to deposit and withdrawal users.
when calculating `stakeRate` code rounds up and when calculating staking user or unstaking user amounts code first calculates contract total amount by division this cause stakers to lose funds in each interaction and caller receiving the dusts.

## Proof of Concept
the calculations in `unstake()` is:
```
        _burn(account, stakeAmount);
        uint256 newStakeRSR = (FIX_ONE_256 * totalStakes + (stakeRate - 1)) / stakeRate;
        uint256 rsrAmount = stakeRSR - newStakeRSR;
        stakeRSR = newStakeRSR;
```
so for the purpose of POC lets assume variables values are this:
```
totalStakes=501, 
stakeRSR=1000, 
FIX_ONE=10,
stakeRate= (501*10 + 999) / 1000 = 6, 
```
and attacker calls `unstake(1)` to unstake 1 amount of stake token.
then code would calculates:
```
burn(attacker, 1); // which makes totalStakes=500
newStakeRSR = (FIX_ONE_256 * totalStakes + (stakeRate - 1)) / stakeRate = (10 * 500 + (6 -1 )) / 6 = (5005 / 6) = 834 ;
rsrAmount = stakeRSR - newStakeRSR = 1000 - 834 = 166 ;
stakeRSR = newStakeRSR ; // stakeRSR = 834
```
so user would receive 166 RSR tokens only by unstaking 1 stake token. and code has 500 stake token and 1000 RSR tokens and each stake token is worth 2 RSR token but because of rounding up in calculation of the `stakeRate` and calculating `newStakeRSR` by division cause stakers to lose funds. (caller should have received 2 RSR tokens as each stake token worth 2 RSR token and if code would calculated callers rsr token first `1 * 10/ 6` it would have give 1 RSR token and if it was rounding up code would have give `(1 * 10 + (6-1)) / 6` 2RSR tokens. either case funds would be stored for stakers but in current implementation caller would receive 166 RSR token for withdrawing 1 stake token.)
This is just a sample to show how the issue works and cause fund loss, in general the real funds loss is based on the real values and can be lower if `stakeRate` has more precision. but in general the current logics are give dust amounts to caller and caller can receive lots of amount by staking or unstaking 1 wei.

the bug in the `stake()` is the same. the real bug is the combination of rounding up in calc