<!-- canonical: https://0xsimao.com/findings/metazero-ii-fees-rewards-reward-properly -->

# feesAccrued or staker principal may be sent as rewards if rewardRate and emissionEnd are not properly calculated

Crit/High · Three Sigma · Omnichain RWA tokenisation · 6th April, 2024

Finding 3S-MZ-H01 of the MetaZero Staking security review.

- Protocol: https://metazero.gg/
- Report: /reports/metazero-ii
- Codebase: https://github.com/0xsimao/stakingContract/tree/dffac73e838a9fbd12bed18e41b9799177bcde7f
- Source: https://cdn.sanity.io/files/qoqld077/production/3e07b0c2806b62578b8031e88c59bc5dbd38de1b.pdf

---

### Description

As emissionEnd and rewardRate can be freely set (although rewardRate only in the
constructor), if emissionEnd x rewardRate is bigger than the amount of tokens sent to
the staking contract, stakers may withdraw feesAccrued or other stakers' principal as
rewards.

### Recommendation

Limit the rewards to claim to IERC20(basicToken).balanceOf(address(this)) totalStaked - feesAccrued.
To simplify the logic, it might be easier to only unstake in function completeUnstake(), but
leave the rewards stored in stakers[msg.sender].reward to be claimed by calling
claimReward().
In claimReward(), instead of deleting staker.rewards, set it to staker.rewards =
staker.rewards - actuallyWithdrawnRewards.

### Status

Addressed in [#dffac73](https://github.com/metazerogg/stakingContract/blob/dffac73e838a9fbd12bed18e41b9799177bcde7f/src/StakingContract.sol).

---

Related findings:

- [`rewardData.releaseRate` is incorrectly calculated on `RewardsController::config()` when `block.timestamp > start` and `rewardData.lastConfig != rewardData.start`](https://0xsimao.com/findings/exactly-protocol-update-staking-contract-reward-release-rewards-timestamp): Exactly Protocol Update - Staking Contract
- [StakingPool is missing rewards distribution end logic](https://0xsimao.com/findings/spirit-protocol-staking-rewards-distribution-end): Spirit Protocol
- [Rewards are calculated as distributed even if there are no stakers, locking the rewards forever](https://0xsimao.com/findings/zivoe-rewards-distributed-stakers-locking): Zivoe
- [Wrong reward distribution between early and late depositors because of the late `syncRewards()` call in the cycle, `syncReward()` logic should be executed in each withdraw or deposits (without reverting)](https://0xsimao.com/findings/gogopool-reward-rewards-withdraw-deposits): GoGoPool
