Skip to content

Commit

Permalink
Document the safe reward notifier requirements in UniStaker comments
Browse files Browse the repository at this point in the history
  • Loading branch information
apbendi committed Feb 21, 2024
1 parent e698ffc commit 074018f
Showing 1 changed file with 18 additions and 2 deletions.
20 changes: 18 additions & 2 deletions src/UniStaker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -550,9 +550,19 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces {
}

/// @notice Called by an authorized rewards notifier to alert the staking contract that a new
/// reward has been transferred to it. Note the reward must already have been transferred to this
/// staking contract before the rewards notifier calls this method.
/// reward has been transferred to it. It is assumed that the reward has already been
/// transferred to this staking contract before the rewards notifier calls this method.
/// @param _amount Quantity of reward tokens the staking contract is being notified of.
/// @dev It is critical that only well behaved contracts are approved by the admin to call this
/// method, for two reasons.
///
/// 1. A misbehaving contract could grief stakers by frequently notifying of tiny rewards,
/// continuously stretching out the time duration over which real rewards are distributed.
/// It is required that reward notifiers supply reasonable rewards at reasonable intervals.
// 2. A misbehaving contract could falsely notify the contract of rewards that were not actually
/// distributed, creating a shortfall for those claiming their rewards after others. It is
/// required that a notifier contract always transfers the `_amount` to this contract before
/// calling this method.
function notifyRewardAmount(uint256 _amount) external {
if (!isRewardNotifier[msg.sender]) revert UniStaker__Unauthorized("not notifier", msg.sender);

Expand All @@ -571,6 +581,12 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces {
lastCheckpointTime = block.timestamp;

if ((scaledRewardRate / SCALE_FACTOR) == 0) revert UniStaker__InvalidRewardRate();

// This check cannot _guarantee_ sufficient rewards have been transferred to the contract,
// because it cannot isolate the unclaimed rewards owed to stakers left in the balance. While
// this check is useful for preventing degenerate cases, it is not sufficient. Therefore, it is
// critical that only safe reward notifier contracts are approved to call this method by the
// admin.
if (
(scaledRewardRate * REWARD_DURATION) > (REWARD_TOKEN.balanceOf(address(this)) * SCALE_FACTOR)
) revert UniStaker__InsufficientRewardBalance();
Expand Down

0 comments on commit 074018f

Please sign in to comment.