Vulnerability: RocketRewardPool - Unpredictable staking rewards as stake can be added just before claiming and rewards may be paid to to operators that do not provide a service to the system  Partially Addressed
Severity: high

Description:
Nodes/TrustedNodes earn rewards based on the current share of the effective RPL stake provided backing the number of Minipools they run. The reward is paid out regardless of when the effective node stake was provided, as long as it is present just before the call to `claim()`. This means the reward does not take into account how long the stake was provided. The effective RPL stake is the nodes RPL stake capped at a maximum of `halfDepositUserAmount * 150% * nr_of_minipools(node) / RPLPrice`. If the node does not run any Minipools, the effective RPL stake is zero.\\nSince effective stake can be added just before calling the `claim()` method (effectively trying to get a reward for a period that passed without RPL being staked for the full duration), this might create an unpredictable outcome for other participants, as adding significant stake (requires creating Minipools and staking the max per pool; the stake is locked for at least the duration of a reward period rpl.rewards.claim.period.blocks) shifts the shares users get for the fixed total amount of rewards. This can be unfair if the first users claimed their reward, and then someone is artificially inflating the total amount of shares by adding more stake to get a bigger part of the remaining reward. However, this comes at the cost of the registered node having to create more Minipools to stake more, requiring an initial deposit (16ETH, or 0ETH under certain circumstances for trusted nodes) by the actor attempting to get a larger share of the rewards. The risk of losing funds for this actor, however, is rather low, as they can immediately `dissolve()` and `close()` the Minipool to refund their node deposit as `NETH` right after claiming the reward only losing the gas spent on the various transactions.\\nThis can be extended to a node operator creating a Minipool and staking the maximum amount before calling `claim` to remove the Minipool right after, freeing up the `ETH` that was locked in the Minipool until the next reward period starts. The node operator is not providing any service to the network, loses some value in `ETH` for gas but may compensate that with the RPL staking rewards. If the node amassed a significant amount of RPL stake, they might even try to flash-loan enough `ETH` to spawn Minipools to inflate their effective stake and earn most of the rewards to return the loan RPL profit.\\n```\\n-- reward period ends -- front-run other claimers to maximize profits\\n[create x minipools]\\n[stake to max effective RPL for amount of minipools; locked for 14 days]\\n[claim rewards for inflated effective RPL stake]\\n[dissolve(), close() minipools -> refund NETH]\\n[burn NETH for ETH]\\n// rest of code wait 14 days\\n[withdraw stake OR start again creating Minipools, claiming rewards while the Minipools are dissolved right after, freeing the ETH]\\n```\\n\\nBy staking just before claiming, the node effectively can earn rewards for 2 reward periods by only staking RPL for the duration of one period (claim the previous period, leave it in for 14 days, claim another period, withdraw).\\nThe stake can be withdrawn at the earliest 14 days after staking. However, it can be added back at any time, and the stake addition takes effect immediately. This allows for optimizing the staking reward as follows (assuming we front-run other claimers to maximize profits and perform all transactions in one block):\\n```\\n[stake max effective amount for the number of minipools]\\n[claim() to claim the previous period even though we did not provide any stake for the duration]\\n[optionally dissolve Minipools unlocking ETH]\\n-- stake is locked for at least 14 days --\\n-- 14 days forward - new reward period started --\\n[claim() the period]\\n[withdraw() (leaving min pool stake OR everything if we dissolve all the Minipool)]\\n[lend RPL to other platforms and earn interest]\\n-- 14 days forward -new reward period started --\\n[get RPL back from another platform]\\n[stake & create minipools to inflate effective stake]\\n[claim()]\\n[optionally dissolve Minipools to unlock node ETH]\\n-- stake is locked for at least 14 days --\\n-- 14 days forward - new reward period started --\\n[claim() the period]\\n[withdraw() (leaving min pool stake OR everything if we dissolve all the Minipools)]\\n[lend RPL to other platforms and earn interest]\\n// rest of code\\n```\\n\\nNote that `withdraw()` can be called right at the time the new reward period starts:\\n```\\nrequire(block.number.sub(getNodeRPLStakedBlock(msg.sender)) >= rocketDAOProtocolSettingsRewards.getRewardsClaimIntervalBlocks(), "The withdrawal cooldown period has not passed");\\n// Get & check node's current RPL stake\\n```\\n\\nA node may choose to register and stake some RPL to collect rewards but never actually provide registered node duties, e.g., operating a Minipool.\\nNode shares for a passed reward epoch are unpredictable as nodes may change their stake (adding) after/before users claim their rewards.\\nA node can maximize its rewards by adding stake just before claiming it\\nA node can stake to claim rewards, wait 14 days, withdraw, lend on a platform and return the stake in time to claim the next period.

Impact:

Recommended mitigation:
Review the incentive model for the RPL rewards. Consider adjusting it so that nodes that provide a service get a better share of the rewards. Consider accruing rewards for the duration the stake was provided instead of taking a snapshot whenever the node calls `claim()`. Require stake to be locked for > 14 days instead of >=14 days (withdraw()) or have users skip the first reward period after staking.