rewarding is not started after StakingRewards contract deployment and there is no specific time set for contract start time of rewarding, users stacked their funds has no way knowing when is rewarding is going to be started #503
after StakingRewards the constructor() logic set value for rewardRate and rewardsDuration but rewarding is not started for stackers and users has no way to find out when is rewarding going to be started. only reward Distributer can start rewarding process immediately by calling notifyRewards() and some functions like getRewardForDuration() return wrong values when rewarding is not started. this behavior can cause users to stake their funds without getting any rewards and knowing when they are gonna get rewards.
Proof of Concept
This is constructor() and notifyRewards() codes in StakingRewards contract:
function notifyRewardAmount(uint256 reward)
external
override
onlyRewardsDistribution
updateReward(address(0))
{
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(rewardsDuration);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(rewardsDuration);
}
// Ensure the provided reward amount is not more than the balance in the contract.
// This keeps the reward rate in the right range, preventing overflows due to
// very high values of rewardRate in the earned and rewardsPerToken functions;
// Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
uint256 balance = rewardsToken.balanceOf(address(this));
require(
rewardRate <= balance.div(rewardsDuration),
"Provided reward too high"
);
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(rewardsDuration);
emit RewardAdded(reward);
}
constructor(
address _owner,
address _rewardsDistribution,
address _rewardsToken,
address _stakingToken,
uint256 _epochEnd,
uint256 _rewardsDuration,
uint256 _rewardRate
) Owned(_owner) {
rewardsToken = ERC20(_rewardsToken);
stakingToken = IERC1155(_stakingToken);
rewardsDistribution = _rewardsDistribution;
id = _epochEnd;
rewardsDuration = _rewardsDuration;
rewardRate = _rewardRate;
}
As you can see constructor set value for rewardRate and rewardsDuration but the rewarding is not started after deployment and the rewardRate is some fake value which can cause users to get confused. rewarding only starts by calling notifyRewards() which sets value for lastUpdateTime and rewardsDuration that make rewards to be calculated and rewarding to be started.
so Users don't know when rewarding is going to be started and if they don't stake their funds they would lose some early time of staking when rewarding starts and if they stake early their funds would be idle for nothing.
Tools Used
VIM
Recommended Mitigation Steps
add some start time to contract or create time-lock mechanism for notifyRewards() functions.
Lines of code
https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/rewards/StakingRewards.sol#L183-L210 https://github.com/code-423n4/2022-09-y2k-finance/blob/2175c044af98509261e4147edeb48e1036773771/src/rewards/StakingRewards.sol#L72-L87
Vulnerability details
Impact
after
StakingRewards
theconstructor()
logic set value forrewardRate
andrewardsDuration
but rewarding is not started for stackers and users has no way to find out when is rewarding going to be started. only reward Distributer can start rewarding process immediately by callingnotifyRewards()
and some functions likegetRewardForDuration()
return wrong values when rewarding is not started. this behavior can cause users to stake their funds without getting any rewards and knowing when they are gonna get rewards.Proof of Concept
This is
constructor()
andnotifyRewards()
codes inStakingRewards
contract:As you can see constructor set value for
rewardRate
andrewardsDuration
but the rewarding is not started after deployment and therewardRate
is some fake value which can cause users to get confused. rewarding only starts by callingnotifyRewards()
which sets value forlastUpdateTime
andrewardsDuration
that make rewards to be calculated and rewarding to be started. so Users don't know when rewarding is going to be started and if they don't stake their funds they would lose some early time of staking when rewarding starts and if they stake early their funds would be idle for nothing.Tools Used
VIM
Recommended Mitigation Steps
add some start time to contract or create time-lock mechanism for
notifyRewards()
functions.